diff options
Diffstat (limited to 'files/fr/learn/javascript')
43 files changed, 8911 insertions, 8779 deletions
diff --git a/files/fr/learn/javascript/asynchronous/async_await/index.md b/files/fr/learn/javascript/asynchronous/async_await/index.md index 5955c0f27f..a7578c08e1 100644 --- a/files/fr/learn/javascript/asynchronous/async_await/index.md +++ b/files/fr/learn/javascript/asynchronous/async_await/index.md @@ -13,17 +13,19 @@ tags: - await translation_of: Learn/JavaScript/Asynchronous/Async_await --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}</div> - -<p>Plus récemment, les <a href="/fr/docs/Web/JavaScript/Reference/Statements/async_function">fonctions async</a> et le mot-clé <code><a href="/fr/docs/Web/JavaScript/Reference/Operators/await">await</a></code> ont été ajoutés au langage JavaScript avec l'édition intitulée ECMAScript 2017. Ces fonctionnalités agissent essentiellement comme du sucre syntaxique sur les promesses, rendant le code asynchrone plus facile à écrire et à lire par la suite. Elles font en sorte que le code asynchrone ressemble davantage au code synchrone de la vieille école, et elles valent donc la peine d'être apprises. Cet article fournit les informations à connaître.</p> +Plus récemment, les [fonctions async](/fr/docs/Web/JavaScript/Reference/Statements/async_function) et le mot-clé [`await`](/fr/docs/Web/JavaScript/Reference/Operators/await) ont été ajoutés au langage JavaScript avec l'édition intitulée ECMAScript 2017. Ces fonctionnalités agissent essentiellement comme du sucre syntaxique sur les promesses, rendant le code asynchrone plus facile à écrire et à lire par la suite. Elles font en sorte que le code asynchrone ressemble davantage au code synchrone de la vieille école, et elles valent donc la peine d'être apprises. Cet article fournit les informations à connaître. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript, compréhension du code asynchrone en général et des promesses.</td> + <td> + Connaissances informatiques de base, compréhension raisonnable des + principes fondamentaux de JavaScript, compréhension du code asynchrone + en général et des promesses. + </td> </tr> <tr> <th scope="row">Objectif :</th> @@ -32,93 +34,110 @@ translation_of: Learn/JavaScript/Asynchronous/Async_await </tbody> </table> -<h2 id="the_basics_of_asyncawait">Les bases de async/await</h2> +## Les bases de async/await -<p>L'utilisation <code>async/await</code> dans votre code comporte deux parties.</p> +L'utilisation `async/await` dans votre code comporte deux parties. -<h3 id="the_async_keyword">Le mot-clé async</h3> +### Le mot-clé async -<p>Tout d'abord, nous avons le mot-clé <code>async</code>, que vous mettez devant une déclaration de fonction pour la transformer en une <a href="/fr/docs/Web/JavaScript/Reference/Statements/async_function">fonction asynchrone</a>. Une fonction asynchrone est une fonction qui saura réagir à une éventuelle utilisation du mot-clé <code>await</code> pour invoquer du code asynchrone.</p> +Tout d'abord, nous avons le mot-clé `async`, que vous mettez devant une déclaration de fonction pour la transformer en une [fonction asynchrone](/fr/docs/Web/JavaScript/Reference/Statements/async_function). Une fonction asynchrone est une fonction qui saura réagir à une éventuelle utilisation du mot-clé `await` pour invoquer du code asynchrone. -<p>Essayez de taper les lignes suivantes dans la console JS de votre navigateur :</p> +Essayez de taper les lignes suivantes dans la console JS de votre navigateur : -<pre class="brush: js">function hello() { return "Bonjour" }; -hello();</pre> +```js +function hello() { return "Bonjour" }; +hello(); +``` -<p>La fonction renvoie « Bonjour » — rien de spécial, n'est-ce pas ?</p> +La fonction renvoie « Bonjour » — rien de spécial, n'est-ce pas ? -<p>Mais que se passe-t-il si nous transformons cette fonction en une fonction asynchrone ? Essayez ce qui suit :</p> +Mais que se passe-t-il si nous transformons cette fonction en une fonction asynchrone ? Essayez ce qui suit : -<pre class="brush: js">async function hello() { return "Bonjour" }; -hello();</pre> +```js +async function hello() { return "Bonjour" }; +hello(); +``` -<p>Ah. L'invocation de la fonction renvoie maintenant une promesse. C'est l'une des caractéristiques des fonctions asynchrones - leurs valeurs de retour sont nécessairement converties en promesses.</p> +Ah. L'invocation de la fonction renvoie maintenant une promesse. C'est l'une des caractéristiques des fonctions asynchrones - leurs valeurs de retour sont nécessairement converties en promesses. -<p>Vous pouvez également créer une <a href="/fr/docs/Web/JavaScript/Reference/Operators/async_function">expression de fonction asynchrone</a>, comme suit :</p> +Vous pouvez également créer une [expression de fonction asynchrone](/fr/docs/Web/JavaScript/Reference/Operators/async_function), comme suit : -<pre class="brush: js">let hello = async function() { return "Bonjour" }; -hello();</pre> +```js +let hello = async function() { return "Bonjour" }; +hello(); +``` -<p>Et vous pouvez utiliser les fonctions fléchées :</p> +Et vous pouvez utiliser les fonctions fléchées : -<pre class="brush: js">let hello = async () => { return "Bonjour" };</pre> +```js +let hello = async () => { return "Bonjour" }; +``` -<p>Elles font toutes à peu près la même chose.</p> +Elles font toutes à peu près la même chose. -<p>Pour consommer réellement la valeur renvoyée lorsque la promesse se réalise, puisqu'elle renvoie une promesse, nous pourrions utiliser un bloc <code>.then()</code> :</p> +Pour consommer réellement la valeur renvoyée lorsque la promesse se réalise, puisqu'elle renvoie une promesse, nous pourrions utiliser un bloc `.then()` : -<pre class="brush: js">hello().then((value) => console.log(value));</pre> +```js +hello().then((value) => console.log(value)); +``` -<p>ou même simplement un raccourci tel que</p> +ou même simplement un raccourci tel que -<pre class="brush: js">hello().then(console.log);</pre> +```js +hello().then(console.log); +``` -<p>Comme nous l'avons vu dans l'article précédent.</p> +Comme nous l'avons vu dans l'article précédent. -<p>Ainsi, le mot-clé <code>async</code> est ajouté aux fonctions pour leur indiquer de retourner une promesse plutôt que de retourner directement la valeur.</p> +Ainsi, le mot-clé `async` est ajouté aux fonctions pour leur indiquer de retourner une promesse plutôt que de retourner directement la valeur. -<h3 id="the_await_keyword">Le mot-clé await</h3> +### Le mot-clé await -<p>L'avantage d'une fonction asynchrone ne devient apparent que lorsque vous la combinez avec le mot-clé <code>await</code>. <code>await</code> ne fonctionne qu'à l'intérieur de fonctions asynchrones dans du code JavaScript ordinaire, mais il peut être utilisé seul avec <a href="/fr/docs/Web/JavaScript/Guide/Modules">des modules JavaScript</a>.</p> +L'avantage d'une fonction asynchrone ne devient apparent que lorsque vous la combinez avec le mot-clé `await`. `await` ne fonctionne qu'à l'intérieur de fonctions asynchrones dans du code JavaScript ordinaire, mais il peut être utilisé seul avec [des modules JavaScript](/fr/docs/Web/JavaScript/Guide/Modules). -<p><code>await</code> peut être placé devant toute fonction asynchrone basée sur une promesse pour mettre en pause votre code sur cette ligne jusqu'à ce que la promesse se réalise, puis retourner la valeur résultante.</p> +`await` peut être placé devant toute fonction asynchrone basée sur une promesse pour mettre en pause votre code sur cette ligne jusqu'à ce que la promesse se réalise, puis retourner la valeur résultante. -<p>Vous pouvez utiliser <code>await</code> lors de l'appel de toute fonction qui renvoie une promesse, y compris les fonctions de l'API web.</p> +Vous pouvez utiliser `await` lors de l'appel de toute fonction qui renvoie une promesse, y compris les fonctions de l'API web. -<p>Voici un exemple trivial :</p> +Voici un exemple trivial : -<pre class="brush: js">async function hello() { +```js +async function hello() { return salutation = await Promise.resolve("Bonjour"); }; -hello().then(console.log);</pre> +hello().then(console.log); +``` -<p>Bien sûr, l'exemple ci-dessus n'est pas très utile, même s'il sert à illustrer la syntaxe. Passons maintenant à un exemple réel.</p> +Bien sûr, l'exemple ci-dessus n'est pas très utile, même s'il sert à illustrer la syntaxe. Passons maintenant à un exemple réel. -<h2 id="rewriting_promise_code_with_asyncawait">Réécriture du code des promesses avec async/await</h2> +## Réécriture du code des promesses avec async/await -<p>Reprenons un exemple simple de récupération que nous avons vu dans l'article précédent :</p> +Reprenons un exemple simple de récupération que nous avons vu dans l'article précédent : -<pre class="brush: js">fetch('coffee.jpg') -.then(response => { +```js +fetch('coffee.jpg') +.then(response => { if (!response.ok) { throw new Error(`Erreur HTTP ! statut : ${response.status}`); } return response.blob(); }) -.then(myBlob => { +.then(myBlob => { let objectURL = URL.createObjectURL(myBlob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); }) -.catch(e => { +.catch(e => { console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message); -});</pre> +}); +``` -<p>À ce stade, vous devriez avoir une compréhension raisonnable des promesses et de leur fonctionnement, mais convertissons le tout en utilisant async/await pour voir à quel point cela simplifie les choses :</p> +À ce stade, vous devriez avoir une compréhension raisonnable des promesses et de leur fonctionnement, mais convertissons le tout en utilisant async/await pour voir à quel point cela simplifie les choses : -<pre class="brush: js">async function myFetch() { +```js +async function myFetch() { let response = await fetch('coffee.jpg'); if (!response.ok) { @@ -134,15 +153,17 @@ hello().then(console.log);</pre> } myFetch() -.catch(e => { +.catch(e => { console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message); -});</pre> +}); +``` -<p>Cela rend le code beaucoup plus simple et plus facile à comprendre — plus de blocs <code>.then()</code> partout !</p> +Cela rend le code beaucoup plus simple et plus facile à comprendre — plus de blocs `.then()` partout ! -<p>Étant donné qu'un mot-clé <code>async</code> transforme une fonction en promesse, vous pourriez remanier votre code pour utiliser une approche hybride de promesses et de <code>await</code>, en faisant sortir la seconde moitié de la fonction dans un nouveau bloc pour la rendre plus flexible :</p> +Étant donné qu'un mot-clé `async` transforme une fonction en promesse, vous pourriez remanier votre code pour utiliser une approche hybride de promesses et de `await`, en faisant sortir la seconde moitié de la fonction dans un nouveau bloc pour la rendre plus flexible : -<pre class="brush: js">async function myFetch() { +```js +async function myFetch() { let response = await fetch('coffee.jpg'); if (!response.ok) { throw new Error(`Erreur HTTP ! statut : ${response.status}`); @@ -151,38 +172,42 @@ myFetch() } -myFetch().then((blob) => { +myFetch().then((blob) => { let objectURL = URL.createObjectURL(blob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); -}).catch(e => console.log(e));</pre> +}).catch(e => console.log(e)); +``` -<p>Vous pouvez essayer de taper vous-même l'exemple, ou d'exécuter notre <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await.html">exemple en direct</a> (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await.html">code source</a>).</p> +Vous pouvez essayer de taper vous-même l'exemple, ou d'exécuter notre [exemple en direct](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await.html) (voir aussi le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await.html)). -<h3 id="but_how_does_it_work">Mais comment est-ce que cela fonctionne ?</h3> +### Mais comment est-ce que cela fonctionne ? -<p>Vous remarquerez que nous avons enveloppé le code à l'intérieur d'une fonction, et que nous avons inclus le mot-clé <code>async</code> avant le mot-clé <code>function</code>. C'est nécessaire - vous devez créer une fonction async pour définir un bloc de code dans lequel vous exécuterez votre code async ; comme nous l'avons dit précédemment, <code>await</code> ne fonctionne qu'à l'intérieur de fonctions async.</p> +Vous remarquerez que nous avons enveloppé le code à l'intérieur d'une fonction, et que nous avons inclus le mot-clé `async` avant le mot-clé `function`. C'est nécessaire - vous devez créer une fonction async pour définir un bloc de code dans lequel vous exécuterez votre code async ; comme nous l'avons dit précédemment, `await` ne fonctionne qu'à l'intérieur de fonctions async. -<p>À l'intérieur de la définition de la fonction <code>myFetch()</code>, vous pouvez voir que le code ressemble beaucoup à la version précédente de la promesse, mais il y a quelques différences. Au lieu de devoir enchaîner un bloc <code>.then()</code> à la fin de chaque méthode basée sur une promesse, il suffit d'ajouter un mot-clé <code>await</code> avant l'appel de la méthode, puis d'affecter le résultat à une variable. Le mot-clé <code>await</code> fait en sorte que le moteur d'exécution JavaScript mette votre code en pause sur cette ligne, ne permettant pas à d'autres codes de s'exécuter entre-temps jusqu'à ce que l'appel de fonction asynchrone ait retourné son résultat - très utile si le code suivant dépend de ce résultat !</p> +À l'intérieur de la définition de la fonction `myFetch()`, vous pouvez voir que le code ressemble beaucoup à la version précédente de la promesse, mais il y a quelques différences. Au lieu de devoir enchaîner un bloc `.then()` à la fin de chaque méthode basée sur une promesse, il suffit d'ajouter un mot-clé `await` avant l'appel de la méthode, puis d'affecter le résultat à une variable. Le mot-clé `await` fait en sorte que le moteur d'exécution JavaScript mette votre code en pause sur cette ligne, ne permettant pas à d'autres codes de s'exécuter entre-temps jusqu'à ce que l'appel de fonction asynchrone ait retourné son résultat - très utile si le code suivant dépend de ce résultat ! -<p>Une fois que c'est terminé, votre code continue à s'exécuter à partir de la ligne suivante. Par exemple :</p> +Une fois que c'est terminé, votre code continue à s'exécuter à partir de la ligne suivante. Par exemple : -<pre class="brush: js">let response = await fetch('coffee.jpg');</pre> +```js +let response = await fetch('coffee.jpg'); +``` -<p>La réponse retournée par la promesse <code>fetch()</code> remplie est affectée à la variable <code>response</code> lorsque cette réponse devient disponible, et le parseur fait une pause sur cette ligne jusqu'à ce que cela se produise. Une fois que la réponse est disponible, le parseur passe à la ligne suivante, qui crée un <code><a href="/fr/docs/Web/API/Blob">Blob</a></code> à partir de celle-ci. Cette ligne invoque également une méthode async basée sur les promesses, nous utilisons donc <code>await</code> ici aussi. Lorsque le résultat de l'opération revient, nous le retournons hors de la fonction <code>myFetch()</code>.</p> +La réponse retournée par la promesse `fetch()` remplie est affectée à la variable `response` lorsque cette réponse devient disponible, et le parseur fait une pause sur cette ligne jusqu'à ce que cela se produise. Une fois que la réponse est disponible, le parseur passe à la ligne suivante, qui crée un [`Blob`](/fr/docs/Web/API/Blob) à partir de celle-ci. Cette ligne invoque également une méthode async basée sur les promesses, nous utilisons donc `await` ici aussi. Lorsque le résultat de l'opération revient, nous le retournons hors de la fonction `myFetch()`. -<p>Cela signifie que lorsque nous appelons la fonction <code>myFetch()</code>, elle retourne une promesse, de sorte que nous pouvons enchaîner un <code>.then()</code> à la fin de celle-ci à l'intérieur duquel nous gérons l'affichage du blob à l'écran.</p> +Cela signifie que lorsque nous appelons la fonction `myFetch()`, elle retourne une promesse, de sorte que nous pouvons enchaîner un `.then()` à la fin de celle-ci à l'intérieur duquel nous gérons l'affichage du blob à l'écran. -<p>Vous vous dites probablement déjà « c'est vraiment cool ! », et vous avez raison — moins de blocs <code>.then()</code> pour envelopper le code, et cela ressemble surtout à du code synchrone, donc c'est vraiment intuitif.</p> +Vous vous dites probablement déjà « c'est vraiment cool ! », et vous avez raison — moins de blocs `.then()` pour envelopper le code, et cela ressemble surtout à du code synchrone, donc c'est vraiment intuitif. -<h3 id="adding_error_handling">Ajout de la gestion des erreurs</h3> +### Ajout de la gestion des erreurs -<p>Si vous voulez ajouter la gestion des erreurs, vous avez plusieurs options.</p> +Si vous voulez ajouter la gestion des erreurs, vous avez plusieurs options. -<p>Vous pouvez utiliser une structure synchrone <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> avec <code>async</code>/<code>await</code>. Cet exemple développe la première version du code que nous avons montré ci-dessus :</p> +Vous pouvez utiliser une structure synchrone [`try...catch`](/fr/docs/Web/JavaScript/Reference/Statements/try...catch) avec `async`/`await`. Cet exemple développe la première version du code que nous avons montré ci-dessus : -<pre class="brush: js">async function myFetch() { +```js +async function myFetch() { try { let response = await fetch('coffee.jpg'); @@ -200,13 +225,15 @@ myFetch().then((blob) => { } } -myFetch();</pre> +myFetch(); +``` -<p>Le bloc <code>catch() {}</code> reçoit un objet d'erreur, que nous avons appelé <code>e</code> ; nous pouvons maintenant l'enregistrer dans la console, et il nous donnera un message d'erreur détaillé montrant où dans le code l'erreur a été lancée.</p> +Le bloc `catch() {}` reçoit un objet d'erreur, que nous avons appelé `e` ; nous pouvons maintenant l'enregistrer dans la console, et il nous donnera un message d'erreur détaillé montrant où dans le code l'erreur a été lancée. -<p>Si vous vouliez utiliser la deuxième version (remaniée) du code que nous avons montré ci-dessus, il serait préférable de continuer l'approche hybride et d'enchaîner un bloc <code>.catch()</code> à la fin de l'appel <code>.then()</code>, comme ceci :</p> +Si vous vouliez utiliser la deuxième version (remaniée) du code que nous avons montré ci-dessus, il serait préférable de continuer l'approche hybride et d'enchaîner un bloc `.catch()` à la fin de l'appel `.then()`, comme ceci : -<pre class="brush: js">async function myFetch() { +```js +async function myFetch() { let response = await fetch('coffee.jpg'); if (!response.ok) { throw new Error(`Erreur HTTP ! statut : ${response.status}`); @@ -215,32 +242,32 @@ myFetch();</pre> } -myFetch().then((blob) => { +myFetch().then((blob) => { let objectURL = URL.createObjectURL(blob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); }) -.catch((e) => +.catch((e) => console.log(e) -);</pre> +); +``` -<p>En effet, le bloc <code>.catch()</code> attrapera les erreurs survenant à la fois dans l'appel de fonction asynchrone et dans la chaîne de promesses. Si vous utilisiez le bloc <code>try</code>/<code>catch</code> ici, vous pourriez toujours obtenir des erreurs non gérées dans la fonction <code>myFetch()</code> lorsqu'elle est appelée.</p> +En effet, le bloc `.catch()` attrapera les erreurs survenant à la fois dans l'appel de fonction asynchrone et dans la chaîne de promesses. Si vous utilisiez le bloc `try`/`catch` ici, vous pourriez toujours obtenir des erreurs non gérées dans la fonction `myFetch()` lorsqu'elle est appelée. -<p>Vous pouvez trouver ces deux exemples sur GitHub :</p> +Vous pouvez trouver ces deux exemples sur GitHub : -<ul> - <li><a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html">simple-fetch-async-await-try-catch.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html">code source</a>)</li> - <li><a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html">simple-fetch-async-await-promise-catch.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html">code source</a>)</li> -</ul> +- [simple-fetch-async-await-try-catch.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html)) +- [simple-fetch-async-await-promise-catch.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html)) -<h2 id="awaiting_a_promise.all">En attente d'un Promise.all()</h2> +## En attente d'un Promise.all() -<p><code>async</code>/<code>await</code> est construit au-dessus de <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise" >Promises</a>, il est donc compatible avec toutes les fonctionnalités offertes par les promesses. Cela inclut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise.all()</a></code> — vous pouvez tout à fait attendre un appel <code>Promise.all()</code> pour obtenir tous les résultats retournés dans une variable d'une manière qui ressemble à du simple code synchrone. Encore une fois, revenons à <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">un exemple que nous avons vu dans notre article précédent</a>. Gardez-le ouvert dans un onglet séparé afin de pouvoir le comparer avec la nouvelle version présentée ci-dessous.</p> +`async`/`await` est construit au-dessus de [Promises](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise), il est donc compatible avec toutes les fonctionnalités offertes par les promesses. Cela inclut [`Promise.all()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) — vous pouvez tout à fait attendre un appel `Promise.all()` pour obtenir tous les résultats retournés dans une variable d'une manière qui ressemble à du simple code synchrone. Encore une fois, revenons à [un exemple que nous avons vu dans notre article précédent](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html). Gardez-le ouvert dans un onglet séparé afin de pouvoir le comparer avec la nouvelle version présentée ci-dessous. -<p>En convertissant cela en <code>async</code>/<code>await</code> (voir la <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-all-async-await.html">démo live</a> et le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-all-async-await.html">code source</a>), cela ressemble maintenant à ceci :</p> +En convertissant cela en `async`/`await` (voir la [démo live](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-all-async-await.html) et le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-all-async-await.html)), cela ressemble maintenant à ceci : -<pre class="brush: js">async function fetchAndDecode(url, type) { +```js +async function fetchAndDecode(url, type) { let response = await fetch(url); let content; @@ -282,31 +309,33 @@ async function displayContent() { } displayContent() -.catch((e) => +.catch((e) => console.log(e) -);</pre> +); +``` -<p>Vous verrez que la fonction <code>fetchAndDecode()</code> a été convertie facilement en fonction asynchrone avec seulement quelques modifications. Voir la ligne <code>Promise.all()</code> :</p> +Vous verrez que la fonction `fetchAndDecode()` a été convertie facilement en fonction asynchrone avec seulement quelques modifications. Voir la ligne `Promise.all()` : -<pre class="brush: js">let values = await Promise.all([coffee, tea, description]);</pre> +```js +let values = await Promise.all([coffee, tea, description]); +``` -<p>En utilisant <code>await</code> ici, nous sommes en mesure d'obtenir tous les résultats des trois promesses retournées dans le tableau <code>values</code>, quand ils sont tous disponibles, d'une manière qui ressemble beaucoup à du code synchrone. Nous avons dû envelopper tout le code dans une nouvelle fonction asynchrone, <code>displayContent()</code>, et nous n'avons pas réduit le code de beaucoup de lignes, mais être capable de déplacer la majeure partie du code hors du bloc <code>.then()</code> fournit une simplification agréable et utile, nous laissant avec un programme beaucoup plus lisible.</p> +En utilisant `await` ici, nous sommes en mesure d'obtenir tous les résultats des trois promesses retournées dans le tableau `values`, quand ils sont tous disponibles, d'une manière qui ressemble beaucoup à du code synchrone. Nous avons dû envelopper tout le code dans une nouvelle fonction asynchrone, `displayContent()`, et nous n'avons pas réduit le code de beaucoup de lignes, mais être capable de déplacer la majeure partie du code hors du bloc `.then()` fournit une simplification agréable et utile, nous laissant avec un programme beaucoup plus lisible. -<p>Pour la gestion des erreurs, nous avons inclus un bloc <code>.catch()</code> sur notre appel <code>displayContent()</code> ; cela permettra de gérer les erreurs survenant dans les deux fonctions.</p> +Pour la gestion des erreurs, nous avons inclus un bloc `.catch()` sur notre appel `displayContent()` ; cela permettra de gérer les erreurs survenant dans les deux fonctions. -<div class="notecard note"> - <p><strong>Note :</strong> Il est également possible d'utiliser un bloc <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/try...catch#the_finally_clause">finally</a></code> au sein d'une fonction asynchrone, à la place d'un bloc asynchrone <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally">.finally()</a></code>, pour montrer un état final sur le déroulement de l'opération — vous pouvez voir cela en action dans notre <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-finally-async-await.html">exemple en direct</a> (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-finally-async-await.html">code source</a>).</p> -</div> +> **Note :** Il est également possible d'utiliser un bloc [`finally`](/fr/docs/Web/JavaScript/Reference/Statements/try...catch#the_finally_clause) au sein d'une fonction asynchrone, à la place d'un bloc asynchrone [`.finally()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally), pour montrer un état final sur le déroulement de l'opération — vous pouvez voir cela en action dans notre [exemple en direct](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-finally-async-await.html) (voir aussi le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-finally-async-await.html)). -<h2 id="handling_asyncawait_slowdown">Gérer les ralentissements potentiellement causés par async/await</h2> +## Gérer les ralentissements potentiellement causés par async/await -<p>Il est vraiment utile de connaître <code>async</code>/<code>await</code>, mais il y a quelques inconvénients à prendre en compte.</p> +Il est vraiment utile de connaître `async`/`await`, mais il y a quelques inconvénients à prendre en compte. -<p><code>async</code>/<code>await</code> donne à votre code une apparence synchrone, et d'une certaine manière, il le fait se comporter de manière plus synchrone. Le mot-clé <code>await</code> bloque l'exécution de tout le code qui le suit jusqu'à ce que la promesse se réalise, exactement comme dans le cas d'une opération synchrone. Il permet certes aux autres tâches de continuer à s'exécuter entre-temps, mais le code attendu est bloqué.</p> +`async`/`await` donne à votre code une apparence synchrone, et d'une certaine manière, il le fait se comporter de manière plus synchrone. Le mot-clé `await` bloque l'exécution de tout le code qui le suit jusqu'à ce que la promesse se réalise, exactement comme dans le cas d'une opération synchrone. Il permet certes aux autres tâches de continuer à s'exécuter entre-temps, mais le code attendu est bloqué. -<pre class="brush: js">async function makeResult(items) { +```js +async function makeResult(items) { let newArr = []; - for(let i=0; i < items.length; i++) { + for(let i=0; i < items.length; i++) { newArr.push('word_'+i); } return newArr; @@ -315,52 +344,62 @@ displayContent() async function getResult() { let result = await makeResult(items); // Bloqué sur cette ligne useThatResult(result); // Pas exécuté tant que makeResult() n'a pas fini -}</pre> +} +``` -<p>Cela signifie que votre code pourrait être ralenti par un nombre important de promesses attendues se produisant directement les unes après les autres. Chaque <code>await</code> attendra que la précédente se termine, alors qu'en réalité ce que vous voulez, c'est que les promesses commencent à être traitées simultanément, comme elles le feraient si nous n'utilisions pas <code>async</code>/<code>await</code>.</p> +Cela signifie que votre code pourrait être ralenti par un nombre important de promesses attendues se produisant directement les unes après les autres. Chaque `await` attendra que la précédente se termine, alors qu'en réalité ce que vous voulez, c'est que les promesses commencent à être traitées simultanément, comme elles le feraient si nous n'utilisions pas `async`/`await`. -<p>Il existe un modèle qui peut atténuer ce problème - déclencher tous les processus de promesse en stockant les objets <code>Promise</code> dans des variables, et en les attendant tous ensuite. Jetons un coup d'œil à quelques exemples qui prouvent le concept.</p> +Il existe un modèle qui peut atténuer ce problème - déclencher tous les processus de promesse en stockant les objets `Promise` dans des variables, et en les attendant tous ensuite. Jetons un coup d'œil à quelques exemples qui prouvent le concept. -<p>Nous disposons de deux exemples - <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/slow-async-await.html">slow-async-await.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/slow-async-await.html">code source</a>) et <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/fast-async-await.html">fast-async-await.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/fast-async-await.html">code source</a>). Les deux commencent par une fonction promise personnalisée qui simule un processus asynchrone avec un appel <code><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> :</p> +Nous disposons de deux exemples - [slow-async-await.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/slow-async-await.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/slow-async-await.html)) et [fast-async-await.html](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/fast-async-await.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/fast-async-await.html)). Les deux commencent par une fonction promise personnalisée qui simule un processus asynchrone avec un appel [`setTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) : -<pre class="brush: js">function timeoutPromise(interval) { - return new Promise((resolve, reject) => { +```js +function timeoutPromise(interval) { + return new Promise((resolve, reject) => { setTimeout(function(){ resolve("fait"); }, interval); }); -};</pre> +}; +``` -<p>Ensuite, chacun comprend une fonction asynchrone <code>timeTest()</code> qui attend trois appels <code>timeoutPromise()</code> :</p> +Ensuite, chacun comprend une fonction asynchrone `timeTest()` qui attend trois appels `timeoutPromise()` : -<pre class="brush: js">async function timeTest() { +```js +async function timeTest() { ... -}</pre> +} +``` -<p>Chacune d'entre elles se termine en enregistrant une heure de début, en voyant combien de temps la promesse <code>timeTest()</code> met à se réaliser, puis en enregistrant une heure de fin et en indiquant combien de temps l'opération a pris au total :</p> +Chacune d'entre elles se termine en enregistrant une heure de début, en voyant combien de temps la promesse `timeTest()` met à se réaliser, puis en enregistrant une heure de fin et en indiquant combien de temps l'opération a pris au total : -<pre class="brush: js">let startTime = Date.now(); -timeTest().then(() => { +```js +let startTime = Date.now(); +timeTest().then(() => { let finishTime = Date.now(); let timeTaken = finishTime - startTime; console.log("Temps pris en millisecondes : " + timeTaken); -})</pre> +}) +``` -<p>C'est la fonction <code>timeTest()</code> qui diffère dans chaque cas.</p> +C'est la fonction `timeTest()` qui diffère dans chaque cas. -<p>Dans l'exemple <code>slow-async-await.html</code>, <code>timeTest()</code> ressemble à ceci :</p> +Dans l'exemple `slow-async-await.html`, `timeTest()` ressemble à ceci : -<pre class="brush: js">async function timeTest() { +```js +async function timeTest() { await timeoutPromise(3000); await timeoutPromise(3000); await timeoutPromise(3000); -}</pre> +} +``` -<p>Ici, nous attendons les trois appels <code>timeoutPromise()</code> directement, en faisant en sorte que chacun d'eux alerte pendant 3 secondes. Chaque appel suivant est forcé d'attendre jusqu'à ce que le dernier soit terminé - si vous exécutez le premier exemple, vous verrez la boîte d'alerte signaler une durée d'exécution totale d'environ 9 secondes.</p> +Ici, nous attendons les trois appels `timeoutPromise()` directement, en faisant en sorte que chacun d'eux alerte pendant 3 secondes. Chaque appel suivant est forcé d'attendre jusqu'à ce que le dernier soit terminé - si vous exécutez le premier exemple, vous verrez la boîte d'alerte signaler une durée d'exécution totale d'environ 9 secondes. -<p>Dans l'exemple <code>fast-async-await.html</code>, <code>timeTest()</code> ressemble à ceci :</p> +Dans l'exemple `fast-async-await.html`, `timeTest()` ressemble à ceci : -<pre class="brush: js">async function timeTest() { +```js +async function timeTest() { const timeoutPromise1 = timeoutPromise(3000); const timeoutPromise2 = timeoutPromise(3000); const timeoutPromise3 = timeoutPromise(3000); @@ -368,19 +407,21 @@ timeTest().then(() => { await timeoutPromise1; await timeoutPromise2; await timeoutPromise3; -}</pre> +} +``` -<p>Ici, nous stockons les trois objets <code>Promise</code> dans des variables, ce qui a pour effet de déclencher leurs processus associés, tous exécutés simultanément.</p> +Ici, nous stockons les trois objets `Promise` dans des variables, ce qui a pour effet de déclencher leurs processus associés, tous exécutés simultanément. -<p>Ensuite, nous attendons leurs résultats - parce que les promesses ont toutes commencé à être traitées essentiellement au même moment, les promesses se réaliseront toutes en même temps ; lorsque vous exécuterez le deuxième exemple, vous verrez la boîte d'alerte indiquant un temps d'exécution total d'un peu plus de 3 secondes !</p> +Ensuite, nous attendons leurs résultats - parce que les promesses ont toutes commencé à être traitées essentiellement au même moment, les promesses se réaliseront toutes en même temps ; lorsque vous exécuterez le deuxième exemple, vous verrez la boîte d'alerte indiquant un temps d'exécution total d'un peu plus de 3 secondes ! -<h3 id="handling_errors">Gestion des erreurs</h3> +### Gestion des erreurs -<p>La stratégie précédente a un défaut : on pourrait avoir des erreurs qui ne seraient pas gérées.</p> +La stratégie précédente a un défaut : on pourrait avoir des erreurs qui ne seraient pas gérées. -<p>Mettons à jour les exemples précédents en ajoutant une promesse rejetée et une instruction <code>catch</code> à la fin :</p> +Mettons à jour les exemples précédents en ajoutant une promesse rejetée et une instruction `catch` à la fin : -<pre class="brush: js">function timeoutPromiseResolve(interval) { +```js +function timeoutPromiseResolve(interval) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve("Succès"); @@ -409,13 +450,15 @@ timeTest().then(() => {}) let finishTime = Date.now(); let timeTaken = finishTime - startTime; console.log("Temps écoulé en millisecondes : " + timeTaken); -})</pre> +}) +``` -<p>Dans l'exemple qui précède, l'erreur est gérée correctement et le message dans la console apparaît après environ 7 secondes.</p> +Dans l'exemple qui précède, l'erreur est gérée correctement et le message dans la console apparaît après environ 7 secondes. -<p>Voyons maintenant la deuxième approche :</p> +Voyons maintenant la deuxième approche : -<pre class="brush: js">function timeoutPromiseResolve(interval) { +```js +function timeoutPromiseResolve(interval) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve("Succès"); @@ -448,13 +491,15 @@ timeTest().then(() => { let finishTime = Date.now(); let timeTaken = finishTime - startTime; console.log("Temps écoulé en millisecondes : " + timeTaken); -})</pre> +}) +``` -<p>Dans cet exemple, on a une erreur qui n'est pas gérée dans la console (après 2 secondes) et le message apparaît après environ 5 secondes.</p> +Dans cet exemple, on a une erreur qui n'est pas gérée dans la console (après 2 secondes) et le message apparaît après environ 5 secondes. -<p>Pour démarrer les promesses en parallèles et intercepter les erreurs correctement, on pourrait utiliser <code>Promise.all()</code> comme vu auparavant :</p> +Pour démarrer les promesses en parallèles et intercepter les erreurs correctement, on pourrait utiliser `Promise.all()` comme vu auparavant : -<pre class="brush: js">function timeoutPromiseResolve(interval) { +```js +function timeoutPromiseResolve(interval) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve("Succès"); @@ -486,17 +531,19 @@ timeTest().then(() => { let finishTime = Date.now(); let timeTaken = finishTime - startTime; console.log("Temps écoulé en millisecondes : " + timeTaken); -})</pre> +}) +``` -<p>Dans cet exemple, l'erreur est gérée correctement après 2 secondes et on a le message dans la console après environ 2 secondes.</p> +Dans cet exemple, l'erreur est gérée correctement après 2 secondes et on a le message dans la console après environ 2 secondes. -<p>La méthode <code>Promise.all()</code> rejète lorsqu'au moins un de ses promesses d'entrée rejète. Si on veut que toutes les promesses soient résolues (correctement ou avec un rejet), on pourra utiliser la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled"><code>Promise.allSettled()</code></a> à la place.</p> +La méthode `Promise.all()` rejète lorsqu'au moins un de ses promesses d'entrée rejète. Si on veut que toutes les promesses soient résolues (correctement ou avec un rejet), on pourra utiliser la méthode [`Promise.allSettled()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled) à la place. -<h2 id="asyncawait_class_methods">Méthodes de classe async/await</h2> +## Méthodes de classe async/await -<p>Une dernière remarque avant de poursuivre, vous pouvez même ajouter <code>async</code> devant les méthodes de classe/objet pour qu'elles renvoient des promesses, et <code>await</code> des promesses à l'intérieur de celles-ci. Jetez un œil au <a href="/fr/docs/Learn/JavaScript/Objects/Inheritance#ecmascript_2015_classes">code de la classe ES que nous avons vu dans notre article sur le JavaScript orienté objet</a>, puis regardez notre version modifiée avec une méthode <code>async</code> :</p> +Une dernière remarque avant de poursuivre, vous pouvez même ajouter `async` devant les méthodes de classe/objet pour qu'elles renvoient des promesses, et `await` des promesses à l'intérieur de celles-ci. Jetez un œil au [code de la classe ES que nous avons vu dans notre article sur le JavaScript orienté objet](/fr/docs/Learn/JavaScript/Objects/Inheritance#ecmascript_2015_classes), puis regardez notre version modifiée avec une méthode `async` : -<pre class="brush: js">class Personne { +```js +class Personne { constructor(prenom, nomFamille, age, genre, interets) { this.nom = { prenom, @@ -516,31 +563,32 @@ timeTest().then(() => { }; } -let han = new Personne('Han', 'Solo', 25, 'homme', ['Contrebande']);</pre> +let han = new Personne('Han', 'Solo', 25, 'homme', ['Contrebande']); +``` -<p>La méthode de la première classe peut maintenant être utilisée de la manière suivante :</p> +La méthode de la première classe peut maintenant être utilisée de la manière suivante : -<pre class="brush: js">han.salutation().then(console.log);</pre> +```js +han.salutation().then(console.log); +``` -<h2 id="browser_support">Prise en charge des navigateurs</h2> +## Prise en charge des navigateurs -<p>L'une des considérations à prendre en compte pour décider d'utiliser <code>async</code>/<code>await</code>est la prise en charge des anciens navigateurs. Ces fonctionnalités sont disponibles dans les versions modernes de la plupart des navigateurs, tout comme les promesses ; les principaux problèmes de prise en charge concernent Internet Explorer et Opera Mini.</p> +L'une des considérations à prendre en compte pour décider d'utiliser `async`/`await`est la prise en charge des anciens navigateurs. Ces fonctionnalités sont disponibles dans les versions modernes de la plupart des navigateurs, tout comme les promesses ; les principaux problèmes de prise en charge concernent Internet Explorer et Opera Mini. -<p>Si vous souhaitez utiliser <code>async</code>/<code>await</code> mais que vous êtes préoccupé par la prise en charge de navigateurs plus anciens, vous pouvez envisager d'utiliser la bibliothèque <a href="https://babeljs.io/">BabelJS</a>. Cela vous permet d'écrire vos applications en utilisant les dernières versions de JavaScript et de laisser Babel déterminer les modifications éventuellement nécessaires pour les navigateurs de vos utilisateurs. Lorsque vous rencontrez un navigateur qui ne supporte pas async/await, le <i>polyfill</i> « prothèse d'émulation » de Babel peut automatiquement fournir des <i>fallbacks</i> « solutions de secours » qui fonctionnent dans les anciens navigateurs.</p> +Si vous souhaitez utiliser `async`/`await` mais que vous êtes préoccupé par la prise en charge de navigateurs plus anciens, vous pouvez envisager d'utiliser la bibliothèque [BabelJS](https://babeljs.io/). Cela vous permet d'écrire vos applications en utilisant les dernières versions de JavaScript et de laisser Babel déterminer les modifications éventuellement nécessaires pour les navigateurs de vos utilisateurs. Lorsque vous rencontrez un navigateur qui ne supporte pas async/await, le _polyfill_ « prothèse d'émulation » de Babel peut automatiquement fournir des _fallbacks_ « solutions de secours » qui fonctionnent dans les anciens navigateurs. -<h2 id="conclusion">Conclusion</h2> +## Conclusion -<p>Et voilà, <code>async</code>/<code>await</code> offre un moyen agréable et simplifié d'écrire du code asynchrone, plus facile à lire et à maintenir. Même si la prise en charge par les navigateurs est plus limitée que d'autres mécanismes de code asynchrone à l'heure où nous écrivons ces lignes, cela vaut la peine de l'apprendre et d'envisager de l'utiliser, maintenant et à l'avenir.</p> +Et voilà, `async`/`await` offre un moyen agréable et simplifié d'écrire du code asynchrone, plus facile à lire et à maintenir. Même si la prise en charge par les navigateurs est plus limitée que d'autres mécanismes de code asynchrone à l'heure où nous écrivons ces lignes, cela vaut la peine de l'apprendre et d'envisager de l'utiliser, maintenant et à l'avenir. -<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}} -<h2 id="in_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li> -</ul> +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Faciliter la programmation asynchrone avec async et await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) diff --git a/files/fr/learn/javascript/asynchronous/choosing_the_right_approach/index.md b/files/fr/learn/javascript/asynchronous/choosing_the_right_approach/index.md index 0b71c56c49..679212748d 100644 --- a/files/fr/learn/javascript/asynchronous/choosing_the_right_approach/index.md +++ b/files/fr/learn/javascript/asynchronous/choosing_the_right_approach/index.md @@ -17,54 +17,43 @@ tags: - timeouts translation_of: Learn/JavaScript/Asynchronous/Choosing_the_right_approach --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}} -<div>{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</div> - -<p>Pour terminer ce module, nous vous proposons une brève discussion sur les différentes techniques et fonctionnalités asynchrones abordées tout au long de ce module, en examinant laquelle de ces techniques est la plus pertinente en fonction de la situation ainsi que des recommandations et des rappels des pièges courants le cas échéant.</p> +Pour terminer ce module, nous vous proposons une brève discussion sur les différentes techniques et fonctionnalités asynchrones abordées tout au long de ce module, en examinant laquelle de ces techniques est la plus pertinente en fonction de la situation ainsi que des recommandations et des rappels des pièges courants le cas échéant. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, une compréhension raisonnable des principes fondamentaux de JavaScript.</td> + <td> + Connaissances informatiques de base, une compréhension raisonnable des + principes fondamentaux de JavaScript. + </td> </tr> <tr> <th scope="row">Objectif :</th> - <td>Être capable de faire un choix judicieux quant à l'utilisation de différentes techniques de programmation asynchrone.</td> + <td> + Être capable de faire un choix judicieux quant à l'utilisation de + différentes techniques de programmation asynchrone. + </td> </tr> </tbody> </table> -<h2 id="asynchronous_callbacks">Fonctions de rappels (callbacks) asynchrones</h2> +## Fonctions de rappels (callbacks) asynchrones -<p>Généralement trouvé dans les API à l'ancienne, une fonction de rappel (ou <i>callback</i> en anglais) implique qu'une fonction soit passée en paramètre à une autre fonction, qui est ensuite invoquée lorsqu'une opération asynchrone est terminée afin réaliser une opération avec le résultat. C'est la méthode qui précédait l'arrivée des promesses : elle n'est pas aussi efficace ou flexible. Ne l'utilisez que si nécessaire.</p> +Généralement trouvé dans les API à l'ancienne, une fonction de rappel (ou _callback_ en anglais) implique qu'une fonction soit passée en paramètre à une autre fonction, qui est ensuite invoquée lorsqu'une opération asynchrone est terminée afin réaliser une opération avec le résultat. C'est la méthode qui précédait l'arrivée des promesses : elle n'est pas aussi efficace ou flexible. Ne l'utilisez que si nécessaire. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Non</td> - <td>Oui (rappels récursifs)</td> - <td>Oui (rappels imbriqués)</td> - <td>Non</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ----------------------- | ---------------------------------- | -------------------------------- | +| Non | Oui (rappels récursifs) | Oui (rappels imbriqués) | Non | -<h3 id="code_example">Exemple de code</h3> +### Exemple de code -<p>Un exemple qui charge une ressource via l'API <a href="/fr/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">l'exécuter en direct</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">voir la source</a>) :</p> +Un exemple qui charge une ressource via l'API [`XMLHttpRequest`](/fr/docs/Web/API/XMLHttpRequest) ([l'exécuter en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html), et [voir la source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html)) : -<pre class="brush: js">function loadAsset(url, type, callback) { +```js +function loadAsset(url, type, callback) { let xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = type; @@ -84,174 +73,122 @@ function displayImage(blob) { document.body.appendChild(image); } -loadAsset('coffee.jpg', 'blob', displayImage);</pre> +loadAsset('coffee.jpg', 'blob', displayImage); +``` -<h3 id="pitfalls">Pièges</h3> +### Pièges -<ul> - <li>Les fonctions de rappels imbriquées peuvent être encombrantes et difficiles à lire (ce qu'on appelle parfois « <i>callback hell</i> » en anglais).</li> - <li>Les fonctions de rappel pour les cas d'erreur doivent être appelés une fois pour chaque niveau d'imbrication, alors qu'avec les promesses, vous pouvez simplement utiliser un seul bloc <code>.catch()</code> pour gérer les erreurs de toute la chaîne.</li> - <li>Les fonctions de rappel asynchrones ne sont pas très élégantes.</li> - <li>Les fonctions de rappel passées en argument de promesses sont toujours appelés dans l'ordre strict où ils sont placés dans la file d'attente des événements ; les fonctions de rappel asynchrones ne le sont pas.</li> - <li>Les fonctions de rappel asynchrones perdent le contrôle total de la façon dont la fonction sera exécutée lorsqu'elle est transmise à une bibliothèque tierce.</li> -</ul> +- Les fonctions de rappels imbriquées peuvent être encombrantes et difficiles à lire (ce qu'on appelle parfois « _callback hell_ » en anglais). +- Les fonctions de rappel pour les cas d'erreur doivent être appelés une fois pour chaque niveau d'imbrication, alors qu'avec les promesses, vous pouvez simplement utiliser un seul bloc `.catch()` pour gérer les erreurs de toute la chaîne. +- Les fonctions de rappel asynchrones ne sont pas très élégantes. +- Les fonctions de rappel passées en argument de promesses sont toujours appelés dans l'ordre strict où ils sont placés dans la file d'attente des événements ; les fonctions de rappel asynchrones ne le sont pas. +- Les fonctions de rappel asynchrones perdent le contrôle total de la façon dont la fonction sera exécutée lorsqu'elle est transmise à une bibliothèque tierce. -<h3 id="browser_compatibility">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>Très bonne prise en charge générale, bien que la prise en charge exacte dans les différentes API dépende de l'API en question. Reportez-vous à la documentation de référence de l'API que vous utilisez pour obtenir des informations plus spécifiques.</p> +Très bonne prise en charge générale, bien que la prise en charge exacte dans les différentes API dépende de l'API en question. Reportez-vous à la documentation de référence de l'API que vous utilisez pour obtenir des informations plus spécifiques. -<h3 id="further_information">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a>, en particulier les <a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing#async_callbacks">Fonctions de rappels asynchrones</a></li> -</ul> +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing), en particulier les [Fonctions de rappels asynchrones](/fr/docs/Learn/JavaScript/Asynchronous/Introducing#async_callbacks) -<h2 id="settimeout">setTimeout()</h2> +## setTimeout() -<p><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout"><code>setTimeout()</a></code> est une méthode qui permet d'exécuter une fonction après l'écoulement d'un délai arbitraire.</p> +[`setTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) est une méthode qui permet d'exécuter une fonction après l'écoulement d'un délai arbitraire. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Oui</td> - <td>Oui (délais récursifs)</td> - <td>Oui (délais d'attente imbriqués)</td> - <td>Non</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ---------------------- | ---------------------------------- | -------------------------------- | +| Oui | Oui (délais récursifs) | Oui (délais d'attente imbriqués) | Non | -<h3 id="code_example_2">Exemple de code</h3> +### Exemple de code -<p>Ici, le navigateur attendra deux secondes avant d'exécuter la fonction anonyme, puis affichera le message dans la console (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">voir son exécution en direct</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">voir le code source</a>) :</p> +Ici, le navigateur attendra deux secondes avant d'exécuter la fonction anonyme, puis affichera le message dans la console ([voir son exécution en direct](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html), et [voir le code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html)) : -<pre class="brush: js">let myGreeting = setTimeout(function() { +```js +let myGreeting = setTimeout(function() { console.log('Bonjour, M. Univers !'); -}, 2000)</pre> +}, 2000) +``` -<h3 id="pitfalls_2">Pièges</h3> +### Pièges -<p>Vous pouvez utiliser des appels récursifs à <code>setTimeout()</code> pour exécuter une fonction de manière répétée de façon similaire à <code>setInterval()</code>, en utilisant un code comme celui-ci :</p> +Vous pouvez utiliser des appels récursifs à `setTimeout()` pour exécuter une fonction de manière répétée de façon similaire à `setInterval()`, en utilisant un code comme celui-ci : -<pre class="brush: js">let i = 1; +```js +let i = 1; setTimeout(function run() { console.log(i); i++; setTimeout(run, 100); -}, 100);</pre> +}, 100); +``` -<p>Il existe une différence entre <code>setTimeout()</code> appelé récursivement et <code>setInterval()</code> :</p> +Il existe une différence entre `setTimeout()` appelé récursivement et `setInterval()` : -<ul> - <li>Les récursions avec <code>setTimeout()</code> garantissent qu'au moins le temps spécifié (100ms dans cet exemple) s'écoulera entre les exécutions ; le code s'exécutera puis attendra 100 millisecondes avant de s'exécuter à nouveau. L'intervalle sera le même quelle que soit la durée d'exécution du code.</li> - <li>Avec <code>setInterval()</code>, l'intervalle que nous choisissons <em>inclut</em> le temps d'exécution du code que nous voulons exécuter. Disons que le code prend 40 millisecondes pour s'exécuter — l'intervalle finit alors par n'être que de 60 millisecondes.</li> -</ul> +- Les récursions avec `setTimeout()` garantissent qu'au moins le temps spécifié (100ms dans cet exemple) s'écoulera entre les exécutions ; le code s'exécutera puis attendra 100 millisecondes avant de s'exécuter à nouveau. L'intervalle sera le même quelle que soit la durée d'exécution du code. +- Avec `setInterval()`, l'intervalle que nous choisissons _inclut_ le temps d'exécution du code que nous voulons exécuter. Disons que le code prend 40 millisecondes pour s'exécuter — l'intervalle finit alors par n'être que de 60 millisecondes. -<p>Lorsque votre code a le potentiel de prendre plus de temps à s'exécuter que l'intervalle de temps que vous avez assigné, il est préférable d'utiliser <code>setTimeout()</code> récursivement - cela maintiendra l'intervalle de temps constant entre les exécutions, quelle que soit la durée d'exécution du code, et vous n'obtiendrez pas d'erreurs.</p> +Lorsque votre code a le potentiel de prendre plus de temps à s'exécuter que l'intervalle de temps que vous avez assigné, il est préférable d'utiliser `setTimeout()` récursivement - cela maintiendra l'intervalle de temps constant entre les exécutions, quelle que soit la durée d'exécution du code, et vous n'obtiendrez pas d'erreurs. -<h3 id="browser_compatibility_2">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}}</p> +{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}} -<h3 id="further_information_2">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a>, en particulier <a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#settimeout()"><code>setTimeout()</code></a></li> - <li>Page de référence pour <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout"><code>setTimeout()</code></a></li> -</ul> +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals), en particulier [`setTimeout()`](</fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#settimeout()>) +- Page de référence pour [`setTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) -<h2 id="setInterval">setInterval()</h2> +## setInterval() -<p><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval"><code>setInterval()</code></a> est une méthode qui permet d'exécuter une fonction de façon répétée avec des intervalles de temps donnés entre chaque exécution. Cette méthode n'est pas aussi efficace que <a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</code></a>, mais elle permet de choisir le rythme d'exécution.</p> +[`setInterval()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) est une méthode qui permet d'exécuter une fonction de façon répétée avec des intervalles de temps donnés entre chaque exécution. Cette méthode n'est pas aussi efficace que [`requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame), mais elle permet de choisir le rythme d'exécution. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Non</td> - <td>Oui</td> - <td>Non (à moins qu'elles ne soient les mêmes)</td> - <td>Non</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ----------------- | ------------------------------------------ | -------------------------------- | +| Non | Oui | Non (à moins qu'elles ne soient les mêmes) | Non | -<h3 id="code_example_3">Exemple de code</h3> +### Exemple de code -<p>La fonction suivante crée un nouvel objet <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date"><code>Date()</code></a>, en extrait une chaîne de temps à l'aide de <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString"><code>toLocaleTimeString()</code></a>, puis l'affiche dans l'interface utilisateur. Nous l'exécutons ensuite une fois par seconde à l'aide de <code>setInterval()</code>, créant l'effet d'une horloge numérique qui se met à jour une fois par seconde (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">voir cela en direct</a>, et aussi <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">voir la source</a>) :</p> +La fonction suivante crée un nouvel objet [`Date()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Date), en extrait une chaîne de temps à l'aide de [`toLocaleTimeString()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString), puis l'affiche dans l'interface utilisateur. Nous l'exécutons ensuite une fois par seconde à l'aide de `setInterval()`, créant l'effet d'une horloge numérique qui se met à jour une fois par seconde ([voir cela en direct](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html), et aussi [voir la source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html)) : -<pre class="brush: js">function displayTime() { +```js +function displayTime() { let date = new Date(); let time = date.toLocaleTimeString(); document.getElementById('demo').textContent = time; } -const createClock = setInterval(displayTime, 1000);</pre> +const createClock = setInterval(displayTime, 1000); +``` -<h3 id="pitfalls_3">Pièges</h3> +### Pièges -<ul> - <li>La fréquence d'exécution et d'affichage n'est pas optimisée pour le système sur lequel l'animation est exécutée, et peut être quelque peu inefficace. À moins que vous n'ayez besoin de choisir un framerate spécifique (plus lent), il est généralement préférable d'utiliser <code>requestAnimationFrame()</code>.</li> -</ul> +- La fréquence d'exécution et d'affichage n'est pas optimisée pour le système sur lequel l'animation est exécutée, et peut être quelque peu inefficace. À moins que vous n'ayez besoin de choisir un framerate spécifique (plus lent), il est généralement préférable d'utiliser `requestAnimationFrame()`. -<h3 id="browser_compatibility_3">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>{{Compat("api.WindowOrWorkerGlobalScope.setInterval")}}</p> +{{Compat("api.WindowOrWorkerGlobalScope.setInterval")}} -<h3 id="further_information_3">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a>, en particulier <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></li> - <li>Page de référence pour <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></li> -</ul> +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals), en particulier [setInterval()](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) +- Page de référence pour [setInterval()](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) -<h2 id="requestAnimationFrame">requestAnimationFrame()</h2> +## requestAnimationFrame() -<p><a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</code></a> est une méthode qui vous permet d'exécuter une fonction de manière répétée, et efficace, à la meilleure fréquence de rafraîchissement disponible compte tenu du navigateur/système actuel. Vous devriez, dans la mesure du possible, utiliser cette méthode au lieu de <code>setInterval()</code>/<code>setTimeout()</code> récursif, sauf si vous avez besoin d'une fréquence de rafraîchissement spécifique.</p> +[`requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame) est une méthode qui vous permet d'exécuter une fonction de manière répétée, et efficace, à la meilleure fréquence de rafraîchissement disponible compte tenu du navigateur/système actuel. Vous devriez, dans la mesure du possible, utiliser cette méthode au lieu de `setInterval()`/`setTimeout()` récursif, sauf si vous avez besoin d'une fréquence de rafraîchissement spécifique. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Non</td> - <td>Oui</td> - <td>Non (à moins que ce soit les mêmes)</td> - <td>Non</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ----------------- | ----------------------------------- | -------------------------------- | +| Non | Oui | Non (à moins que ce soit les mêmes) | Non | -<h3 id="code_example_4">Exemple de code</h3> +### Exemple de code -<p>Une toupie animée simple ; vous pouvez trouver cet <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">exemple en direct sur GitHub</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">code source</a>) :</p> +Une toupie animée simple ; vous pouvez trouver cet [exemple en direct sur GitHub](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html)) : -<pre class="brush: js">const spinner = document.querySelector('div'); +```js +const spinner = document.querySelector('div'); let rotateCount = 0; let startTime = null; let rAF; @@ -263,7 +200,7 @@ function draw(timestamp) { rotateCount = (timestamp - startTime) / 3; - if(rotateCount > 359) { + if(rotateCount > 359) { rotateCount %= 360; } @@ -272,70 +209,54 @@ function draw(timestamp) { rAF = requestAnimationFrame(draw); } -draw();</pre> +draw(); +``` -<h3 id="pitfalls_4">Pièges</h3> +### Pièges -<ul> - <li>Vous ne pouvez pas choisir une fréquence d'images spécifique avec <code>requestAnimationFrame()</code>. Si vous devez exécuter votre animation à un <i>framerate</i> plus lent, vous devrez utiliser <code>setInterval()</code> ou <code>setTimeout()</code> récursif.</li> -</ul> +- Vous ne pouvez pas choisir une fréquence d'images spécifique avec `requestAnimationFrame()`. Si vous devez exécuter votre animation à un _framerate_ plus lent, vous devrez utiliser `setInterval()` ou `setTimeout()` récursif. -<h3 id="browser_compatibility_4">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>{{Compat("api.Window.requestAnimationFrame")}}</p> +{{Compat("api.Window.requestAnimationFrame")}} -<h3 id="further_information_4">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a>, en particulier <a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#requestanimationframe()"><code>requestAnimationFrame()</code></a></li> - <li>Page de référence pour <a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</code></a></li> -</ul> +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals), en particulier [`requestAnimationFrame()`](</fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#requestanimationframe()>) +- Page de référence pour [`requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame) -<h2 id="Promises">Promises (Promesses)</h2> +## Promises (Promesses) -<p><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise">Les promesses</a> sont une fonctionnalité JavaScript qui permet d'exécuter des opérations asynchrones et d'attendre qu'elles soient définitivement terminées avant d'exécuter une autre opération en fonction de son résultat. Les promesses sont la colonne vertébrale du JavaScript asynchrone moderne.</p> +[Les promesses](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) sont une fonctionnalité JavaScript qui permet d'exécuter des opérations asynchrones et d'attendre qu'elles soient définitivement terminées avant d'exécuter une autre opération en fonction de son résultat. Les promesses sont la colonne vertébrale du JavaScript asynchrone moderne. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Non</td> - <td>Non</td> - <td>Oui</td> - <td>Voir <code>Promise.all()</code>, en dessous</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ----------------- | ---------------------------------- | -------------------------------- | +| Non | Non | Oui | Voir `Promise.all()`, en dessous | -<h3 id="code_example_5">Exemple de code</h3> +### Exemple de code -<p>Le code suivant va chercher une image sur le serveur et l'affiche à l'intérieur d'un élément <a href="/fr/docs/Web/HTML/Element/Img"><code><img></code></a> ; <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch-chained.html">voyez-le aussi en direct</a>, et voyez aussi <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html">le code source</a> :</p> +Le code suivant va chercher une image sur le serveur et l'affiche à l'intérieur d'un élément [`<img>`](/fr/docs/Web/HTML/Element/Img) ; [voyez-le aussi en direct](https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch-chained.html), et voyez aussi [le code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html) : -<pre class="brush: js">fetch('coffee.jpg') -.then(response => response.blob()) -.then(myBlob => { +```js +fetch('coffee.jpg') +.then(response => response.blob()) +.then(myBlob => { let objectURL = URL.createObjectURL(myBlob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); }) -.catch(e => { +.catch(e => { console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message); -});</pre> +}); +``` -<h3 id="pitfalls_5">Pièges</h3> +### Pièges -<p>Les chaînes de promesses peuvent être complexes et difficiles à analyser. Si vous imbriquez un certain nombre de promesses, vous pouvez vous retrouver avec des problèmes similaires à l'enfer des rappels. Par exemple :</p> +Les chaînes de promesses peuvent être complexes et difficiles à analyser. Si vous imbriquez un certain nombre de promesses, vous pouvez vous retrouver avec des problèmes similaires à l'enfer des rappels. Par exemple : -<pre class="brush: js">remotedb.allDocs({ +```js +remotedb.allDocs({ include_docs: true, attachments: true }).then(function (result) { @@ -347,11 +268,13 @@ draw();</pre> if (err.name == 'conflict') { localdb.get(element.doc._id).then(function (resp) { localdb.remove(resp._id, resp._rev).then(function (resp) { -// et cetera...</pre> +// et cetera... +``` -<p>Il est préférable d'utiliser la puissance de chaînage des promesses pour aller avec une structure plus plate et plus facile à analyser :</p> +Il est préférable d'utiliser la puissance de chaînage des promesses pour aller avec une structure plus plate et plus facile à analyser : -<pre class="brush: js">remotedb.allDocs(...).then(function (resultOfAllDocs) { +```js +remotedb.allDocs(...).then(function (resultOfAllDocs) { return localdb.put(...); }).then(function (resultOfPut) { return localdb.get(...); @@ -359,68 +282,54 @@ draw();</pre> return localdb.put(...); }).catch(function (err) { console.log(err); -});</pre> +}); +``` -<p>ou encore :</p> +ou encore : -<pre class="brush: js">remotedb.allDocs(...) -.then(resultOfAllDocs => { +```js +remotedb.allDocs(...) +.then(resultOfAllDocs => { return localdb.put(...); }) -.then(resultOfPut => { +.then(resultOfPut => { return localdb.get(...); }) -.then(resultOfGet => { +.then(resultOfGet => { return localdb.put(...); }) -.catch(err => console.log(err));</pre> +.catch(err => console.log(err)); +``` -<p>Cela couvre une grande partie des éléments de base. Pour un traitement beaucoup plus complet, voir l'excellent article <a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Nous avons un problème avec les promesses</a> <small>(en)</small>, par Nolan Lawson.</p> +Cela couvre une grande partie des éléments de base. Pour un traitement beaucoup plus complet, voir l'excellent article [Nous avons un problème avec les promesses](https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html) (en), par Nolan Lawson. -<h3 id="browser_compatibility_5">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>{{Compat("javascript.builtins.Promise")}}</p> +{{Compat("javascript.builtins.Promise")}} -<h3 id="further_information_5">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Web/JavaScript/Guide/Using_promises">Utiliser les promesses</a></li> - <li>Page de référence pour <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Promise</code></a></li> -</ul> +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Utiliser les promesses](/fr/docs/Web/JavaScript/Guide/Using_promises) +- Page de référence pour [`Promise`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) -<h2 id="Promise.all">Promise.all()</h2> +## Promise.all() -<p>Une fonction JavaScript qui vous permet d'attendre que plusieurs promesses se terminent avant d'exécuter une autre opération basée sur les résultats de toutes les autres promesses.</p> +Une fonction JavaScript qui vous permet d'attendre que plusieurs promesses se terminent avant d'exécuter une autre opération basée sur les résultats de toutes les autres promesses. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Non</td> - <td>Non</td> - <td>Non</td> - <td>Oui</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ----------------- | ---------------------------------- | -------------------------------- | +| Non | Non | Non | Oui | -<h3 id="code_example_6">Exemple de code</h3> +### Exemple de code -<p>L'exemple suivant va chercher plusieurs ressources sur le serveur, et utilise <code>Promise.all()</code> pour attendre qu'elles soient toutes disponibles avant de les afficher toutes — <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html">le voir fonctionner</a>, et voir son <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">code source</a> :</p> +L'exemple suivant va chercher plusieurs ressources sur le serveur, et utilise `Promise.all()` pour attendre qu'elles soient toutes disponibles avant de les afficher toutes — [le voir fonctionner](https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html), et voir son [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html) : -<pre class="brush: js">function fetchAndDecode(url, type) { +```js +function fetchAndDecode(url, type) { // Retourner la promesse de niveau supérieur, de sorte que le résultat // de l'ensemble de la chaîne est retourné hors de la fonction - return fetch(url).then(response => { + return fetch(url).then(response => { // Selon le type de fichier recherché, utilisez la fonction appropriée pour décoder son contenu if(type === 'blob') { return response.blob(); @@ -428,7 +337,7 @@ draw();</pre> return response.text(); } }) - .catch(e => { + .catch(e => { console.log(`Il y a eu un problème avec votre opération de récupération de la ressource "${url}" : ` + e.message); }); } @@ -441,7 +350,7 @@ let description = fetchAndDecode('description.txt', 'text'); // Utiliser Promise.all() pour exécuter le code uniquement lorsque // les trois appels de fonction ont été résolus -Promise.all([coffee, tea, description]).then(values => { +Promise.all([coffee, tea, description]).then(values => { console.log(values); // Stocker chaque valeur retournée par les promesses dans des variables séparées ; // créer des URL d'objets à partir des blobs. @@ -449,7 +358,7 @@ Promise.all([coffee, tea, description]).then(values => { let objectURL2 = URL.createObjectURL(values[1]); let descText = values[2]; - // Afficher les images dans les éléments <img> + // Afficher les images dans les éléments <img> let image1 = document.createElement('img'); let image2 = document.createElement('img'); image1.src = objectURL1; @@ -461,54 +370,36 @@ Promise.all([coffee, tea, description]).then(values => { let para = document.createElement('p'); para.textContent = descText; document.body.appendChild(para); -});</pre> +}); +``` -<h3 id="pitfalls_6">Pièges</h3> +### Pièges -<ul> - <li>Si <code>Promesse.all()</code> est rejeté, alors une ou plusieurs des promesses que vous lui fournissez dans son paramètre de tableau doivent être rejetées, ou pourraient ne pas retourner de promesses du tout. Vous devez vérifier chacune d'entre elles pour voir ce qu'elles ont retourné.</li> -</ul> +- Si `Promesse.all()` est rejeté, alors une ou plusieurs des promesses que vous lui fournissez dans son paramètre de tableau doivent être rejetées, ou pourraient ne pas retourner de promesses du tout. Vous devez vérifier chacune d'entre elles pour voir ce qu'elles ont retourné. -<h3 id="browser_compatibility_6">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>{{Compat("javascript.builtins.Promise.all")}}</p> +{{Compat("javascript.builtins.Promise.all")}} -<h3 id="further_information_6">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises#running_code_in_response_to_multiple_promises_fulfilling">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li>Page de référence pour <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/all"><code>Promise.all()</code></a></li> -</ul> +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises#running_code_in_response_to_multiple_promises_fulfilling) +- Page de référence pour [`Promise.all()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) -<h2 id="Asyncawait">async/await</h2> +## async/await -<p>Un outil syntaxique construit sur les promesses qui vous permet d'exécuter des opérations asynchrones en utilisant une syntaxe qui ressemble plus à l'écriture de code de rappel synchrone.</p> +Un outil syntaxique construit sur les promesses qui vous permet d'exécuter des opérations asynchrones en utilisant une syntaxe qui ressemble plus à l'écriture de code de rappel synchrone. -<table class="standard-table"> - <caption>Utile pour…</caption> - <thead> - <tr> - <th scope="col">Opération unique retardée</th> - <th scope="col">Opération répétée</th> - <th scope="col">Opérations séquentielles multiples</th> - <th scope="col">Opérations simultanées multiples</th> - </tr> - </thead> - <tbody> - <tr> - <td>Non</td> - <td>Non</td> - <td>Oui</td> - <td>Oui (en combinaison avec <code>Promise.all()</code>)</td> - </tr> - </tbody> -</table> +| Opération unique retardée | Opération répétée | Opérations séquentielles multiples | Opérations simultanées multiples | +| ------------------------- | ----------------- | ---------------------------------- | ----------------------------------------- | +| Non | Non | Oui | Oui (en combinaison avec `Promise.all()`) | -<h3 id="code_example_7">Exemple de code</h3> +### Exemple de code -<p>L'exemple suivant est un remaniement de l'exemple simple de promesse que nous avons vu précédemment, qui récupère et affiche une image, écrit à l'aide d'async/await (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-refactored-fetch.html">voir en direct</a>, et voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-refactored-fetch.html">code source</a>) :</p> +L'exemple suivant est un remaniement de l'exemple simple de promesse que nous avons vu précédemment, qui récupère et affiche une image, écrit à l'aide d'async/await ([voir en direct](https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-refactored-fetch.html), et voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-refactored-fetch.html)) : -<pre class="brush: js">async function myFetch() { +```js +async function myFetch() { let response = await fetch('coffee.jpg'); let myBlob = await response.blob(); @@ -518,36 +409,31 @@ Promise.all([coffee, tea, description]).then(values => { document.body.appendChild(image); } -myFetch();</pre> +myFetch(); +``` -<h3 id="pitfalls_7">Pièges</h3> +### Pièges -<ul> - <li>Vous ne pouvez pas utiliser l'opérateur <code>await</code> à l'intérieur d'une fonction non-<code>async</code>, ou dans le contexte de haut niveau de votre code. Cela peut parfois entraîner la création d'une fonction encapsulante supplémentaire, ce qui peut être légèrement frustrant dans certaines circonstances. Mais cela en vaut la peine la plupart du temps.</li> - <li>Le support des navigateurs pour <code>async</code>/<code>await</code> n'est pas aussi bon que celui des promesses. Si vous souhaitez utiliser <code>async</code>/<code>await</code> mais que vous êtes préoccupé par la prise en charge de navigateurs plus anciens, vous pouvez envisager d'utiliser la bibliothèque <a href="https://babeljs.io/">BabelJS</a> — cela vous permet d'écrire vos applications en utilisant le JavaScript le plus récent et de laisser Babel déterminer les modifications éventuellement nécessaires pour les navigateurs de vos utilisateurs.</li> -</ul> +- Vous ne pouvez pas utiliser l'opérateur `await` à l'intérieur d'une fonction non-`async`, ou dans le contexte de haut niveau de votre code. Cela peut parfois entraîner la création d'une fonction encapsulante supplémentaire, ce qui peut être légèrement frustrant dans certaines circonstances. Mais cela en vaut la peine la plupart du temps. +- Le support des navigateurs pour `async`/`await` n'est pas aussi bon que celui des promesses. Si vous souhaitez utiliser `async`/`await` mais que vous êtes préoccupé par la prise en charge de navigateurs plus anciens, vous pouvez envisager d'utiliser la bibliothèque [BabelJS](https://babeljs.io/) — cela vous permet d'écrire vos applications en utilisant le JavaScript le plus récent et de laisser Babel déterminer les modifications éventuellement nécessaires pour les navigateurs de vos utilisateurs. -<h3 id="browser_compatibility_7">Compatibilité des navigateurs</h3> +### Compatibilité des navigateurs -<p>{{Compat("javascript.statements.async_function")}}</p> +{{Compat("javascript.statements.async_function")}} -<h3 id="further_information_7">Plus d'informations</h3> +### Plus d'informations -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec <code>async</code> et <code>await</code></a></li> - <li>Page de référence pour <a href="/fr/docs/Web/JavaScript/Reference/Statements/async_function">les fonctions asynchrones</a></li> - <li>Page de référence pour l'opérateur <a href="/fr/docs/Web/JavaScript/Reference/Operators/await">await</a></li> -</ul> +- [Faciliter la programmation asynchrone avec `async` et `await`](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- Page de référence pour [les fonctions asynchrones](/fr/docs/Web/JavaScript/Reference/Statements/async_function) +- Page de référence pour l'opérateur [await](/fr/docs/Web/JavaScript/Reference/Operators/await) -<p>{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</p> +{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}} -<h2 id="In_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec <code>async</code> et <code>await</code></a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li> -</ul> +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Faciliter la programmation asynchrone avec `async` et `await`](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) diff --git a/files/fr/learn/javascript/asynchronous/concepts/index.md b/files/fr/learn/javascript/asynchronous/concepts/index.md index ee10969b47..03dc27feaf 100644 --- a/files/fr/learn/javascript/asynchronous/concepts/index.md +++ b/files/fr/learn/javascript/asynchronous/concepts/index.md @@ -10,46 +10,53 @@ tags: - blocking translation_of: Learn/JavaScript/Asynchronous/Concepts --- -<div>{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}</div> +{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}} -<p>Dans cet article, nous allons passer en revue un certain nombre de concepts importants relatifs à la programmation asynchrone et à la façon dont elle se présente dans les navigateurs web et JavaScript. Vous devriez comprendre ces concepts avant de travailler sur les autres articles du module.</p> +Dans cet article, nous allons passer en revue un certain nombre de concepts importants relatifs à la programmation asynchrone et à la façon dont elle se présente dans les navigateurs web et JavaScript. Vous devriez comprendre ces concepts avant de travailler sur les autres articles du module. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript.</td> + <td> + Connaissances informatiques de base, compréhension raisonnable des + principes fondamentaux de JavaScript. + </td> </tr> <tr> <th scope="row">Objectif :</th> - <td>Comprendre les concepts de base de la programmation asynchrone et la façon dont elles se manifestent dans les navigateurs Web et dans JavaScript.</td> + <td> + Comprendre les concepts de base de la programmation asynchrone et la + façon dont elles se manifestent dans les navigateurs Web et dans + JavaScript. + </td> </tr> </tbody> </table> -<h2 id="asynchronous">Asynchrone ?</h2> +## Asynchrone ? -<p>Normalement, le code d'un programme donné se déroule sans interruption, une seule chose se produisant à la fois. Si une fonction dépend du résultat d'une autre fonction, elle doit attendre que l'autre fonction se termine et retourne sa réponse, et jusqu'à ce que cela se produise, le programme entier est essentiellement bloqué du point de vue de l'utilisateur.</p> +Normalement, le code d'un programme donné se déroule sans interruption, une seule chose se produisant à la fois. Si une fonction dépend du résultat d'une autre fonction, elle doit attendre que l'autre fonction se termine et retourne sa réponse, et jusqu'à ce que cela se produise, le programme entier est essentiellement bloqué du point de vue de l'utilisateur. -<p>Les utilisatrices et utilisateurs de macOS, par exemple, le voient parfois avec le curseur rotatif de couleur arc-en-ciel (ou « ballon de plage », comme on l'appelle souvent). Ce curseur est la façon dont le système d'exploitation dit "le programme que vous utilisez actuellement a dû s'arrêter et attendre que quelque chose se termine, et cela prend tellement de temps que je craignais que vous vous demandiez ce qui se passe".</p> +Les utilisatrices et utilisateurs de macOS, par exemple, le voient parfois avec le curseur rotatif de couleur arc-en-ciel (ou « ballon de plage », comme on l'appelle souvent). Ce curseur est la façon dont le système d'exploitation dit "le programme que vous utilisez actuellement a dû s'arrêter et attendre que quelque chose se termine, et cela prend tellement de temps que je craignais que vous vous demandiez ce qui se passe". -<p><img alt="Spinner multicolore pour macOS avec ballon de plage." src="beachball.jpg"></p> + +C'est une expérience frustrante qui n'est pas une bonne utilisation de la puissance de traitement de l'ordinateur, surtout à une époque où les ordinateurs disposent de plusieurs cœurs de processeur. Il est inutile de rester assis à attendre quelque chose alors que vous pouvez laisser une tâche se dérouler sur un autre cœur de processeur et être averti quand elle a terminé. Cela vous permet d'effectuer d'autres travaux en même temps, ce qui est la base de la **programmation asynchrone**. C'est à l'environnement de programmation que vous utilisez (les navigateurs web, dans le cas du développement web) de vous fournir des API qui vous permettent d'exécuter de telles tâches de manière asynchrone. -<p>C'est une expérience frustrante qui n'est pas une bonne utilisation de la puissance de traitement de l'ordinateur, surtout à une époque où les ordinateurs disposent de plusieurs cœurs de processeur. Il est inutile de rester assis à attendre quelque chose alors que vous pouvez laisser une tâche se dérouler sur un autre cœur de processeur et être averti quand elle a terminé. Cela vous permet d'effectuer d'autres travaux en même temps, ce qui est la base de la <strong>programmation asynchrone</strong>. C'est à l'environnement de programmation que vous utilisez (les navigateurs web, dans le cas du développement web) de vous fournir des API qui vous permettent d'exécuter de telles tâches de manière asynchrone.</p> +## Code bloquant -<h2 id="blocking_code">Code bloquant</h2> +Les techniques asynchrones sont très utiles, notamment dans la programmation web. Lorsqu'une application web s'exécute dans un navigateur et qu'elle exécute un morceau de code considérable sans rendre le contrôle au navigateur, ce dernier peut sembler figé. C'est ce qu'on appelle du code **bloquant** ; le navigateur est incapable de continuer à traiter les entrées de l'utilisateur et d'effectuer d'autres tâches jusqu'à ce que l'application web rende le contrôle du processeur. -<p>Les techniques asynchrones sont très utiles, notamment dans la programmation web. Lorsqu'une application web s'exécute dans un navigateur et qu'elle exécute un morceau de code considérable sans rendre le contrôle au navigateur, ce dernier peut sembler figé. C'est ce qu'on appelle du code <strong>bloquant</strong> ; le navigateur est incapable de continuer à traiter les entrées de l'utilisateur et d'effectuer d'autres tâches jusqu'à ce que l'application web rende le contrôle du processeur.</p> +Examinons quelques exemples qui montrent ce que nous entendons par blocage. -<p>Examinons quelques exemples qui montrent ce que nous entendons par blocage.</p> +Dans notre exemple [simple-sync.html](https://github.com/mdn/learning-area/tree/master/javascript/asynchronous/introducing/simple-sync.html) ([voir le fonctionnement en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html)), nous ajoutons un écouteur d'événement de clic à un bouton de sorte que, lorsqu'il est cliqué, il exécute une opération qui prend du temps (calcule 10 millions de dates puis enregistre la dernière dans la console) et ajoute ensuite un paragraphe au DOM : -<p>Dans notre exemple <a href="https://github.com/mdn/learning-area/tree/master/javascript/asynchronous/introducing/simple-sync.html">simple-sync.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html">voir le fonctionnement en direct</a>), nous ajoutons un écouteur d'événement de clic à un bouton de sorte que, lorsqu'il est cliqué, il exécute une opération qui prend du temps (calcule 10 millions de dates puis enregistre la dernière dans la console) et ajoute ensuite un paragraphe au DOM :</p> - -<pre class="brush: js">const btn = document.querySelector('button'); -btn.addEventListener('click', () => { +```js +const btn = document.querySelector('button'); +btn.addEventListener('click', () => { let myDate; - for(let i = 0; i < 10000000; i++) { + for(let i = 0; i < 10000000; i++) { let date = new Date(); myDate = date; } @@ -59,23 +66,21 @@ btn.addEventListener('click', () => { let pElem = document.createElement('p'); pElem.textContent = `Il s'agit d'un paragraphe nouvellement ajouté.`; document.body.appendChild(pElem); -});</pre> +}); +``` -<p>Lorsque vous exécutez l'exemple, ouvrez votre console JavaScript, puis cliquez sur le bouton. Vous remarquerez que le paragraphe n'apparaît qu'une fois que le calcul des dates est terminé et que le message de la console a été enregistré. Le code s'exécute dans l'ordre où il apparaît dans la source, et la dernière opération ne s'exécute pas tant que la première n'est pas terminée.</p> +Lorsque vous exécutez l'exemple, ouvrez votre console JavaScript, puis cliquez sur le bouton. Vous remarquerez que le paragraphe n'apparaît qu'une fois que le calcul des dates est terminé et que le message de la console a été enregistré. Le code s'exécute dans l'ordre où il apparaît dans la source, et la dernière opération ne s'exécute pas tant que la première n'est pas terminée. -<div class="note"> - <p><strong>Note :</strong> L'exemple précédent est très peu réaliste. Vous ne calculeriez jamais 10 millions de dates sur une véritable application web ! Il sert cependant à vous donner l'idée de base.</p> -</div> +> **Note :** L'exemple précédent est très peu réaliste. Vous ne calculeriez jamais 10 millions de dates sur une véritable application web ! Il sert cependant à vous donner l'idée de base. -<p>Dans notre deuxième exemple, <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">simple-sync-ui-blocking.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">voir en direct</a>), nous simulons quelque chose de légèrement plus réaliste que vous pourriez rencontrer sur une page réelle. Nous bloquons l'interactivité de l'utilisateur avec le rendu de l'interface utilisateur. Dans cet exemple, nous avons deux boutons :</p> +Dans notre deuxième exemple, [simple-sync-ui-blocking.html](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-ui-blocking.html) ([voir en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-ui-blocking.html)), nous simulons quelque chose de légèrement plus réaliste que vous pourriez rencontrer sur une page réelle. Nous bloquons l'interactivité de l'utilisateur avec le rendu de l'interface utilisateur. Dans cet exemple, nous avons deux boutons : -<ul> - <li>Un bouton "Remplir le canevas" qui, lorsqu'il est cliqué, remplit le <a href="/fr/docs/Web/HTML/Element/canvas"><code><canvas></code></a> disponible avec 1 million de cercles bleus.</li> - <li>Un bouton "Cliquez sur moi pour l'alerte" qui, lorsqu'il est cliqué, affiche un message d'alerte.</li> -</ul> +- Un bouton "Remplir le canevas" qui, lorsqu'il est cliqué, remplit le [`<canvas>`](/fr/docs/Web/HTML/Element/canvas) disponible avec 1 million de cercles bleus. +- Un bouton "Cliquez sur moi pour l'alerte" qui, lorsqu'il est cliqué, affiche un message d'alerte. -<pre class="brush: js">function expensiveOperation() { - for(let i = 0; i < 1000000; i++) { +```js +function expensiveOperation() { + for(let i = 0; i < 1000000; i++) { ctx.fillStyle = 'rgba(0,0,255, 0.2)'; ctx.beginPath(); ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false); @@ -85,81 +90,78 @@ btn.addEventListener('click', () => { fillBtn.addEventListener('click', expensiveOperation); -alertBtn.addEventListener('click', () => +alertBtn.addEventListener('click', () => alert('Vous avez cliqué sur moi !'); -);</pre> +); +``` -<p>Si vous cliquez sur le premier bouton, puis rapidement sur le second, vous verrez que l'alerte n'apparaît pas avant que les cercles aient fini d'être rendus. La première opération bloque la seconde jusqu'à ce qu'elle ait fini de s'exécuter.</p> +Si vous cliquez sur le premier bouton, puis rapidement sur le second, vous verrez que l'alerte n'apparaît pas avant que les cercles aient fini d'être rendus. La première opération bloque la seconde jusqu'à ce qu'elle ait fini de s'exécuter. -<div class="note"> - <p><strong>Note :</strong> D'accord, dans notre cas, c'est laid et nous simulons l'effet de blocage, mais il s'agit d'un problème courant contre lequel les développeuses et développeurs d'applications réelles se battent sans cesse pour atténuer les impacts indésirables.</p> -</div> +> **Note :** D'accord, dans notre cas, c'est laid et nous simulons l'effet de blocage, mais il s'agit d'un problème courant contre lequel les développeuses et développeurs d'applications réelles se battent sans cesse pour atténuer les impacts indésirables. -<p>Pourquoi ? La réponse est que JavaScript, de manière générale, ne s'exécute que sur <strong>un seul <i>thread</i></strong>. À ce stade, nous devons introduire le concept de <strong><i>threads</i></strong>.</p> +Pourquoi ? La réponse est que JavaScript, de manière générale, ne s'exécute que sur **un seul _thread_**. À ce stade, nous devons introduire le concept de **_threads_**. -<h2 id="threads">Les threads</h2> +## Les threads -<p>Un <strong><i>thread</i></strong> est fondamentalement un processus unique qu'un programme peut utiliser pour accomplir des tâches. Chaque <i>thread</i> ne peut effectuer qu'une seule tâche à la fois :</p> +Un **_thread_** est fondamentalement un processus unique qu'un programme peut utiliser pour accomplir des tâches. Chaque _thread_ ne peut effectuer qu'une seule tâche à la fois : -<pre>Tâche A --> Tâche B --> Tâche C</pre> + Tâche A --> Tâche B --> Tâche C -<p>Chaque tâche sera exécutée de manière séquentielle ; une tâche doit être terminée avant que la suivante puisse être lancée.</p> +Chaque tâche sera exécutée de manière séquentielle ; une tâche doit être terminée avant que la suivante puisse être lancée. -<p>Comme nous l'avons dit précédemment, de nombreux ordinateurs sont désormais dotés de plusieurs cœurs et peuvent donc faire plusieurs choses à la fois. Les langages de programmation qui prennent en charge plusieurs processus peuvent utiliser plusieurs cœurs pour accomplir de multiples tâches simultanément :</p> +Comme nous l'avons dit précédemment, de nombreux ordinateurs sont désormais dotés de plusieurs cœurs et peuvent donc faire plusieurs choses à la fois. Les langages de programmation qui prennent en charge plusieurs processus peuvent utiliser plusieurs cœurs pour accomplir de multiples tâches simultanément : -<pre>Processus 1: Tâche A --> Tâche B -Processus 2: Tâche C --> Tâche D</pre> + Processus 1: Tâche A --> Tâche B + Processus 2: Tâche C --> Tâche D -<h3 id="javascript_is_single-threaded">JavaScript n'a qu'un thread</h3> +### JavaScript n'a qu'un thread -<p>JavaScript est traditionnellement « single-threaded ». Même avec plusieurs cœurs, vous ne pouviez le faire exécuter des tâches que sur un seul processus, appelé le <strong>main thread</strong>. Notre exemple ci-dessus est exécuté comme ceci :</p> +JavaScript est traditionnellement « single-threaded ». Même avec plusieurs cœurs, vous ne pouviez le faire exécuter des tâches que sur un seul processus, appelé le **main thread**. Notre exemple ci-dessus est exécuté comme ceci : -<pre>processus principal : Rendre des cercles dans <canvas> --> Afficher alert()</pre> + processus principal : Rendre des cercles dans <canvas> --> Afficher alert() -<p>Après un certain temps, JavaScript a gagné quelques outils pour aider à résoudre de tels problèmes. <a href="/fr/docs/Web/API/Web_Workers_API">Les Web workers</a> vous permettent d'envoyer une partie du traitement JavaScript hors d'un processus distinct, appelé worker, afin que vous puissiez exécuter plusieurs morceaux JavaScript simultanément. Vous utiliserez généralement un worker pour exécuter des processus coûteux hors du processus principal afin de ne pas bloquer l'interaction avec l'utilisateur.</p> +Après un certain temps, JavaScript a gagné quelques outils pour aider à résoudre de tels problèmes. [Les Web workers](/fr/docs/Web/API/Web_Workers_API) vous permettent d'envoyer une partie du traitement JavaScript hors d'un processus distinct, appelé worker, afin que vous puissiez exécuter plusieurs morceaux JavaScript simultanément. Vous utiliserez généralement un worker pour exécuter des processus coûteux hors du processus principal afin de ne pas bloquer l'interaction avec l'utilisateur. -<pre>Processus principal : Tâche A --> Tâche C -Processus du Worker : Tâche coûteuse B</pre> + Processus principal : Tâche A --> Tâche C + Processus du Worker : Tâche coûteuse B -<p>Dans cette optique, jetez un coup d'œil à <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-worker.html">simple-sync-worker.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-worker.html">voyez-le fonctionner en direct</a>), toujours avec la console JavaScript de votre navigateur ouverte. Il s'agit d'une réécriture de notre exemple précédent qui calcule les 10 millions de dates dans un fil de travail (<i>worker</i>) séparé. Vous pouvez voir le code du <i>worker</i> ici : <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/worker.js">worker.js</a>. Désormais, lorsque vous cliquez sur le bouton, le navigateur est capable d'afficher le paragraphe avant que les dates n'aient fini d'être calculées. La première opération ne bloque plus la seconde et une fois que le <i>worker</i> a fini ses calculs, la date est affichée dans la console.</p> +Dans cette optique, jetez un coup d'œil à [simple-sync-worker.html](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-worker.html) ([voyez-le fonctionner en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-worker.html)), toujours avec la console JavaScript de votre navigateur ouverte. Il s'agit d'une réécriture de notre exemple précédent qui calcule les 10 millions de dates dans un fil de travail (_worker_) séparé. Vous pouvez voir le code du _worker_ ici : [worker.js](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/worker.js). Désormais, lorsque vous cliquez sur le bouton, le navigateur est capable d'afficher le paragraphe avant que les dates n'aient fini d'être calculées. La première opération ne bloque plus la seconde et une fois que le _worker_ a fini ses calculs, la date est affichée dans la console. -<h2 id="asynchronous_code">Code asynchrone</h2> +## Code asynchrone -<p>Les web workers sont très utiles, mais ils ont leurs limites. L'une des principales est qu'ils ne peuvent pas accéder au <a href="/fr/docs/Glossary/DOM">DOM</a>. Vous ne pouvez pas demander à un worker de faire directement quelque chose pour mettre à jour l'interface utilisateur. Nous n'avons pas pu rendre nos 1 million de cercles bleus à l'intérieur de notre worker ; il ne peut faire que le calcul des chiffres.</p> +Les web workers sont très utiles, mais ils ont leurs limites. L'une des principales est qu'ils ne peuvent pas accéder au [DOM](/fr/docs/Glossary/DOM). Vous ne pouvez pas demander à un worker de faire directement quelque chose pour mettre à jour l'interface utilisateur. Nous n'avons pas pu rendre nos 1 million de cercles bleus à l'intérieur de notre worker ; il ne peut faire que le calcul des chiffres. -<p>Le deuxième problème est que, bien que le code exécuté dans un worker ne soit pas bloquant, il reste fondamentalement synchrone. Cela devient un problème lorsqu'une fonction s'appuie sur les résultats de plusieurs processus précédents pour fonctionner. Considérons les diagrammes de processus suivants :</p> +Le deuxième problème est que, bien que le code exécuté dans un worker ne soit pas bloquant, il reste fondamentalement synchrone. Cela devient un problème lorsqu'une fonction s'appuie sur les résultats de plusieurs processus précédents pour fonctionner. Considérons les diagrammes de processus suivants : -<pre>Processus principal : Tâche A --> Tâche B</pre> + Processus principal : Tâche A --> Tâche B -<p>Dans ce cas, disons que la tâche A fait quelque chose comme récupérer une image du serveur et que la tâche B fait ensuite quelque chose à l'image comme lui appliquer un filtre. Si vous lancez la tâche A et essayez immédiatement d'exécuter la tâche B, vous obtiendrez une erreur, car l'image ne sera pas encore disponible.</p> +Dans ce cas, disons que la tâche A fait quelque chose comme récupérer une image du serveur et que la tâche B fait ensuite quelque chose à l'image comme lui appliquer un filtre. Si vous lancez la tâche A et essayez immédiatement d'exécuter la tâche B, vous obtiendrez une erreur, car l'image ne sera pas encore disponible. -<pre>Processus principal : Tâche A --> Tâche B --> |Tâche D| -Processus du Worker : Tâche C --------------> | |</pre> + Processus principal : Tâche A --> Tâche B --> |Tâche D| + Processus du Worker : Tâche C --------------> | | -<p>Dans ce cas, disons que la tâche D utilise les résultats de la tâche B et de la tâche C. Si nous pouvons garantir que ces résultats seront tous deux disponibles au même moment, alors nous pourrions être OK, mais c'est peu probable. Si la tâche D tente de s'exécuter alors que l'une de ses entrées n'est pas encore disponible, elle déclenchera une erreur.</p> +Dans ce cas, disons que la tâche D utilise les résultats de la tâche B et de la tâche C. Si nous pouvons garantir que ces résultats seront tous deux disponibles au même moment, alors nous pourrions être OK, mais c'est peu probable. Si la tâche D tente de s'exécuter alors que l'une de ses entrées n'est pas encore disponible, elle déclenchera une erreur. -<p>Pour résoudre ces problèmes, les navigateurs nous permettent d'exécuter certaines opérations de manière asynchrone. Des fonctionnalités telles que <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Promise</code></a> permettent de lancer une opération (par exemple, la récupération d'une image sur le serveur), puis d'attendre le retour du résultat avant de lancer une autre opération :</p> +Pour résoudre ces problèmes, les navigateurs nous permettent d'exécuter certaines opérations de manière asynchrone. Des fonctionnalités telles que [`Promise`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) permettent de lancer une opération (par exemple, la récupération d'une image sur le serveur), puis d'attendre le retour du résultat avant de lancer une autre opération : -<pre>Processus principal : Tâche A Tâche B -Promesse : |__opération asynchrone__|</pre> + Processus principal : Tâche A Tâche B + Promesse : |__opération asynchrone__| -<p>Comme l'opération se déroule ailleurs, le processus principal n'est pas bloqué pendant le traitement de l'opération asynchrone.</p> +Comme l'opération se déroule ailleurs, le processus principal n'est pas bloqué pendant le traitement de l'opération asynchrone. -<p>Nous allons commencer à examiner comment écrire du code asynchrone dans le prochain article. C'est passionnant, non ? Bonne lecture !</p> +Nous allons commencer à examiner comment écrire du code asynchrone dans le prochain article. C'est passionnant, non ? Bonne lecture ! -<h2 id="conclusion">Conclusion</h2> +## Conclusion -<p>La conception de logiciels modernes s'articule de plus en plus autour de l'utilisation de la programmation asynchrone, afin de permettre aux programmes de faire plusieurs choses à la fois. À mesure que vous utilisez des API plus récentes et plus puissantes, vous trouverez de plus en plus de cas où la seule façon de faire les choses est asynchrone. Il était autrefois difficile d'écrire du code asynchrone. Il faut encore s'y habituer, mais c'est devenu beaucoup plus facile. Dans la suite de ce module, nous étudierons plus en détail pourquoi le code asynchrone est important et comment concevoir un code qui évite certains des problèmes décrits ci-dessus.</p> +La conception de logiciels modernes s'articule de plus en plus autour de l'utilisation de la programmation asynchrone, afin de permettre aux programmes de faire plusieurs choses à la fois. À mesure que vous utilisez des API plus récentes et plus puissantes, vous trouverez de plus en plus de cas où la seule façon de faire les choses est asynchrone. Il était autrefois difficile d'écrire du code asynchrone. Il faut encore s'y habituer, mais c'est devenu beaucoup plus facile. Dans la suite de ce module, nous étudierons plus en détail pourquoi le code asynchrone est important et comment concevoir un code qui évite certains des problèmes décrits ci-dessus. -<div>{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}</div> +{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}} -<h2 id="in_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li> -</ul> +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Faciliter la programmation asynchrone avec async et await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) diff --git a/files/fr/learn/javascript/asynchronous/index.md b/files/fr/learn/javascript/asynchronous/index.md index 0688d5de42..c555f017df 100644 --- a/files/fr/learn/javascript/asynchronous/index.md +++ b/files/fr/learn/javascript/asynchronous/index.md @@ -17,46 +17,41 @@ tags: - setTimeout translation_of: Learn/JavaScript/Asynchronous --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}} -<p>Dans ce module, nous examinons le <a href="/fr/docs/Glossary/JavaScript">JavaScript</a> <a href="/fr/docs/Glossary/Asynchronous">asynchrone</a>, pourquoi il est important et comment il peut être utilisé afin de gérer efficacement les opérations potentiellement bloquantes telles que la récupération de ressources sur un serveur.</p> +Dans ce module, nous examinons le [JavaScript](/fr/docs/Glossary/JavaScript) [asynchrone](/fr/docs/Glossary/Asynchronous), pourquoi il est important et comment il peut être utilisé afin de gérer efficacement les opérations potentiellement bloquantes telles que la récupération de ressources sur un serveur. -<div class="callout"> - <p>Vous cherchez à devenir une développeuse ou un développeur web front-end ?</p> - <p>Nous avons élaboré un cours qui comprend toutes les informations essentielles dont vous avez besoin pour atteindre votre objectif.</p> - <p><a href="/fr/docs/Learn/Front-end_web_developer">Commencer</a> - </p> -</div> +> **Remarque :** +> +> Vous cherchez à devenir une développeuse ou un développeur web front-end ? +> +> Nous avons élaboré un cours qui comprend toutes les informations essentielles dont vous avez besoin pour atteindre votre objectif. +> +> [Commencer](/fr/docs/Learn/Front-end_web_developer) -<h2 id="prerequisites">Prérequis</h2> +## Prérequis -<p>Le JavaScript asynchrone est un sujet assez avancé, et il vous est conseillé de travailler sur les modules <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction de JavaScript</a> avant d'attaquer cette leçon.</p> +Le JavaScript asynchrone est un sujet assez avancé, et il vous est conseillé de travailler sur les modules [Premiers pas en JavaScript](/fr/docs/Learn/JavaScript/First_steps) et [Blocs de construction de JavaScript](/fr/docs/Learn/JavaScript/Building_blocks) avant d'attaquer cette leçon. -<p>Si vous n'êtes pas familier avec le concept de programmation asynchrone, vous devriez absolument commencer par l'article <a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a> de ce module. Si vous connaissez ce concept, vous pouvez probablement passer directement au module <a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a>.</p> +Si vous n'êtes pas familier avec le concept de programmation asynchrone, vous devriez absolument commencer par l'article [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) de ce module. Si vous connaissez ce concept, vous pouvez probablement passer directement au module [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing). -<div class="note"> - <p><strong>Note :</strong> Si vous travaillez sur un ordinateur/tablette/autre appareil où vous n'avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer (la plupart) des exemples de code dans un programme de codage en ligne tel que <a href="https://jsbin.com/">JSBin</a> ou <a href="https://glitch.com">Glitch</a>.</p> -</div> +> **Note :** Si vous travaillez sur un ordinateur/tablette/autre appareil où vous n'avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer (la plupart) des exemples de code dans un programme de codage en ligne tel que [JSBin](https://jsbin.com/) ou [Glitch](https://glitch.com). -<h2 id="guides">Guides</h2> +## Guides -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></dt> - <dd>Dans cet article, nous allons passer en revue un certain nombre de concepts importants relatifs à la programmation asynchrone et à la façon dont elle se présente dans les navigateurs web et JavaScript. Vous devez comprendre ces concepts avant de travailler sur les autres articles du module.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></dt> - <dd>Dans cet article, nous récapitulons brièvement les problèmes associés au JavaScript synchrone, et nous jetons un premier coup d'œil à certaines des différentes techniques JavaScript asynchrones que vous rencontrerez, en montrant comment elles peuvent nous aider à résoudre ces problèmes.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></dt> - <dd>Nous examinons ici les méthodes traditionnelles dont dispose JavaScript pour exécuter du code de manière asynchrone après l'écoulement d'une période déterminée ou à un intervalle régulier (par exemple, un nombre déterminé de fois par seconde), nous expliquons à quoi elles servent et nous examinons leurs problèmes inhérents.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></dt> - <dd>Les promesses sont une fonctionnalité relativement nouvelle du langage JavaScript qui vous permet de reporter d'autres actions jusqu'à ce que l'action précédente soit terminée, ou de réagir à son échec. C'est très utile pour mettre en place une séquence d'opérations qui fonctionne correctement. Cet article vous montre comment les promesses fonctionnent, où vous les verrez utilisées dans les API Web et comment écrire les vôtres.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></dt> - <dd>Les promesses peuvent être quelque peu complexes à mettre en place et à comprendre, c'est pourquoi les navigateurs modernes ont implémenté les fonctions <code>async</code> et l'opérateur <code>await</code>. Le premier permet aux fonctions standard de se comporter implicitement de manière asynchrone avec les promesses, tandis que le second peut être utilisé à l'intérieur des fonctions <code>async</code> pour attendre les promesses avant que la fonction ne continue. Cela rend l'enchaînement des promesses plus simple et plus facile à lire.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></dt> - <dd>Pour terminer ce module, nous examinerons les différentes techniques et fonctionnalités de codage que nous avons abordées tout au long de ce module, et nous verrons lesquelles vous devez utiliser et à quel moment, avec des recommandations et des rappels des pièges courants le cas échéant.</dd> -</dl> +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) + - : Dans cet article, nous allons passer en revue un certain nombre de concepts importants relatifs à la programmation asynchrone et à la façon dont elle se présente dans les navigateurs web et JavaScript. Vous devez comprendre ces concepts avant de travailler sur les autres articles du module. +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) + - : Dans cet article, nous récapitulons brièvement les problèmes associés au JavaScript synchrone, et nous jetons un premier coup d'œil à certaines des différentes techniques JavaScript asynchrones que vous rencontrerez, en montrant comment elles peuvent nous aider à résoudre ces problèmes. +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) + - : Nous examinons ici les méthodes traditionnelles dont dispose JavaScript pour exécuter du code de manière asynchrone après l'écoulement d'une période déterminée ou à un intervalle régulier (par exemple, un nombre déterminé de fois par seconde), nous expliquons à quoi elles servent et nous examinons leurs problèmes inhérents. +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) + - : Les promesses sont une fonctionnalité relativement nouvelle du langage JavaScript qui vous permet de reporter d'autres actions jusqu'à ce que l'action précédente soit terminée, ou de réagir à son échec. C'est très utile pour mettre en place une séquence d'opérations qui fonctionne correctement. Cet article vous montre comment les promesses fonctionnent, où vous les verrez utilisées dans les API Web et comment écrire les vôtres. +- [Faciliter la programmation asynchrone avec async et await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) + - : Les promesses peuvent être quelque peu complexes à mettre en place et à comprendre, c'est pourquoi les navigateurs modernes ont implémenté les fonctions `async` et l'opérateur `await`. Le premier permet aux fonctions standard de se comporter implicitement de manière asynchrone avec les promesses, tandis que le second peut être utilisé à l'intérieur des fonctions `async` pour attendre les promesses avant que la fonction ne continue. Cela rend l'enchaînement des promesses plus simple et plus facile à lire. +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) + - : Pour terminer ce module, nous examinerons les différentes techniques et fonctionnalités de codage que nous avons abordées tout au long de ce module, et nous verrons lesquelles vous devez utiliser et à quel moment, avec des recommandations et des rappels des pièges courants le cas échéant. -<h2 id="see_also">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="https://eloquentjavascript.net/11_async.html">Programmation asynchrone</a> (en anglais) à partir du fantastique livre en ligne <a href="https://eloquentjavascript.net/">Eloquent JavaScript</a> de Marijn Haverbeke.</li> -</ul> +- [Programmation asynchrone](https://eloquentjavascript.net/11_async.html) (en anglais) à partir du fantastique livre en ligne [Eloquent JavaScript](https://eloquentjavascript.net/) de Marijn Haverbeke. diff --git a/files/fr/learn/javascript/asynchronous/introducing/index.md b/files/fr/learn/javascript/asynchronous/introducing/index.md index 1a352017dd..f86e565338 100644 --- a/files/fr/learn/javascript/asynchronous/introducing/index.md +++ b/files/fr/learn/javascript/asynchronous/introducing/index.md @@ -15,102 +15,108 @@ tags: - callbacks translation_of: Learn/JavaScript/Asynchronous/Introducing --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</div> - -<p>Dans cet article, nous récapitulons brièvement les problèmes associés au JavaScript synchrone, et nous jetons un premier coup d'œil à certaines des différentes techniques asynchrones que vous rencontrerez, en montrant comment elles peuvent nous aider à résoudre ces problèmes.</p> +Dans cet article, nous récapitulons brièvement les problèmes associés au JavaScript synchrone, et nous jetons un premier coup d'œil à certaines des différentes techniques asynchrones que vous rencontrerez, en montrant comment elles peuvent nous aider à résoudre ces problèmes. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript.</td> + <td> + Connaissances informatiques de base, compréhension raisonnable des + principes fondamentaux de JavaScript. + </td> </tr> <tr> <th scope="row">Objectif :</th> - <td>Se familiariser avec ce qu'est le JavaScript asynchrone, comment il diffère du JavaScript synchrone et quels sont ses cas d'utilisation.</td> + <td> + Se familiariser avec ce qu'est le JavaScript asynchrone, comment il + diffère du JavaScript synchrone et quels sont ses cas d'utilisation. + </td> </tr> </tbody> </table> -<h2 id="synchronous_javascript">JavaScript synchrone</h2> +## JavaScript synchrone -<p>Pour nous permettre de comprendre ce qu'est le JavaScript <strong><a href="/fr/docs/Glossary/Asynchronous">asynchrone</a></strong>, nous devons commencer par nous assurer que nous comprenons ce qu'est le JavaScript <strong><a href="/fr/docs/Glossary/Synchronous">synchrone</a></strong>. Cette section récapitule certaines des informations que nous avons vues dans l'article précédent.</p> +Pour nous permettre de comprendre ce qu'est le JavaScript **[asynchrone](/fr/docs/Glossary/Asynchronous)**, nous devons commencer par nous assurer que nous comprenons ce qu'est le JavaScript **[synchrone](/fr/docs/Glossary/Synchronous)**. Cette section récapitule certaines des informations que nous avons vues dans l'article précédent. -<p>Une grande partie des fonctionnalités que nous avons examinées dans les modules précédents du domaine d'apprentissage sont synchrones - vous exécutez un certain code, et le résultat est renvoyé dès que le navigateur peut le faire. Examinons un exemple simple (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html">voir en direct ici</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html">voir la source</a>) :</p> +Une grande partie des fonctionnalités que nous avons examinées dans les modules précédents du domaine d'apprentissage sont synchrones - vous exécutez un certain code, et le résultat est renvoyé dès que le navigateur peut le faire. Examinons un exemple simple ([voir en direct ici](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html), et [voir la source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html)) : -<pre class="brush: js">const btn = document.querySelector('button'); -btn.addEventListener('click', () => { +```js +const btn = document.querySelector('button'); +btn.addEventListener('click', () => { alert(`Vous avez cliqué sur moi !`); let pElem = document.createElement('p'); pElem.textContent = `Il s'agit d'un paragraphe nouvellement ajouté.`; document.body.appendChild(pElem); }); -</pre> +``` + +Dans ce bloc, les lignes sont exécutées les unes après les autres : -<p>Dans ce bloc, les lignes sont exécutées les unes après les autres :</p> +1. Nous saisissons une référence à un élément [`<button>`](/fr/docs/Web/HTML/Element/Button) qui est déjà disponible dans le DOM. +2. Nous lui ajoutons un écouteur d'événements [`click`](/fr/docs/Web/API/Element/click_event) afin que lorsque le bouton est cliqué : -<ol> - <li>Nous saisissons une référence à un élément <a href="/fr/docs/Web/HTML/Element/Button"><code><button></code></a> qui est déjà disponible dans le DOM.</li> - <li>Nous lui ajoutons un écouteur d'événements <code><a href="/fr/docs/Web/API/Element/click_event">click</a></code> afin que lorsque le bouton est cliqué : - <ol> - <li>Un message <code><a href="/fr/docs/Web/API/Window/alert">alert()</a></code> apparaît.</li> - <li>Une fois l'alerte rejetée, nous créons un élément <a href="/fr/docs/Web/HTML/Element/p"><code><p></code></a>.</li> - <li>Nous lui donnons ensuite du contenu textuel.</li> - <li>Enfin, nous ajoutons le paragraphe au corps du document.</li> - </ol> - </li> -</ol> + 1. Un message [`alert()`](/fr/docs/Web/API/Window/alert) apparaît. + 2. Une fois l'alerte rejetée, nous créons un élément [`<p>`](/fr/docs/Web/HTML/Element/p). + 3. Nous lui donnons ensuite du contenu textuel. + 4. Enfin, nous ajoutons le paragraphe au corps du document. -<p>Pendant que chaque opération est en cours de traitement, rien d'autre ne peut se produire - le rendu est mis en pause. Cela est dû au fait que, comme nous l'avons dit dans l'<a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">article précédent</a>, <a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts#javascript_is_single_threaded">JavaScript est ne dispose que d'un seul <i>thread</i></a>. Une seule chose peut se produire à la fois, sur le <i>thread</i> principal, et tout le reste est bloqué jusqu'à la fin d'une opération.</p> +Pendant que chaque opération est en cours de traitement, rien d'autre ne peut se produire - le rendu est mis en pause. Cela est dû au fait que, comme nous l'avons dit dans l'[article précédent](/fr/docs/Learn/JavaScript/Asynchronous/Concepts), [JavaScript est ne dispose que d'un seul _thread_](/fr/docs/Learn/JavaScript/Asynchronous/Concepts#javascript_is_single_threaded). Une seule chose peut se produire à la fois, sur le _thread_ principal, et tout le reste est bloqué jusqu'à la fin d'une opération. -<p>Ainsi, dans l'exemple ci-dessus, après avoir cliqué sur le bouton, le paragraphe n'apparaîtra qu'après avoir appuyé sur le bouton OK dans la boîte d'alerte. Vous pouvez l'essayer vous-même :</p> +Ainsi, dans l'exemple ci-dessus, après avoir cliqué sur le bouton, le paragraphe n'apparaîtra qu'après avoir appuyé sur le bouton OK dans la boîte d'alerte. Vous pouvez l'essayer vous-même : -<pre class="brush: html hidden"><button>Cliquez sur moi</button></pre> +```html hidden +<button>Cliquez sur moi</button> +``` -<p>{{EmbedLiveSample('synchronous_javascript', '100%', '110px')}}</p> +{{EmbedLiveSample('synchronous_javascript', '100%', '110px')}} -<div class="note"> - <p><strong>Note :</strong> Il est important de se rappeler que <code><a href="/fr/docs/Web/API/Window/alert">alert()</a></code>, tout en étant très utile pour démontrer une opération de blocage synchrone, est horrible à utiliser dans des applications du monde réel.</p> -</div> +> **Note :** Il est important de se rappeler que [`alert()`](/fr/docs/Web/API/Window/alert), tout en étant très utile pour démontrer une opération de blocage synchrone, est horrible à utiliser dans des applications du monde réel. -<h2 id="asynchronous_javascript">JavaScript asynchrone</h2> +## JavaScript asynchrone -<p>Pour des raisons illustrées précédemment (par exemple, en rapport avec le blocage), de nombreuses fonctionnalités des API Web utilisent désormais du code asynchrone pour s'exécuter, en particulier celles qui accèdent à un type de ressource ou le récupèrent à partir d'un périphérique externe, par exemple en récupérant un fichier sur le réseau, en accédant à une base de données et en renvoyant des données, en accédant à un flux vidéo à partir d'une webcam ou en diffusant l'affichage vers un casque VR.</p> +Pour des raisons illustrées précédemment (par exemple, en rapport avec le blocage), de nombreuses fonctionnalités des API Web utilisent désormais du code asynchrone pour s'exécuter, en particulier celles qui accèdent à un type de ressource ou le récupèrent à partir d'un périphérique externe, par exemple en récupérant un fichier sur le réseau, en accédant à une base de données et en renvoyant des données, en accédant à un flux vidéo à partir d'une webcam ou en diffusant l'affichage vers un casque VR. -<p>Pourquoi est-il difficile de faire fonctionner un code synchrone ? Prenons un exemple rapide. Lorsque vous récupérez une image sur un serveur, vous ne pouvez pas renvoyer le résultat immédiatement. Cela signifie que l'exemple suivant (pseudocode) ne fonctionnerait pas :</p> +Pourquoi est-il difficile de faire fonctionner un code synchrone ? Prenons un exemple rapide. Lorsque vous récupérez une image sur un serveur, vous ne pouvez pas renvoyer le résultat immédiatement. Cela signifie que l'exemple suivant (pseudocode) ne fonctionnerait pas : -<pre class="brush: js">let response = fetch('myImage.png'); // la récupération est asynchrone +```js +let response = fetch('myImage.png'); // la récupération est asynchrone let blob = response.blob(); -// afficher votre blob d'image à l'écran d'une manière ou d'une autre</pre> +// afficher votre blob d'image à l'écran d'une manière ou d'une autre +``` -<p>C'est parce que vous ne savez pas combien de temps l'image prendra pour être téléchargée, donc lorsque vous viendrez à exécuter la deuxième ligne, elle lancera une erreur (éventuellement par intermittence, éventuellement à chaque fois) parce que la réponse <code>response</code> n'est pas encore disponible. Au lieu de cela, vous avez besoin que votre code attende que la réponse <code>response</code> soit retournée avant d'essayer de lui faire quoi que ce soit d'autre.</p> +C'est parce que vous ne savez pas combien de temps l'image prendra pour être téléchargée, donc lorsque vous viendrez à exécuter la deuxième ligne, elle lancera une erreur (éventuellement par intermittence, éventuellement à chaque fois) parce que la réponse `response` n'est pas encore disponible. Au lieu de cela, vous avez besoin que votre code attende que la réponse `response` soit retournée avant d'essayer de lui faire quoi que ce soit d'autre. -<p>Il existe deux principaux types de code asynchrone que vous rencontrerez dans le code JavaScript : les anciens rappels et le code plus récent de type promesse. Dans les sections suivantes, nous allons examiner chacun d'eux à tour de rôle.</p> +Il existe deux principaux types de code asynchrone que vous rencontrerez dans le code JavaScript : les anciens rappels et le code plus récent de type promesse. Dans les sections suivantes, nous allons examiner chacun d'eux à tour de rôle. -<h2 id="async_callbacks">Fonctions de rappel asynchrones</h2> +## Fonctions de rappel asynchrones -<p>Les <i>callbacks</i> asynchrones ou fonctions de rappels asynchrones sont des fonctions qui sont passées comme arguments lors de l'appel d'une fonction qui commencera à exécuter du code en arrière-plan. Lorsque le code d'arrière-plan a fini de s'exécuter, il appelle la fonction de rappel pour vous faire savoir que le travail est terminé, ou pour vous faire savoir que quelque chose d'intéressant s'est produit. L'utilisation des <i>callbacks</i> est un peu démodée aujourd'hui, mais vous les verrez encore dans un certain nombre d'API plus anciennes encore couramment utilisées.</p> +Les _callbacks_ asynchrones ou fonctions de rappels asynchrones sont des fonctions qui sont passées comme arguments lors de l'appel d'une fonction qui commencera à exécuter du code en arrière-plan. Lorsque le code d'arrière-plan a fini de s'exécuter, il appelle la fonction de rappel pour vous faire savoir que le travail est terminé, ou pour vous faire savoir que quelque chose d'intéressant s'est produit. L'utilisation des _callbacks_ est un peu démodée aujourd'hui, mais vous les verrez encore dans un certain nombre d'API plus anciennes encore couramment utilisées. -<p>Un exemple de rappel asynchrone est le deuxième paramètre de la méthode <a href="/fr/docs/Web/API/EventTarget/addEventListener"><code>addEventListener()</code></a> (comme nous pouvons le voir en action ci-dessous) :</p> +Un exemple de rappel asynchrone est le deuxième paramètre de la méthode [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener) (comme nous pouvons le voir en action ci-dessous) : -<pre class="brush: js">btn.addEventListener('click', () => { +```js +btn.addEventListener('click', () => { alert(`Vous avez cliqué sur moi !`); let pElem = document.createElement('p'); pElem.textContent = `Il s'agit d'un paragraphe nouvellement ajouté.`; document.body.appendChild(pElem); -});</pre> +}); +``` -<p>Le premier paramètre est le type d'événement à écouter, et le deuxième paramètre est une fonction de rappel qui est invoquée lorsque l'événement est déclenché.</p> +Le premier paramètre est le type d'événement à écouter, et le deuxième paramètre est une fonction de rappel qui est invoquée lorsque l'événement est déclenché. -<p>Lorsque nous passons une fonction de rappel comme argument à une autre fonction, nous ne passons que la référence de la fonction comme argument, c'est-à-dire que la fonction de rappel n'est <strong>pas</strong> exécutée immédiatement. Elle est « rappelée » (d'où son nom) de manière asynchrone quelque part dans le corps de la fonction contenante. La fonction contenante est responsable de l'exécution de la fonction de rappel le moment venu.</p> +Lorsque nous passons une fonction de rappel comme argument à une autre fonction, nous ne passons que la référence de la fonction comme argument, c'est-à-dire que la fonction de rappel n'est **pas** exécutée immédiatement. Elle est « rappelée » (d'où son nom) de manière asynchrone quelque part dans le corps de la fonction contenante. La fonction contenante est responsable de l'exécution de la fonction de rappel le moment venu. -<p>Vous pouvez écrire votre propre fonction contenant un <i>callback</i> assez facilement. Examinons un autre exemple qui charge une ressource via l'API <a href="/fr/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">exécutez-le code en direct</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">voir sa source</a>) :</p> +Vous pouvez écrire votre propre fonction contenant un _callback_ assez facilement. Examinons un autre exemple qui charge une ressource via l'API [`XMLHttpRequest`](/fr/docs/Web/API/XMLHttpRequest) ([exécutez-le code en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html), et [voir sa source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html)) : -<pre class="brush: js">function loadAsset(url, type, callback) { +```js +function loadAsset(url, type, callback) { let xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = type; @@ -130,157 +136,152 @@ function displayImage(blob) { document.body.appendChild(image); } -loadAsset('coffee.jpg', 'blob', displayImage);</pre> +loadAsset('coffee.jpg', 'blob', displayImage); +``` -<p>Ici, nous créons une fonction <code>displayImage()</code> qui représente un blob qui lui est passé sous forme d'URL d'objet, puis crée une image dans laquelle afficher l'URL, en l'annexant au <code><body></code> du document. Cependant, nous créons ensuite une fonction <code>loadAsset()</code> qui prend une fonction de rappel en paramètre, ainsi qu'une URL à récupérer et un type de contenu. Elle utilise <code>XMLHttpRequest</code> (souvent abrégé en "XHR") pour récupérer la ressource à l'URL donnée, puis passe la réponse à la fonction de rappel pour qu'elle fasse quelque chose avec. Dans ce cas, le callback attend que l'appel XHR termine le téléchargement de la ressource (en utilisant l'écouteur d'événement <code><a href="/fr/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) avant de la transmettre au <i>callback</i>.</p> +Ici, nous créons une fonction `displayImage()` qui représente un blob qui lui est passé sous forme d'URL d'objet, puis crée une image dans laquelle afficher l'URL, en l'annexant au `<body>` du document. Cependant, nous créons ensuite une fonction `loadAsset()` qui prend une fonction de rappel en paramètre, ainsi qu'une URL à récupérer et un type de contenu. Elle utilise `XMLHttpRequest` (souvent abrégé en "XHR") pour récupérer la ressource à l'URL donnée, puis passe la réponse à la fonction de rappel pour qu'elle fasse quelque chose avec. Dans ce cas, le callback attend que l'appel XHR termine le téléchargement de la ressource (en utilisant l'écouteur d'événement [`onload`](/fr/docs/Web/API/XMLHttpRequestEventTarget/onload)) avant de la transmettre au _callback_. -<p>Les fonctions de rappel sont polyvalentes - non seulement elles permettent de contrôler l'ordre dans lequel les fonctions sont exécutées et quelles données sont transmises entre elles, mais elles permettent également de transmettre des données à différentes fonctions en fonction des circonstances. Ainsi, vous pourriez avoir différentes actions à exécuter sur la réponse téléchargée, comme <code>processingJSON()</code>, <code>displayText()</code>, etc.</p> +Les fonctions de rappel sont polyvalentes - non seulement elles permettent de contrôler l'ordre dans lequel les fonctions sont exécutées et quelles données sont transmises entre elles, mais elles permettent également de transmettre des données à différentes fonctions en fonction des circonstances. Ainsi, vous pourriez avoir différentes actions à exécuter sur la réponse téléchargée, comme `processingJSON()`, `displayText()`, etc. -<p>Notez que tous les <i>callbacks</i> ne sont pas asynchrones - certains s'exécutent de manière synchrone. Par exemple, lorsque nous utilisons <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.prototype.forEach()</code></a> pour parcourir en boucle les éléments d'un tableau (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html">voir en direct</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html">la source</a>) :</p> +Notez que tous les _callbacks_ ne sont pas asynchrones - certains s'exécutent de manière synchrone. Par exemple, lorsque nous utilisons [`Array.prototype.forEach()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) pour parcourir en boucle les éléments d'un tableau ([voir en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html), et [la source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html)) : -<pre class="brush: js">const gods = ['Apollon', 'Artémis', 'Arès', 'Zeus']; +```js +const gods = ['Apollon', 'Artémis', 'Arès', 'Zeus']; gods.forEach(function (eachName, index){ console.log(`${index}. ${eachName}`); -});</pre> +}); +``` -<p>Dans cet exemple, nous parcourons en boucle un tableau de dieux grecs et nous imprimons les numéros d'index et les valeurs sur la console. Le paramètre attendu de <code>forEach()</code> est une fonction de rappel, qui prend elle-même deux paramètres, une référence au nom du tableau et aux valeurs d'index. Cependant, elle n'attend rien - elle s'exécute immédiatement.</p> +Dans cet exemple, nous parcourons en boucle un tableau de dieux grecs et nous imprimons les numéros d'index et les valeurs sur la console. Le paramètre attendu de `forEach()` est une fonction de rappel, qui prend elle-même deux paramètres, une référence au nom du tableau et aux valeurs d'index. Cependant, elle n'attend rien - elle s'exécute immédiatement. -<h2 id="promises">Promesses</h2> +## Promesses -<p>Les promesses sont le nouveau style de code asynchrone que vous verrez utilisé dans les API Web modernes. Un bon exemple est l'API <code><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code>, qui est en fait comme une version moderne et plus efficace de <a href="/fr/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a>. Voyons un exemple rapide, tiré de notre article <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Fetching data from the server</a> :</p> +Les promesses sont le nouveau style de code asynchrone que vous verrez utilisé dans les API Web modernes. Un bon exemple est l'API [`fetch()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch), qui est en fait comme une version moderne et plus efficace de [`XMLHttpRequest`](/fr/docs/Web/API/XMLHttpRequest). Voyons un exemple rapide, tiré de notre article [Fetching data from the server](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data) : -<pre class="brush: js">fetch('products.json').then(function(response) { +```js +fetch('products.json').then(function(response) { return response.json(); }).then(function(json) { let products = json; initialize(products); }).catch(function(err) { console.log('Problème de récupération : ' + err.message); -});</pre> +}); +``` -<div class="note"> - <p><strong>Note :</strong> Vous pouvez trouver la version finale sur GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js">voir la source ici</a>, et aussi <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/">voir le fonctionnement en direct</a>).</p> -</div> +> **Note :** Vous pouvez trouver la version finale sur GitHub ([voir la source ici](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js), et aussi [voir le fonctionnement en direct](https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/)). -<p>Nous voyons ici <code>fetch()</code> prendre un seul paramètre - l'URL d'une ressource que vous souhaitez récupérer sur le réseau - et renvoyer une <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise">promesse</a>. La promesse est un objet représentant l'achèvement ou l'échec de l'opération asynchrone. Elle représente un état intermédiaire, en quelque sorte. En substance, c'est la façon dont le navigateur dit « Je promets de vous donner la réponse dès que possible », d'où le nom de « promesse ».</p> +Nous voyons ici `fetch()` prendre un seul paramètre - l'URL d'une ressource que vous souhaitez récupérer sur le réseau - et renvoyer une [promesse](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise). La promesse est un objet représentant l'achèvement ou l'échec de l'opération asynchrone. Elle représente un état intermédiaire, en quelque sorte. En substance, c'est la façon dont le navigateur dit « Je promets de vous donner la réponse dès que possible », d'où le nom de « promesse ». -<p>Il faut parfois s'habituer à ce concept, qui ressemble un peu au <a href="https://fr.wikipedia.org/wiki/Chat_de_Schrödinger">Chat de Schrödinger</a> en action. Aucun des résultats possibles ne s'est encore produit, donc l'opération de récupération est actuellement en attente du résultat du navigateur qui tente de terminer l'opération à un moment donné dans le futur. Nous avons ensuite trois autres blocs de code enchaînés à la fin de <code>fetch()</code> :</p> +Il faut parfois s'habituer à ce concept, qui ressemble un peu au [Chat de Schrödinger](https://fr.wikipedia.org/wiki/Chat_de_Schrödinger) en action. Aucun des résultats possibles ne s'est encore produit, donc l'opération de récupération est actuellement en attente du résultat du navigateur qui tente de terminer l'opération à un moment donné dans le futur. Nous avons ensuite trois autres blocs de code enchaînés à la fin de `fetch()` : -<ul> - <li>Deux blocs <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code>. Ils contiennent tous deux une fonction de rappel qui s'exécutera si l'opération précédente est réussie, et chaque fonction de rappel reçoit en entrée le résultat de l'opération précédente réussie, afin que vous puissiez poursuivre et y faire autre chose. Chaque bloc <code>.then()</code> renvoie une autre promesse, ce qui signifie que vous pouvez enchaîner plusieurs blocs <code>.then()</code> les uns sur les autres, de sorte que plusieurs opérations asynchrones peuvent être exécutées dans l'ordre, les unes après les autres.</li> - <li>Le bloc <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">catch()</a></code> à la fin s'exécute si l'un des blocs <code>.then()</code> échoue - de manière similaire aux blocs synchrones <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/try...catch" >try...catch</a></code>, un objet d'erreur est mis à disposition à l'intérieur du <code>catch()</code>, qui peut être utilisé pour signaler le type d'erreur qui s'est produit. Notez cependant que le <code>try...catch</code> synchrone ne fonctionnera pas avec les promesses, bien qu'il fonctionne avec <a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">async/await</a>, comme vous l'apprendrez plus tard.</li> -</ul> +- Deux blocs [`then()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/then). Ils contiennent tous deux une fonction de rappel qui s'exécutera si l'opération précédente est réussie, et chaque fonction de rappel reçoit en entrée le résultat de l'opération précédente réussie, afin que vous puissiez poursuivre et y faire autre chose. Chaque bloc `.then()` renvoie une autre promesse, ce qui signifie que vous pouvez enchaîner plusieurs blocs `.then()` les uns sur les autres, de sorte que plusieurs opérations asynchrones peuvent être exécutées dans l'ordre, les unes après les autres. +- Le bloc [`catch()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) à la fin s'exécute si l'un des blocs `.then()` échoue - de manière similaire aux blocs synchrones [`try...catch`](/fr/docs/Web/JavaScript/Reference/Statements/try...catch), un objet d'erreur est mis à disposition à l'intérieur du `catch()`, qui peut être utilisé pour signaler le type d'erreur qui s'est produit. Notez cependant que le `try...catch` synchrone ne fonctionnera pas avec les promesses, bien qu'il fonctionne avec [async/await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await), comme vous l'apprendrez plus tard. -<div class="note"> - <p><strong>Note :</strong> Vous en apprendrez beaucoup plus sur les promesses plus tard dans le module, alors ne vous inquiétez pas si vous ne les comprenez pas encore complètement.</p> -</div> +> **Note :** Vous en apprendrez beaucoup plus sur les promesses plus tard dans le module, alors ne vous inquiétez pas si vous ne les comprenez pas encore complètement. -<h3 id="the_event_queue">La file d'attente des événements</h3> +### La file d'attente des événements -<p>Les opérations asynchrones comme les promesses sont placées dans une <strong>file d'attente d'événements</strong>, qui s'exécute après que le processus principal a terminé son traitement afin qu'elles <em>ne bloquent pas</em> l'exécution du code JavaScript suivant. Les opérations mises en file d'attente se terminent dès que possible puis renvoient leurs résultats à l'environnement JavaScript.</p> +Les opérations asynchrones comme les promesses sont placées dans une **file d'attente d'événements**, qui s'exécute après que le processus principal a terminé son traitement afin qu'elles _ne bloquent pas_ l'exécution du code JavaScript suivant. Les opérations mises en file d'attente se terminent dès que possible puis renvoient leurs résultats à l'environnement JavaScript. -<h3 id="promises_versus_callbacks">Promesses contre callbacks</h3> +### Promesses contre callbacks -<p>Les promesses présentent certaines similitudes avec les anciennes fonctions de rappel. Il s'agit essentiellement d'un objet retourné auquel vous attachez des fonctions de rappel, plutôt que de devoir passer des <i>callbacks</i> dans une fonction.</p> +Les promesses présentent certaines similitudes avec les anciennes fonctions de rappel. Il s'agit essentiellement d'un objet retourné auquel vous attachez des fonctions de rappel, plutôt que de devoir passer des _callbacks_ dans une fonction. -<p>Cependant, les promesses sont spécifiquement conçues pour gérer les opérations asynchrones et présentent de nombreux avantages par rapport aux fonctions de rappel classiques :</p> +Cependant, les promesses sont spécifiquement conçues pour gérer les opérations asynchrones et présentent de nombreux avantages par rapport aux fonctions de rappel classiques : -<ul> - <li>Vous pouvez enchaîner plusieurs opérations asynchrones en utilisant plusieurs opérations <code>.then()</code>, en passant le résultat de l'une dans la suivante comme entrée. Ceci est beaucoup plus difficile à faire avec les fonctions de rappel, ce qui aboutit souvent à une « pyramide de malheur » désordonnée (également connue sous le nom de <a href="http://callbackhell.com/">callback hell</a>).</li> - <li>Les fonctions de rappel passées aux promesses sont toujours appelées dans l'ordre strict où ils sont placés dans la file d'attente des événements.</li> - <li>La gestion des erreurs est bien meilleure - toutes les erreurs sont traitées par un seul bloc <code>.catch()</code> à la fin du bloc, plutôt que d'être traitées individuellement à chaque niveau de la « pyramide ».</li> - <li>Les promesses évitent l'inversion de contrôle, contrairement aux callbacks à l'ancienne, qui perdent le contrôle total de la façon dont la fonction sera exécutée lorsqu'ils sont transmis à une bibliothèque tierce.</li> -</ul> +- Vous pouvez enchaîner plusieurs opérations asynchrones en utilisant plusieurs opérations `.then()`, en passant le résultat de l'une dans la suivante comme entrée. Ceci est beaucoup plus difficile à faire avec les fonctions de rappel, ce qui aboutit souvent à une « pyramide de malheur » désordonnée (également connue sous le nom de [callback hell](http://callbackhell.com/)). +- Les fonctions de rappel passées aux promesses sont toujours appelées dans l'ordre strict où ils sont placés dans la file d'attente des événements. +- La gestion des erreurs est bien meilleure - toutes les erreurs sont traitées par un seul bloc `.catch()` à la fin du bloc, plutôt que d'être traitées individuellement à chaque niveau de la « pyramide ». +- Les promesses évitent l'inversion de contrôle, contrairement aux callbacks à l'ancienne, qui perdent le contrôle total de la façon dont la fonction sera exécutée lorsqu'ils sont transmis à une bibliothèque tierce. -<h2 id="the_nature_of_asynchronous_code">La nature du code asynchrone</h2> +## La nature du code asynchrone -<p>Explorons un exemple qui illustre davantage la nature du code asynchrone, en montrant ce qui peut se produire lorsque nous ne sommes pas pleinement conscients de l'ordre d'exécution du code et les problèmes liés à la tentative de traiter le code asynchrone comme du code synchrone. L'exemple suivant est assez similaire à ce que nous avons vu auparavant (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html">voir en direct</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">la source</a>). Une différence est que nous avons inclus un certain nombre d'instructions <a href="/fr/docs/Web/API/Console/log"><code>console.log()</code></a> pour illustrer un ordre dans lequel on pourrait penser que le code s'exécute.</p> +Explorons un exemple qui illustre davantage la nature du code asynchrone, en montrant ce qui peut se produire lorsque nous ne sommes pas pleinement conscients de l'ordre d'exécution du code et les problèmes liés à la tentative de traiter le code asynchrone comme du code synchrone. L'exemple suivant est assez similaire à ce que nous avons vu auparavant ([voir en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html), et [la source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html)). Une différence est que nous avons inclus un certain nombre d'instructions [`console.log()`](/fr/docs/Web/API/Console/log) pour illustrer un ordre dans lequel on pourrait penser que le code s'exécute. -<pre class="brush: js">console.log(`Démarrage`); +```js +console.log(`Démarrage`); let image; -fetch('coffee.jpg').then((response) => { +fetch('coffee.jpg').then((response) => { console.log(`Ça a fonctionné :)`) return response.blob(); -}).then((myBlob) => { +}).then((myBlob) => { let objectURL = URL.createObjectURL(myBlob); image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); -}).catch((error) => { +}).catch((error) => { console.log(`Il y a eu un problème avec votre opération de récupération : ${error.message}`); }); -console.log(`C'est fait !`);</pre> +console.log(`C'est fait !`); +``` -<p>Le navigateur va commencer à exécuter le code, voir la première instruction <code>console.log()</code> (<code>Démarrage</code>) et l'exécuter, puis créer la variable <code>image</code>.</p> +Le navigateur va commencer à exécuter le code, voir la première instruction `console.log()` (`Démarrage`) et l'exécuter, puis créer la variable `image`. -<p>Il passera ensuite à la ligne suivante et commencera à exécuter le bloc <code>fetch()</code> mais, comme <code>fetch()</code> s'exécute de manière asynchrone sans blocage, l'exécution du code se poursuit après le code lié à la promesse, atteignant ainsi l'instruction finale <code>console.log()</code> (<code>C'est fait !</code>) et la sortant sur la console.</p> +Il passera ensuite à la ligne suivante et commencera à exécuter le bloc `fetch()` mais, comme `fetch()` s'exécute de manière asynchrone sans blocage, l'exécution du code se poursuit après le code lié à la promesse, atteignant ainsi l'instruction finale `console.log()` (`C'est fait !`) et la sortant sur la console. -<p>Ce n'est qu'une fois que le bloc <code>fetch()</code> a complètement fini de s'exécuter et de délivrer son résultat à travers les blocs <code>.then()</code> que nous verrons enfin apparaître le deuxième message <code>console.log()</code> (<code>Ça a fonctionné :)</code>). Les messages sont donc apparus dans un ordre différent de celui auquel on pourrait s'attendre :</p> +Ce n'est qu'une fois que le bloc `fetch()` a complètement fini de s'exécuter et de délivrer son résultat à travers les blocs `.then()` que nous verrons enfin apparaître le deuxième message `console.log()` (`Ça a fonctionné :)`). Les messages sont donc apparus dans un ordre différent de celui auquel on pourrait s'attendre : -<ul> - <li>Démarrage</li> - <li>C'est fait !</li> - <li>Ça a fonctionné :)</li> -</ul> +- Démarrage +- C'est fait ! +- Ça a fonctionné :) -<p>Si cela vous déconcerte, considérez le petit exemple suivant :</p> +Si cela vous déconcerte, considérez le petit exemple suivant : -<pre class="brush: js">console.log(`Enregistrement de l'événement de clics`); +```js +console.log(`Enregistrement de l'événement de clics`); -button.addEventListener('click', () => { +button.addEventListener('click', () => { console.log(`Obtenir un clic`); }); -console.log(`Tout est bon !`);</pre> +console.log(`Tout est bon !`); +``` -<p>Le comportement est très similaire - les premier et troisième messages <code>console.log()</code> s'affichent immédiatement, mais le deuxième est bloqué jusqu'à ce que quelqu'un clique sur le bouton de la souris. L'exemple précédent fonctionne de la même manière, sauf que dans ce cas, le deuxième message est bloqué sur la chaîne de promesses allant chercher une ressource puis l'affichant à l'écran, plutôt que sur un clic.</p> +Le comportement est très similaire - les premier et troisième messages `console.log()` s'affichent immédiatement, mais le deuxième est bloqué jusqu'à ce que quelqu'un clique sur le bouton de la souris. L'exemple précédent fonctionne de la même manière, sauf que dans ce cas, le deuxième message est bloqué sur la chaîne de promesses allant chercher une ressource puis l'affichant à l'écran, plutôt que sur un clic. -<p>Dans un exemple de code moins trivial, ce type de configuration pourrait poser un problème - vous ne pouvez pas inclure un bloc de code asynchrone qui renvoie un résultat, sur lequel vous vous appuyez ensuite dans un bloc de code synchrone. Vous ne pouvez tout simplement pas garantir que la fonction asynchrone retournera avant que le navigateur ait traité le bloc de synchronisation.</p> +Dans un exemple de code moins trivial, ce type de configuration pourrait poser un problème - vous ne pouvez pas inclure un bloc de code asynchrone qui renvoie un résultat, sur lequel vous vous appuyez ensuite dans un bloc de code synchrone. Vous ne pouvez tout simplement pas garantir que la fonction asynchrone retournera avant que le navigateur ait traité le bloc de synchronisation. -<p>Pour voir cela en action, essayez de prendre une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">notre exemple</a>, et changez le quatrième appel <code>console.log()</code> par le suivant :</p> +Pour voir cela en action, essayez de prendre une copie locale de [notre exemple](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html), et changez le quatrième appel `console.log()` par le suivant : -<pre class="brush: js">console.log (`Tout est bon ! ${image.src} est affiché.`);</pre> +```js +console.log (`Tout est bon ! ${image.src} est affiché.`); +``` -<p>Vous devriez maintenant obtenir une erreur dans votre console au lieu du troisième message :</p> +Vous devriez maintenant obtenir une erreur dans votre console au lieu du troisième message : -<pre>TypeError: image is undefined; can't access its "src" property</pre> + TypeError: image is undefined; can't access its "src" property -<p>Cela est dû au fait qu'au moment où le navigateur tente d'exécuter la troisième instruction <code>console.log()</code>, le bloc <code>fetch()</code> n'a pas fini de s'exécuter, de sorte que la variable <code>image</code> n'a pas reçu de valeur.</p> +Cela est dû au fait qu'au moment où le navigateur tente d'exécuter la troisième instruction `console.log()`, le bloc `fetch()` n'a pas fini de s'exécuter, de sorte que la variable `image` n'a pas reçu de valeur. -<div class="note"> - <p><strong>Note :</strong> Pour des raisons de sécurité, vous ne pouvez pas <code>fetch()</code> les fichiers de votre système de fichiers local (ou exécuter d'autres opérations de ce type localement) ; pour exécuter l'exemple ci-dessus localement, vous devrez le faire passer par un <a href="/fr/docs/Learn/Common_questions/set_up_a_local_testing_server">serveur web local</a>.</p> -</div> +> **Note :** Pour des raisons de sécurité, vous ne pouvez pas `fetch()` les fichiers de votre système de fichiers local (ou exécuter d'autres opérations de ce type localement) ; pour exécuter l'exemple ci-dessus localement, vous devrez le faire passer par un [serveur web local](/fr/docs/Learn/Common_questions/set_up_a_local_testing_server). -<h2 id="active_learning_make_it_all_async!">Apprentissage actif : rendez tout asynchrone !</h2> +## Apprentissage actif : rendez tout asynchrone ! -<p>Pour corriger l'exemple problématique de <code>fetch()</code> et faire en sorte que les trois déclarations <code>console.log()</code> apparaissent dans l'ordre souhaité, vous pourriez faire en sorte que la troisième déclaration <code>console.log()</code> s'exécute également de manière asynchrone. Cela peut être fait en la déplaçant à l'intérieur d'un autre bloc <code>.then()</code> enchaîné à la fin du deuxième, ou en la déplaçant à l'intérieur du deuxième bloc <code>then()</code>. Essayez de corriger cela maintenant.</p> +Pour corriger l'exemple problématique de `fetch()` et faire en sorte que les trois déclarations `console.log()` apparaissent dans l'ordre souhaité, vous pourriez faire en sorte que la troisième déclaration `console.log()` s'exécute également de manière asynchrone. Cela peut être fait en la déplaçant à l'intérieur d'un autre bloc `.then()` enchaîné à la fin du deuxième, ou en la déplaçant à l'intérieur du deuxième bloc `then()`. Essayez de corriger cela maintenant. -<div class="note"> - <p><strong>Note :</strong> Si vous êtes bloqué, vous pouvez <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html">trouver une réponse ici</a> (voyez-la fonctionner <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html">en direct</a>). Vous pouvez également trouver beaucoup plus d'informations sur les promesses dans notre guide <a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a>, plus loin dans ce module.</p> -</div> +> **Note :** Si vous êtes bloqué, vous pouvez [trouver une réponse ici](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html) (voyez-la fonctionner [en direct](https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html)). Vous pouvez également trouver beaucoup plus d'informations sur les promesses dans notre guide [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises), plus loin dans ce module. -<h2 id="conclusion">Conclusion</h2> +## Conclusion -<p>Dans sa forme la plus élémentaire, JavaScript est un langage synchrone, bloquant et à un seul processus, dans lequel une seule opération peut être en cours à la fois. Mais les navigateurs web définissent des fonctions et des API qui nous permettent d'enregistrer des fonctions qui ne doivent pas être exécutées de manière synchrone, mais qui doivent être invoquées de manière asynchrone lorsqu'un événement quelconque se produit (le passage du temps, l'interaction de l'utilisateur avec la souris ou l'arrivée de données sur le réseau, par exemple). Cela signifie que vous pouvez laisser votre code faire plusieurs choses en même temps sans arrêter ou bloquer votre processus principal.</p> +Dans sa forme la plus élémentaire, JavaScript est un langage synchrone, bloquant et à un seul processus, dans lequel une seule opération peut être en cours à la fois. Mais les navigateurs web définissent des fonctions et des API qui nous permettent d'enregistrer des fonctions qui ne doivent pas être exécutées de manière synchrone, mais qui doivent être invoquées de manière asynchrone lorsqu'un événement quelconque se produit (le passage du temps, l'interaction de l'utilisateur avec la souris ou l'arrivée de données sur le réseau, par exemple). Cela signifie que vous pouvez laisser votre code faire plusieurs choses en même temps sans arrêter ou bloquer votre processus principal. -<p>Le fait de vouloir exécuter du code de manière synchrone ou asynchrone dépend de ce que l'on essaie de faire.</p> +Le fait de vouloir exécuter du code de manière synchrone ou asynchrone dépend de ce que l'on essaie de faire. -<p>Il y a des moments où nous voulons que les choses se chargent et se produisent immédiatement. Par exemple, lorsque vous appliquez des styles définis par l'utilisateur à une page web, vous voulez que les styles soient appliqués dès que possible.</p> +Il y a des moments où nous voulons que les choses se chargent et se produisent immédiatement. Par exemple, lorsque vous appliquez des styles définis par l'utilisateur à une page web, vous voulez que les styles soient appliqués dès que possible. -<p>Cependant, si nous exécutons une opération qui prend du temps, comme l'interrogation d'une base de données et l'utilisation des résultats pour remplir des modèles, il est préférable d'écarter cette opération du thread principal et de réaliser la tâche de manière asynchrone. Avec le temps, vous apprendrez quand il est plus judicieux de choisir une technique asynchrone plutôt qu'une technique synchrone.</p> +Cependant, si nous exécutons une opération qui prend du temps, comme l'interrogation d'une base de données et l'utilisation des résultats pour remplir des modèles, il est préférable d'écarter cette opération du thread principal et de réaliser la tâche de manière asynchrone. Avec le temps, vous apprendrez quand il est plus judicieux de choisir une technique asynchrone plutôt qu'une technique synchrone. -<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}} -<h2 id="in_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li> -</ul> +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Faciliter la programmation asynchrone avec async et await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) diff --git a/files/fr/learn/javascript/asynchronous/promises/index.md b/files/fr/learn/javascript/asynchronous/promises/index.md index 69f6de6a21..0c3b506ed7 100644 --- a/files/fr/learn/javascript/asynchronous/promises/index.md +++ b/files/fr/learn/javascript/asynchronous/promises/index.md @@ -15,93 +15,94 @@ tags: - then translation_of: Learn/JavaScript/Asynchronous/Promises --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</div> - -<p><strong>Les promesses</strong> sont une fonctionnalité relativement nouvelle du langage JavaScript qui vous permet de reporter d'autres actions jusqu'à ce qu'une action précédente soit terminée, ou de répondre à son échec. Ceci est utile pour mettre en place une séquence d'opérations asynchrones afin qu'elles fonctionnent correctement. Cet article vous montre comment les promesses fonctionnent, comment vous les verrez utilisées avec les API Web, et comment écrire les vôtres.</p> +**Les promesses** sont une fonctionnalité relativement nouvelle du langage JavaScript qui vous permet de reporter d'autres actions jusqu'à ce qu'une action précédente soit terminée, ou de répondre à son échec. Ceci est utile pour mettre en place une séquence d'opérations asynchrones afin qu'elles fonctionnent correctement. Cet article vous montre comment les promesses fonctionnent, comment vous les verrez utilisées avec les API Web, et comment écrire les vôtres. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript.</td> - </tr> + <td> + Connaissances informatiques de base, compréhension raisonnable des + principes fondamentaux de JavaScript. + </td> + </tr> <tr> <th scope="row">Objectif :</th> <td>Comprendre les promesses et savoir comment les utiliser.</td> - </tr> + </tr> </tbody> </table> -<h2 id="what_are_promises">Que sont les promesses ?</h2> +## Que sont les promesses ? -<p>Nous avons examiné les <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise">promesses (<code>Promise</code>)</a> brièvement dans le premier article du cours, mais ici nous allons les examiner de manière beaucoup plus approfondie.</p> +Nous avons examiné les [promesses (`Promise`)](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) brièvement dans le premier article du cours, mais ici nous allons les examiner de manière beaucoup plus approfondie. -<p>Essentiellement, une promesse est un objet qui représente un état intermédiaire d'une opération - en fait, c'est une <em>promesse</em> qu'un résultat d'une certaine nature sera retourné à un moment donné dans le futur. Il n'y a aucune garantie du moment exact où l'opération se terminera et où le résultat sera renvoyé, mais il <em>est</em> une garantie que lorsque le résultat est disponible, ou que la promesse échoue, le code que vous fournissez sera exécuté afin de faire autre chose avec un résultat réussi, ou de gérer gracieusement un cas d'échec.</p> +Essentiellement, une promesse est un objet qui représente un état intermédiaire d'une opération - en fait, c'est une _promesse_ qu'un résultat d'une certaine nature sera retourné à un moment donné dans le futur. Il n'y a aucune garantie du moment exact où l'opération se terminera et où le résultat sera renvoyé, mais il _est_ une garantie que lorsque le résultat est disponible, ou que la promesse échoue, le code que vous fournissez sera exécuté afin de faire autre chose avec un résultat réussi, ou de gérer gracieusement un cas d'échec. -<p>En général, vous êtes moins intéressé par le temps qu'une opération asynchrone prendra pour renvoyer son résultat (à moins bien sûr qu'elle ne prenne <em>beaucoup</em> trop de temps !), et plus intéressé par le fait de pouvoir répondre à son retour, quel que soit le moment. Et bien sûr, il est agréable que cela ne bloque pas le reste de l'exécution du code.</p> +En général, vous êtes moins intéressé par le temps qu'une opération asynchrone prendra pour renvoyer son résultat (à moins bien sûr qu'elle ne prenne _beaucoup_ trop de temps !), et plus intéressé par le fait de pouvoir répondre à son retour, quel que soit le moment. Et bien sûr, il est agréable que cela ne bloque pas le reste de l'exécution du code. -<p>L'une des utilisations les plus courantes des promesses concerne les API web qui renvoient une promesse. Considérons une hypothétique application de chat vidéo. L'application dispose d'une fenêtre contenant une liste des amis de l'utilisateur, et un clic sur un bouton à côté d'un utilisateur lance un appel vidéo vers cet utilisateur.</p> +L'une des utilisations les plus courantes des promesses concerne les API web qui renvoient une promesse. Considérons une hypothétique application de chat vidéo. L'application dispose d'une fenêtre contenant une liste des amis de l'utilisateur, et un clic sur un bouton à côté d'un utilisateur lance un appel vidéo vers cet utilisateur. -<p>Le gestionnaire de ce bouton appelle <a href="/fr/docs/Web/API/MediaDevices/getUserMedia"><code>getUserMedia()</code></a> afin d'avoir accès à la caméra et au microphone de l'utilisateur. Puisque <code>getUserMedia()</code> doit s'assurer que l'utilisateur a la permission d'utiliser ces dispositifs <em>et</em> lui demander quel microphone utiliser et quelle caméra utiliser (ou s'il s'agit d'un appel vocal uniquement, parmi d'autres options possibles), il peut bloquer jusqu'à ce que non seulement toutes ces décisions soient prises, mais aussi que la caméra et le microphone soient activés. En outre, l'utilisateur peut ne pas répondre immédiatement à ces demandes d'autorisation. Cela peut potentiellement prendre beaucoup de temps.</p> +Le gestionnaire de ce bouton appelle [`getUserMedia()`](/fr/docs/Web/API/MediaDevices/getUserMedia) afin d'avoir accès à la caméra et au microphone de l'utilisateur. Puisque `getUserMedia()` doit s'assurer que l'utilisateur a la permission d'utiliser ces dispositifs _et_ lui demander quel microphone utiliser et quelle caméra utiliser (ou s'il s'agit d'un appel vocal uniquement, parmi d'autres options possibles), il peut bloquer jusqu'à ce que non seulement toutes ces décisions soient prises, mais aussi que la caméra et le microphone soient activés. En outre, l'utilisateur peut ne pas répondre immédiatement à ces demandes d'autorisation. Cela peut potentiellement prendre beaucoup de temps. -<p>Puisque l'appel à <code>getUserMedia()</code> est effectué depuis le processus principal du navigateur, l'ensemble du navigateur est bloqué jusqu'à ce que <code>getUserMedia()</code> retourne une réponse ! Évidemment, ce n'est pas une option viable ; sans les promesses, tout dans le navigateur devient inutilisable jusqu'à ce que l'utilisateur décide ce qu'il faut faire de la caméra et du microphone. Ainsi, au lieu d'attendre l'utilisateur, d'obtenir l'activation des périphériques choisis et de retourner directement le <a href="/fr/docs/Web/API/MediaStream"><code>MediaStream</code></a> pour le flux créé à partir des sources sélectionnées, <code>getUserMedia()</code> retourne une <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>promesse</code></a> qui est résolue avec le <a href="/fr/docs/Web/API/MediaStream"><code>MediaStream</code></a> une fois qu'il est disponible.</p> +Puisque l'appel à `getUserMedia()` est effectué depuis le processus principal du navigateur, l'ensemble du navigateur est bloqué jusqu'à ce que `getUserMedia()` retourne une réponse ! Évidemment, ce n'est pas une option viable ; sans les promesses, tout dans le navigateur devient inutilisable jusqu'à ce que l'utilisateur décide ce qu'il faut faire de la caméra et du microphone. Ainsi, au lieu d'attendre l'utilisateur, d'obtenir l'activation des périphériques choisis et de retourner directement le [`MediaStream`](/fr/docs/Web/API/MediaStream) pour le flux créé à partir des sources sélectionnées, `getUserMedia()` retourne une [`promesse`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) qui est résolue avec le [`MediaStream`](/fr/docs/Web/API/MediaStream) une fois qu'il est disponible. -<p>Le code qu'utiliserait l'application de chat vidéo pourrait ressembler à ceci :</p> +Le code qu'utiliserait l'application de chat vidéo pourrait ressembler à ceci : -<pre class="brush: js">function handleCallButton(evt) { +```js +function handleCallButton(evt) { setStatusMessage("Appel..."); navigator.mediaDevices.getUserMedia({video: true, audio: true}) - .then(chatStream => { + .then(chatStream => { selfViewElem.srcObject = chatStream; - chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream)); + chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream)); setStatusMessage("Connecté"); - }).catch(err => { + }).catch(err => { setStatusMessage("Échec de la connexion"); }); } -</pre> +``` -<p>Cette fonction commence par utiliser une fonction appelée <code>setStatusMessage()</code> pour mettre à jour un affichage d'état avec le message "Appel...", indiquant qu'un appel est tenté.Il appelle ensuite <code>getUserMedia()</code>, demandant un flux qui a à la fois des pistes vidéo et audio, puis une fois que cela a été obtenu, configure un élément vidéo pour montrer le flux provenant de la caméra comme une "vue de soi", puis prend chacune des pistes du flux et les ajoute à la <a href="/fr/docs/Web/API/RTCPeerConnection"><code>RTCPeerConnection</code></a> <a href="/fr/docs/Web/API/WebRTC_API">WebRTC</a> représentant une connexion à un autre utilisateur. Après cela, l'affichage de l'état est mis à jour pour indiquer "Connecté".</p> +Cette fonction commence par utiliser une fonction appelée `setStatusMessage()` pour mettre à jour un affichage d'état avec le message "Appel...", indiquant qu'un appel est tenté.Il appelle ensuite `getUserMedia()`, demandant un flux qui a à la fois des pistes vidéo et audio, puis une fois que cela a été obtenu, configure un élément vidéo pour montrer le flux provenant de la caméra comme une "vue de soi", puis prend chacune des pistes du flux et les ajoute à la [`RTCPeerConnection`](/fr/docs/Web/API/RTCPeerConnection) [WebRTC](/fr/docs/Web/API/WebRTC_API) représentant une connexion à un autre utilisateur. Après cela, l'affichage de l'état est mis à jour pour indiquer "Connecté". -<p>Si <code>getUserMedia()</code> échoue, le bloc <code>catch</code> s'exécute. Celui-ci utilise <code>setStatusMessage()</code> pour mettre à jour la case d'état afin d'indiquer qu'une erreur s'est produite.</p> +Si `getUserMedia()` échoue, le bloc `catch` s'exécute. Celui-ci utilise `setStatusMessage()` pour mettre à jour la case d'état afin d'indiquer qu'une erreur s'est produite. -<p>La chose importante ici est que l'appel <code>getUserMedia()</code> revient presque immédiatement, même si le flux de la caméra n'a pas encore été obtenu. Même si la fonction <code>handleCallButton()</code> est déjà retournée au code qui l'a appelée, lorsque <code>getUserMedia()</code> a fini de travailler, elle appelle le gestionnaire que vous fournissez. Tant que l'application ne suppose pas que le flux a commencé, elle peut continuer à fonctionner.</p> +La chose importante ici est que l'appel `getUserMedia()` revient presque immédiatement, même si le flux de la caméra n'a pas encore été obtenu. Même si la fonction `handleCallButton()` est déjà retournée au code qui l'a appelée, lorsque `getUserMedia()` a fini de travailler, elle appelle le gestionnaire que vous fournissez. Tant que l'application ne suppose pas que le flux a commencé, elle peut continuer à fonctionner. -<div class="note"> - <p><strong>Note :</strong> Vous pouvez en apprendre davantage sur ce sujet quelque peu avancé, si cela vous intéresse, dans l'article <a href="/fr/docs/Web/API/WebRTC_API/Signaling_and_video_calling">L'essentiel du WebRTC</a>. Un code similaire à celui-ci, mais beaucoup plus complet, est utilisé dans cet exemple.</p> -</div> +> **Note :** Vous pouvez en apprendre davantage sur ce sujet quelque peu avancé, si cela vous intéresse, dans l'article [L'essentiel du WebRTC](/fr/docs/Web/API/WebRTC_API/Signaling_and_video_calling). Un code similaire à celui-ci, mais beaucoup plus complet, est utilisé dans cet exemple. -<h2 id="the_trouble_with_callbacks">Le problème des fonctions de rappel</h2> +## Le problème des fonctions de rappel -<p>Pour bien comprendre pourquoi les promesses sont une bonne chose, il est utile de repenser aux anciennes fonctions de rappel (<i>callback</i>) et de comprendre pourquoi elles sont problématiques.</p> +Pour bien comprendre pourquoi les promesses sont une bonne chose, il est utile de repenser aux anciennes fonctions de rappel (_callback_) et de comprendre pourquoi elles sont problématiques. -<p>Prenons l'exemple de la commande d'une pizza. Il y a certaines étapes que vous devez franchir pour que votre commande soit réussie, et cela n'a pas vraiment de sens d'essayer de les exécuter dans le désordre, ou dans l'ordre mais avant que chaque étape précédente ne soit tout à fait terminée :</p> +Prenons l'exemple de la commande d'une pizza. Il y a certaines étapes que vous devez franchir pour que votre commande soit réussie, et cela n'a pas vraiment de sens d'essayer de les exécuter dans le désordre, ou dans l'ordre mais avant que chaque étape précédente ne soit tout à fait terminée : -<ol> - <li>Vous choisissez les garnitures que vous voulez. Cela peut prendre un certain temps si vous êtes indécis, et peut échouer si vous n'arrivez pas à vous décider, ou si vous décidez de prendre un curry à la place.</li> - <li>Vous passez ensuite votre commande. Le retour d'une pizza peut prendre un certain temps et peut échouer si le restaurant ne dispose pas des ingrédients nécessaires à sa cuisson.</li> - <li>Vous récupérez ensuite votre pizza et la mangez. Cela peut échouer si, par exemple, vous avez oublié votre portefeuille et ne pouvez pas payer la pizza !</li> -</ol> +1. Vous choisissez les garnitures que vous voulez. Cela peut prendre un certain temps si vous êtes indécis, et peut échouer si vous n'arrivez pas à vous décider, ou si vous décidez de prendre un curry à la place. +2. Vous passez ensuite votre commande. Le retour d'une pizza peut prendre un certain temps et peut échouer si le restaurant ne dispose pas des ingrédients nécessaires à sa cuisson. +3. Vous récupérez ensuite votre pizza et la mangez. Cela peut échouer si, par exemple, vous avez oublié votre portefeuille et ne pouvez pas payer la pizza ! -<p>Avec l'ancien modèle de <a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing#callbacks">rappels</a>, une représentation en pseudo-code de la fonctionnalité ci-dessus pourrait ressembler à quelque chose comme ceci :</p> +Avec l'ancien modèle de [rappels](/fr/docs/Learn/JavaScript/Asynchronous/Introducing#callbacks), une représentation en pseudo-code de la fonctionnalité ci-dessus pourrait ressembler à quelque chose comme ceci : -<pre class="brush: js">chooseToppings(function(toppings) { +```js +chooseToppings(function(toppings) { placeOrder(toppings, function(order) { collectOrder(order, function(pizza) { eatPizza(pizza); }, failureCallback); }, failureCallback); -}, failureCallback);</pre> +}, failureCallback); +``` -<p>Cela est désordonné et difficile à lire (souvent appelé « <a href="http://callbackhell.com/"><i>callback hell</i></a> »), nécessite que le <code>failureCallback()</code> soit appelé plusieurs fois (une fois pour chaque fonction imbriquée), avec d'autres problèmes en plus.</p> +Cela est désordonné et difficile à lire (souvent appelé « [_callback hell_](http://callbackhell.com/) »), nécessite que le `failureCallback()` soit appelé plusieurs fois (une fois pour chaque fonction imbriquée), avec d'autres problèmes en plus. -<h3 id="improvements_with_promises">Améliorations avec des promesses</h3> +### Améliorations avec des promesses -<p>Les promesses facilitent grandement l'écriture, l'analyse et l'exécution de situations telles que celle décrite ci-dessus. Si nous avions représenté le pseudo-code ci-dessus en utilisant des promesses asynchrones à la place, nous aurions obtenu quelque chose comme ceci :</p> +Les promesses facilitent grandement l'écriture, l'analyse et l'exécution de situations telles que celle décrite ci-dessus. Si nous avions représenté le pseudo-code ci-dessus en utilisant des promesses asynchrones à la place, nous aurions obtenu quelque chose comme ceci : -<pre class="brush: js">chooseToppings() +```js +chooseToppings() .then(function(toppings) { return placeOrder(toppings); }) @@ -111,322 +112,337 @@ translation_of: Learn/JavaScript/Asynchronous/Promises .then(function(pizza) { eatPizza(pizza); }) -.catch(failureCallback);</pre> +.catch(failureCallback); +``` -<p>C'est bien mieux - il est plus facile de voir ce qui se passe, nous n'avons besoin que d'un seul bloc <code>.catch()</code> pour gérer toutes les erreurs, cela ne bloque pas le processus principal (nous pouvons donc continuer à jouer à des jeux vidéo en attendant que la pizza soit prête à être collectée), et chaque opération a la garantie d'attendre que les opérations précédentes soient terminées avant de s'exécuter. Nous sommes en mesure d'enchaîner plusieurs actions asynchrones pour qu'elles se produisent les unes après les autres de cette façon, car chaque bloc <code>.then()</code> renvoie une nouvelle promesse qui se résout lorsque le bloc <code>.then()</code> a fini de s'exécuter. Astucieux, non ?</p> +C'est bien mieux - il est plus facile de voir ce qui se passe, nous n'avons besoin que d'un seul bloc `.catch()` pour gérer toutes les erreurs, cela ne bloque pas le processus principal (nous pouvons donc continuer à jouer à des jeux vidéo en attendant que la pizza soit prête à être collectée), et chaque opération a la garantie d'attendre que les opérations précédentes soient terminées avant de s'exécuter. Nous sommes en mesure d'enchaîner plusieurs actions asynchrones pour qu'elles se produisent les unes après les autres de cette façon, car chaque bloc `.then()` renvoie une nouvelle promesse qui se résout lorsque le bloc `.then()` a fini de s'exécuter. Astucieux, non ? -<p>En utilisant les fonctions flèches, vous pouvez simplifier encore plus le code :</p> +En utilisant les fonctions flèches, vous pouvez simplifier encore plus le code : -<pre class="brush: js">chooseToppings() -.then(toppings => +```js +chooseToppings() +.then(toppings => placeOrder(toppings) ) -.then(order => +.then(order => collectOrder(order) ) -.then(pizza => +.then(pizza => eatPizza(pizza) ) -.catch(failureCallback);</pre> - -<p>Ou encore ça :</p> - -<pre class="brush: js">chooseToppings() -.then(toppings => placeOrder(toppings)) -.then(order => collectOrder(order)) -.then(pizza => eatPizza(pizza)) -.catch(failureCallback);</pre> - -<p>Cela fonctionne car avec les fonctions flèches <code>() => x</code> est un raccourci valide pour <code>() => { return x ; }</code>.</p> - -<p>Vous pourriez même le faire ainsi, puisque les fonctions ne font que passer leurs arguments directement, et qu'il n'y a donc pas besoin de cette couche supplémentaire de fonctions :</p> - -<pre class="brush: js">chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback);</pre> - -<p>Cependant, la lecture n'est pas aussi facile et cette syntaxe peut ne pas être utilisable si vos blocs sont plus complexes que ce que nous avons montré ici.</p> - -<div class="note"> - <p><strong>Note :</strong> Vous pouvez apporter d'autres améliorations avec la syntaxe <code>async</code>/<code>await</code>, que nous aborderons dans le prochain article.</p> -</div> - -<p>Dans leur forme la plus basique, les promesses sont similaires aux écouteurs d'événements, mais avec quelques différences :</p> - -<ul> - <li>Une promesse ne peut réussir ou échouer qu'une seule fois. Elle ne peut pas réussir ou échouer deux fois et elle ne peut pas passer du succès à l'échec ou vice versa une fois l'opération terminée.</li> - <li>Si une promesse a réussi ou échoué et que vous ajoutez plus tard une de rappel de réussite/échec, la bonne fonction de rappel sera appelée, même si l'événement a eu lieu plus tôt.</li> -</ul> - -<h2 id="explaining_basic_promise_syntax_a_real_example">Explication de la syntaxe de base des promesses : exemple concret</h2> - -<p>Il est important de comprendre les promesses, car la plupart des API Web modernes les utilisent pour les fonctions qui exécutent des tâches potentiellement longues. Pour utiliser les technologies Web modernes, vous devrez utiliser des promesses. Plus loin dans ce chapitre, nous verrons comment écrire votre propre promesse, mais pour l'instant, nous allons nous pencher sur quelques exemples simples que vous rencontrerez dans les API Web.</p> - -<p>Dans le premier exemple, nous allons utiliser la méthode <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch"><code>fetch()</code></a> pour récupérer une image sur le web, la méthode <a href="/fr/docs/Web/API/Body/blob"><code>blob()</code></a> pour transformer le contenu brut du corps de la réponse fetch en un objet <a href="/fr/docs/Web/API/Blob"><code>Blob</code></a>, puis afficher ce blob à l'intérieur d'un élément <a href="/fr/docs/Web/HTML/Element/Img"><code><img></code></a>. Cet exemple est très similaire à celui que nous avons examiné dans le <a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing#asynchronous_javascript">premier article</a>, mais nous le ferons un peu différemment au fur et à mesure que nous vous ferons construire votre propre code basé sur des promesses.</p> - -<div class="note"> - <p><strong>Note :</strong> L'exemple suivant ne fonctionnera pas si vous l'exécutez directement à partir du fichier (c'est-à-dire via une URL <code>file://</code>). Vous devez l'exécuter via un <a href="/fr/docs/Learn/Common_questions/set_up_a_local_testing_server">serveur de test local</a>, ou utiliser une solution en ligne telle que <a href="https://glitch.com/">Glitch</a> ou <a href="/fr/docs/Learn/Common_questions/Using_Github_pages">les pages GitHub</a>.</p> -</div> - -<ol> - <li> - <p>Tout d'abord, téléchargez notre <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">modèle HTML simple</a> et le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg">fichier image</a> que nous allons récupérer.</p> - </li> - <li> - <p>Ajoutez un élément <a href="/fr/docs/Web/HTML/Element/script"><code><script></code></a> au bas de l'élément HTML <a href="/fr/docs/Web/HTML/Element/body"><code><body></code></a>.</p> - </li> - <li> - <p>À l'intérieur de votre élément <a href="/fr/docs/Web/HTML/Element/script"><code><script></code></a>, ajoutez la ligne suivante :</p> - <pre class="brush: js">let promise = fetch('coffee.jpg');</pre> - <p>Cela appelle la méthode <code>fetch()</code>, en lui passant en paramètre l'URL de l'image à récupérer sur le réseau. Cette méthode peut également prendre un objet d'options comme second paramètre facultatif, mais nous n'utilisons que la version la plus simple pour le moment. Nous stockons l'objet promesse retourné par <code>fetch()</code> à l'intérieur d'une variable appelée <code>promise</code>. Comme nous l'avons dit précédemment, cet objet représente un état intermédiaire qui n'est initialement ni un succès ni un échec - le terme officiel pour une promesse dans cet état est <strong>en attente</strong> (<i>pending</i> en anglais).</p> - </li> - <li> - <p>Pour répondre à l'achèvement réussi de l'opération lorsque cela se produit (dans ce cas, lorsqu'une <a href="/fr/docs/Web/API/Response">réponse</a> est retournée), nous invoquons la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/then"><code>.then()</code></a> de l'objet promesse. La fonction de rappel à l'intérieur du bloc <code>.then()</code> s'exécute uniquement lorsque l'appel de la promesse se termine avec succès et retourne l'objet <a href="/fr/docs/Web/API/Response"><code>Response</code></a> — en langage de promesse, lorsqu'elle a été <strong>remplie</strong> (<i>fullfilled</i> en anglais). On lui passe l'objet <a href="/fr/docs/Web/API/Response"><code>Response</code></a> retourné en tant que paramètre.</p> - <div class="note"> - <p><strong>Note :</strong> Le fonctionnement d'un bloc <code>.then()</code> est similaire à celui de l'ajout d'un écouteur d'événements à un objet à l'aide de <code>AddEventListener()</code>. Il ne s'exécute pas avant qu'un événement ne se produise (lorsque la promesse se réalise). La différence la plus notable est qu'un <code>.then()</code> ne s'exécutera qu'une fois à chaque fois qu'il sera utilisé, alors qu'un écouteur d'événements pourrait être invoqué plusieurs fois.</p> - </div> - <p>Nous exécutons immédiatement la méthode <code>blob()</code> sur cette réponse pour nous assurer que le corps de la réponse est entièrement téléchargé, et lorsqu'il est disponible, le transformer en un objet <code>Blob</code> avec lequel nous pouvons faire quelque chose. Le résultat de cette méthode est retourné comme suit :</p> - <pre class="brush: js">response => response.blob()</pre> - <p>qui est un raccourci de</p> - <pre class="brush: js">function(response) { - return response.blob(); -}</pre> - <p>Malheureusement, nous devons faire un peu plus que cela. Les promesses de récupération n'échouent pas sur les erreurs 404 ou 500 - seulement sur quelque chose de catastrophique comme une panne de réseau. Au lieu de cela, elles réussissent, mais avec la propriété <a href="/fr/docs/Web/API/Response/ok"><code>response.ok</code></a> définie à <code>false</code>. Pour produire une erreur sur un 404, par exemple, nous devons vérifier la valeur de <code>response.ok</code>, et si c'est <code>false</code>, lancer une erreur, ne renvoyant le blob que si elle est à <code>true</code>. Cela peut être fait comme suit - ajoutez les lignes suivantes sous votre première ligne de JavaScript.</p> - <pre class="brush: js">let promise2 = promise.then(response => { - if (!response.ok) { - throw new Error(`erreur HTTP ! statut : ${response.status}`); - } else { - return response.blob(); - } -});</pre> - </li> - <li> - <p>Chaque appel à la méthode <code>.then()</code> crée une nouvelle promesse. Ceci est très utile ; parce que la méthode <code>blob()</code> renvoie également une promesse, nous pouvons manipuler l'objet <code>Blob</code> qu'elle renvoie sur l'accomplissement en invoquant la méthode <code>.then()</code> de la seconde promesse. Parce que nous voulons faire quelque chose d'un peu plus complexe au blob que de simplement exécuter une seule méthode sur lui et renvoyer le résultat, nous devrons envelopper le corps de la fonction dans des accolades cette fois (sinon, ça lancera une erreur).</p> - <p>Ajoutez ce qui suit à la fin de votre code :</p> - <pre class="brush: js">let promise3 = promise2.then(myBlob => { -})</pre> - </li> - <li> - <p>Maintenant, remplissons le corps de la fonction de rappel <code>.then()</code>. Ajoutez les lignes suivantes à l'intérieur des accolades :</p> - <pre class="brush: js">let objectURL = URL.createObjectURL(myBlob); -let image = document.createElement('img'); -image.src = objectURL; -document.body.appendChild(image);</pre> - <p>Nous exécutons ici la méthode <a href="/fr/docs/Web/API/URL/createObjectURL"><code>URL.createObjectURL()</code></a>, en lui passant en paramètre le <code>Blob</code> renvoyé lors de la réalisation de la deuxième promesse. Cela permettra de renvoyer une URL pointant vers l'objet. Ensuite, nous créons un élément <a href="/fr/docs/Web/HTML/Element/Img"><code><img></code></a>, définissons son attribut <code>src</code> comme étant égal à l'URL de l'objet et l'ajoutons au DOM, de sorte que l'image s'affiche sur la page !</p> - </li> -</ol> - -<p>Si vous enregistrez le fichier HTML que vous venez de créer et le chargez dans votre navigateur, vous verrez que l'image s'affiche dans la page comme prévu. Bon travail !</p> - -<div class="note"> - <p><strong>Note :</strong> Vous remarquerez probablement que ces exemples sont quelque peu artificiels. Vous pourriez tout simplement vous passer de toute la chaîne <code>fetch()</code> et <code>blob()</code>, et simplement créer un élément <code><img></code> et définir la valeur de son attribut <code>src</code> à l'URL du fichier image, <code>coffee.jpg</code>. Nous avons toutefois choisi cet exemple parce qu'il démontre les promesses d'une manière simple et agréable, plutôt que pour sa pertinence dans le monde réel.</p> -</div> - -<h3 id="responding_to_failure">Réagir à un échec</h3> - -<p>Il manque quelque chose — actuellement, il n'y a rien pour gérer explicitement les erreurs si l'une des promesses <strong>échoue</strong> (<i>rejects</i>, en anglais). Nous pouvons ajouter la gestion des erreurs en exécutant la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch"><code>.catch()</code></a> de la promesse précédente. Ajoutez ceci maintenant :</p> - -<pre class="brush: js">let errorCase = promise3.catch(e => { +.catch(failureCallback); +``` + +Ou encore ça : + +```js +chooseToppings() +.then(toppings => placeOrder(toppings)) +.then(order => collectOrder(order)) +.then(pizza => eatPizza(pizza)) +.catch(failureCallback); +``` + +Cela fonctionne car avec les fonctions flèches `() => x` est un raccourci valide pour `() => { return x ; }`. + +Vous pourriez même le faire ainsi, puisque les fonctions ne font que passer leurs arguments directement, et qu'il n'y a donc pas besoin de cette couche supplémentaire de fonctions : + +```js +chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback); +``` + +Cependant, la lecture n'est pas aussi facile et cette syntaxe peut ne pas être utilisable si vos blocs sont plus complexes que ce que nous avons montré ici. + +> **Note :** Vous pouvez apporter d'autres améliorations avec la syntaxe `async`/`await`, que nous aborderons dans le prochain article. + +Dans leur forme la plus basique, les promesses sont similaires aux écouteurs d'événements, mais avec quelques différences : + +- Une promesse ne peut réussir ou échouer qu'une seule fois. Elle ne peut pas réussir ou échouer deux fois et elle ne peut pas passer du succès à l'échec ou vice versa une fois l'opération terminée. +- Si une promesse a réussi ou échoué et que vous ajoutez plus tard une de rappel de réussite/échec, la bonne fonction de rappel sera appelée, même si l'événement a eu lieu plus tôt. + +## Explication de la syntaxe de base des promesses : exemple concret + +Il est important de comprendre les promesses, car la plupart des API Web modernes les utilisent pour les fonctions qui exécutent des tâches potentiellement longues. Pour utiliser les technologies Web modernes, vous devrez utiliser des promesses. Plus loin dans ce chapitre, nous verrons comment écrire votre propre promesse, mais pour l'instant, nous allons nous pencher sur quelques exemples simples que vous rencontrerez dans les API Web. + +Dans le premier exemple, nous allons utiliser la méthode [`fetch()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch) pour récupérer une image sur le web, la méthode [`blob()`](/fr/docs/Web/API/Body/blob) pour transformer le contenu brut du corps de la réponse fetch en un objet [`Blob`](/fr/docs/Web/API/Blob), puis afficher ce blob à l'intérieur d'un élément [`<img>`](/fr/docs/Web/HTML/Element/Img). Cet exemple est très similaire à celui que nous avons examiné dans le [premier article](/fr/docs/Learn/JavaScript/Asynchronous/Introducing#asynchronous_javascript), mais nous le ferons un peu différemment au fur et à mesure que nous vous ferons construire votre propre code basé sur des promesses. + +> **Note :** L'exemple suivant ne fonctionnera pas si vous l'exécutez directement à partir du fichier (c'est-à-dire via une URL `file://`). Vous devez l'exécuter via un [serveur de test local](/fr/docs/Learn/Common_questions/set_up_a_local_testing_server), ou utiliser une solution en ligne telle que [Glitch](https://glitch.com/) ou [les pages GitHub](/fr/docs/Learn/Common_questions/Using_Github_pages). + +1. Tout d'abord, téléchargez notre [modèle HTML simple](https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html) et le [fichier image](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg) que nous allons récupérer. +2. Ajoutez un élément [`<script>`](/fr/docs/Web/HTML/Element/script) au bas de l'élément HTML [`<body>`](/fr/docs/Web/HTML/Element/body). +3. À l'intérieur de votre élément [`<script>`](/fr/docs/Web/HTML/Element/script), ajoutez la ligne suivante : + + ```js + let promise = fetch('coffee.jpg'); + ``` + + Cela appelle la méthode `fetch()`, en lui passant en paramètre l'URL de l'image à récupérer sur le réseau. Cette méthode peut également prendre un objet d'options comme second paramètre facultatif, mais nous n'utilisons que la version la plus simple pour le moment. Nous stockons l'objet promesse retourné par `fetch()` à l'intérieur d'une variable appelée `promise`. Comme nous l'avons dit précédemment, cet objet représente un état intermédiaire qui n'est initialement ni un succès ni un échec - le terme officiel pour une promesse dans cet état est **en attente** (_pending_ en anglais). + +4. Pour répondre à l'achèvement réussi de l'opération lorsque cela se produit (dans ce cas, lorsqu'une [réponse](/fr/docs/Web/API/Response) est retournée), nous invoquons la méthode [`.then()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) de l'objet promesse. La fonction de rappel à l'intérieur du bloc `.then()` s'exécute uniquement lorsque l'appel de la promesse se termine avec succès et retourne l'objet [`Response`](/fr/docs/Web/API/Response) — en langage de promesse, lorsqu'elle a été **remplie** (_fullfilled_ en anglais). On lui passe l'objet [`Response`](/fr/docs/Web/API/Response) retourné en tant que paramètre. + + > **Note :** Le fonctionnement d'un bloc `.then()` est similaire à celui de l'ajout d'un écouteur d'événements à un objet à l'aide de `AddEventListener()`. Il ne s'exécute pas avant qu'un événement ne se produise (lorsque la promesse se réalise). La différence la plus notable est qu'un `.then()` ne s'exécutera qu'une fois à chaque fois qu'il sera utilisé, alors qu'un écouteur d'événements pourrait être invoqué plusieurs fois. + + Nous exécutons immédiatement la méthode `blob()` sur cette réponse pour nous assurer que le corps de la réponse est entièrement téléchargé, et lorsqu'il est disponible, le transformer en un objet `Blob` avec lequel nous pouvons faire quelque chose. Le résultat de cette méthode est retourné comme suit : + + ```js + response => response.blob() + ``` + + qui est un raccourci de + + ```js + function(response) { + return response.blob(); + } + ``` + + Malheureusement, nous devons faire un peu plus que cela. Les promesses de récupération n'échouent pas sur les erreurs 404 ou 500 - seulement sur quelque chose de catastrophique comme une panne de réseau. Au lieu de cela, elles réussissent, mais avec la propriété [`response.ok`](/fr/docs/Web/API/Response/ok) définie à `false`. Pour produire une erreur sur un 404, par exemple, nous devons vérifier la valeur de `response.ok`, et si c'est `false`, lancer une erreur, ne renvoyant le blob que si elle est à `true`. Cela peut être fait comme suit - ajoutez les lignes suivantes sous votre première ligne de JavaScript. + + ```js + let promise2 = promise.then(response => { + if (!response.ok) { + throw new Error(`erreur HTTP ! statut : ${response.status}`); + } else { + return response.blob(); + } + }); + ``` + +5. Chaque appel à la méthode `.then()` crée une nouvelle promesse. Ceci est très utile ; parce que la méthode `blob()` renvoie également une promesse, nous pouvons manipuler l'objet `Blob` qu'elle renvoie sur l'accomplissement en invoquant la méthode `.then()` de la seconde promesse. Parce que nous voulons faire quelque chose d'un peu plus complexe au blob que de simplement exécuter une seule méthode sur lui et renvoyer le résultat, nous devrons envelopper le corps de la fonction dans des accolades cette fois (sinon, ça lancera une erreur). + + Ajoutez ce qui suit à la fin de votre code : + + ```js + let promise3 = promise2.then(myBlob => { + }) + ``` + +6. Maintenant, remplissons le corps de la fonction de rappel `.then()`. Ajoutez les lignes suivantes à l'intérieur des accolades : + + ```js + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); + ``` + + Nous exécutons ici la méthode [`URL.createObjectURL()`](/fr/docs/Web/API/URL/createObjectURL), en lui passant en paramètre le `Blob` renvoyé lors de la réalisation de la deuxième promesse. Cela permettra de renvoyer une URL pointant vers l'objet. Ensuite, nous créons un élément [`<img>`](/fr/docs/Web/HTML/Element/Img), définissons son attribut `src` comme étant égal à l'URL de l'objet et l'ajoutons au DOM, de sorte que l'image s'affiche sur la page ! + +Si vous enregistrez le fichier HTML que vous venez de créer et le chargez dans votre navigateur, vous verrez que l'image s'affiche dans la page comme prévu. Bon travail ! + +> **Note :** Vous remarquerez probablement que ces exemples sont quelque peu artificiels. Vous pourriez tout simplement vous passer de toute la chaîne `fetch()` et `blob()`, et simplement créer un élément `<img>` et définir la valeur de son attribut `src` à l'URL du fichier image, `coffee.jpg`. Nous avons toutefois choisi cet exemple parce qu'il démontre les promesses d'une manière simple et agréable, plutôt que pour sa pertinence dans le monde réel. + +### Réagir à un échec + +Il manque quelque chose — actuellement, il n'y a rien pour gérer explicitement les erreurs si l'une des promesses **échoue** (_rejects_, en anglais). Nous pouvons ajouter la gestion des erreurs en exécutant la méthode [`.catch()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) de la promesse précédente. Ajoutez ceci maintenant : + +```js +let errorCase = promise3.catch(e => { console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message); -});</pre> +}); +``` -<p>Pour voir cela en action, essayez de mal orthographier l'URL de l'image et de recharger la page. L'erreur sera signalée dans la console des outils de développement de votre navigateur.</p> +Pour voir cela en action, essayez de mal orthographier l'URL de l'image et de recharger la page. L'erreur sera signalée dans la console des outils de développement de votre navigateur. -<p>Cela ne fait pas beaucoup plus que si vous ne preniez pas la peine d'inclure le bloc <code>.catch()</code> du tout, mais pensez-y - cela nous permet de contrôler la gestion des erreurs exactement comme nous le voulons. Dans une application réelle, votre bloc <code>.catch()</code> pourrait réessayer de récupérer l'image, ou afficher une image par défaut, ou demander à l'utilisateur de fournir une URL d'image différente, ou autre.</p> +Cela ne fait pas beaucoup plus que si vous ne preniez pas la peine d'inclure le bloc `.catch()` du tout, mais pensez-y - cela nous permet de contrôler la gestion des erreurs exactement comme nous le voulons. Dans une application réelle, votre bloc `.catch()` pourrait réessayer de récupérer l'image, ou afficher une image par défaut, ou demander à l'utilisateur de fournir une URL d'image différente, ou autre. -<div class="note"> - <p><strong>Note :</strong> Vous pouvez voir <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch.html">notre version de l'exemple en direct</a> (voir également son <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch.html">code source</a>).</p> -</div> +> **Note :** Vous pouvez voir [notre version de l'exemple en direct](https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch.html) (voir également son [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch.html)). -<h3 id="chaining_the_blocks_together">Enchaîner les blocs</h3> +### Enchaîner les blocs -<p>C'est une façon très manuscrite d'écrire cela ; nous l'avons délibérément fait pour vous aider à comprendre clairement ce qui se passe. Comme nous l'avons montré plus haut dans l'article, vous pouvez enchaîner les blocs <code>.then()</code> (et aussi les blocs <code>.catch()</code>). Le code ci-dessus pourrait aussi être écrit comme ceci (voir aussi <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html">simple-fetch-chained.html</a> sur GitHub) :</p> +C'est une façon très manuscrite d'écrire cela ; nous l'avons délibérément fait pour vous aider à comprendre clairement ce qui se passe. Comme nous l'avons montré plus haut dans l'article, vous pouvez enchaîner les blocs `.then()` (et aussi les blocs `.catch()`). Le code ci-dessus pourrait aussi être écrit comme ceci (voir aussi [simple-fetch-chained.html](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html) sur GitHub) : -<pre class="brush: js">fetch('coffee.jpg') -.then(response => { +```js +fetch('coffee.jpg') +.then(response => { if (!response.ok) { throw new Error(`Erreur HTTP ! statut : ${response.status}`); } else { return response.blob(); } }) -.then(myBlob => { +.then(myBlob => { let objectURL = URL.createObjectURL(myBlob); let image = document.createElement('img'); image.src = objectURL; document.body.appendChild(image); }) -.catch(e => { +.catch(e => { console.log('Il y a eu un problème avec votre opération de récupération : ' + e.message); -});</pre> +}); +``` + +Gardez à l'esprit que la valeur renvoyée par une promesse remplie devient le paramètre transmis à la fonction de rappel du bloc `.then()` suivant. -<p>Gardez à l'esprit que la valeur renvoyée par une promesse remplie devient le paramètre transmis à la fonction de rappel du bloc <code>.then()</code> suivant.</p> +> **Note :** Les blocs `.then()`/`.catch()` dans les promesses sont essentiellement l'équivalent asynchrone d'un bloc [`try...catch`](/fr/docs/Web/JavaScript/Reference/Statements/try...catch) dans du code synchrone. Gardez à l'esprit que le `try...catch` synchrone ne fonctionnera pas dans du code asynchrone. -<div class="note"> - <p><strong>Note :</strong> Les blocs <code>.then()</code>/<code>.catch()</code> dans les promesses sont essentiellement l'équivalent asynchrone d'un bloc <code><a href="/fr/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> dans du code synchrone. Gardez à l'esprit que le <code>try...catch</code> synchrone ne fonctionnera pas dans du code asynchrone.</p> -</div> +## Récapitulatif de la terminologie des promesses -<h2 id="promise_terminology_recap">Récapitulatif de la terminologie des promesses</h2> +Il y avait beaucoup à couvrir dans la section ci-dessus, alors revenons-y rapidement pour vous donner un [court guide que vous pouvez mettre en favoris](#promise_terminology_recap) et utiliser pour vous rafraîchir la mémoire à l'avenir. Vous devriez également revoir la section ci-dessus quelques fois de plus pour vous assurer que ces concepts sont bien assimilés. -<p>Il y avait beaucoup à couvrir dans la section ci-dessus, alors revenons-y rapidement pour vous donner un <a href="#promise_terminology_recap" >court guide que vous pouvez mettre en favoris</a> et utiliser pour vous rafraîchir la mémoire à l'avenir. Vous devriez également revoir la section ci-dessus quelques fois de plus pour vous assurer que ces concepts sont bien assimilés.</p> +1. Lorsqu'une promesse est créée, elle n'est ni dans un état de réussite ni dans un état d'échec. On dit qu'elle est **en attente**. +2. Lorsqu'une promesse est retournée, on dit qu'elle est **résolue**. -<ol> - <li>Lorsqu'une promesse est créée, elle n'est ni dans un état de réussite ni dans un état d'échec. On dit qu'elle est <strong>en attente</strong>.</li> - <li>Lorsqu'une promesse est retournée, on dit qu'elle est <strong>résolue</strong>. - <ol> - <li>Une promesse résolue avec succès est dite <strong>remplie</strong>. Elle retourne une valeur, à laquelle on peut accéder en enchaînant un bloc <code>.then()</code> à la fin de la chaîne de promesses. La fonction de rappel à l'intérieur du bloc <code>.then()</code> contiendra la valeur de retour de la promesse.</li> - <li>Une promesse résolue non aboutie est dite <strong>rejetée</strong>. Elle renvoie une <strong>raison</strong>, un message d'erreur indiquant pourquoi la promesse a été rejetée. On peut accéder à cette raison en enchaînant un bloc <code>.catch()</code> à la fin de la chaîne de promesses.</li> - </ol> - </li> -</ol> + 1. Une promesse résolue avec succès est dite **remplie**. Elle retourne une valeur, à laquelle on peut accéder en enchaînant un bloc `.then()` à la fin de la chaîne de promesses. La fonction de rappel à l'intérieur du bloc `.then()` contiendra la valeur de retour de la promesse. + 2. Une promesse résolue non aboutie est dite **rejetée**. Elle renvoie une **raison**, un message d'erreur indiquant pourquoi la promesse a été rejetée. On peut accéder à cette raison en enchaînant un bloc `.catch()` à la fin de la chaîne de promesses. -<h2 id="running_code_in_response_to_multiple_promises_fulfilling">Exécution du code en réponse à des promesses multiples remplies</h2> +## Exécution du code en réponse à des promesses multiples remplies -<p>L'exemple ci-dessus nous a montré certaines des bases réelles de l'utilisation des promesses. Voyons maintenant quelques fonctionnalités plus avancées. Pour commencer, enchaîner des processus pour qu'ils se réalisent l'un après l'autre, c'est très bien, mais que faire si vous voulez exécuter du code seulement après que tout un tas de promesses aient <em>toutes</em> été remplies ?</p> +L'exemple ci-dessus nous a montré certaines des bases réelles de l'utilisation des promesses. Voyons maintenant quelques fonctionnalités plus avancées. Pour commencer, enchaîner des processus pour qu'ils se réalisent l'un après l'autre, c'est très bien, mais que faire si vous voulez exécuter du code seulement après que tout un tas de promesses aient _toutes_ été remplies ? -<p>Vous pouvez le faire avec la méthode statique ingénieusement nommée <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/all"><code>Promise.all()</code></a>. Celle-ci prend un tableau de promesses comme paramètre d'entrée et retourne un nouvel objet <code>Promise</code> qui ne se réalisera que si et quand <em>toutes</em> les promesses du tableau se réaliseront. Cela ressemble à quelque chose comme ceci :</p> +Vous pouvez le faire avec la méthode statique ingénieusement nommée [`Promise.all()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/all). Celle-ci prend un tableau de promesses comme paramètre d'entrée et retourne un nouvel objet `Promise` qui ne se réalisera que si et quand _toutes_ les promesses du tableau se réaliseront. Cela ressemble à quelque chose comme ceci : -<pre class="brush: js">Promise.all([a, b, c]).then(values => { +```js +Promise.all([a, b, c]).then(values => { ... -});</pre> +}); +``` -<p>Si elles se réalisent toutes, la fonction de callback du bloc <code>.then()</code> enchaîné se verra passer un tableau contenant tous ces résultats en paramètre. Si l'une des promesses passées à <code>Promise.all()</code> rejette, le bloc entier sera rejeté.</p> +Si elles se réalisent toutes, la fonction de callback du bloc `.then()` enchaîné se verra passer un tableau contenant tous ces résultats en paramètre. Si l'une des promesses passées à `Promise.all()` rejette, le bloc entier sera rejeté. -<p>Cela peut être très utile. Imaginez que nous récupérions des informations pour alimenter dynamiquement en contenu une fonction de l'interface utilisateur de notre page. Dans de nombreux cas, il est préférable de recevoir toutes les données et de n'afficher que le contenu complet, plutôt que d'afficher des informations partielles.</p> +Cela peut être très utile. Imaginez que nous récupérions des informations pour alimenter dynamiquement en contenu une fonction de l'interface utilisateur de notre page. Dans de nombreux cas, il est préférable de recevoir toutes les données et de n'afficher que le contenu complet, plutôt que d'afficher des informations partielles. -<p>Construisons un autre exemple pour montrer cela en action.</p> +Construisons un autre exemple pour montrer cela en action. -<ol> - <li> - <p>Téléchargez une nouvelle copie de notre <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">modèle de page</a>, et mettez à nouveau un élément <code><script></code> juste avant la balise de fermeture <code></body></code>.</p> - </li> - <li> - <p>Téléchargez nos fichiers sources (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg">coffee.jpg</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/tea.jpg">tea.jpg</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/description.txt">description.txt</a>), ou n'hésitez pas à y substituer les vôtres.</p> - </li> - <li> - <p>Dans notre script, nous allons d'abord définir une fonction qui retourne les promesses que nous voulons envoyer à <code>Promise.all()</code>. Cela serait facile si nous voulions simplement exécuter le bloc <code>Promise.all()</code> en réponse à trois opérations <code>fetch()</code> qui se terminent. Nous pourrions simplement faire quelque chose comme :</p> - <pre class="brush: js">let a = fetch(url1); -let b = fetch(url2); -let c = fetch(url3); +1. Téléchargez une nouvelle copie de notre [modèle de page](https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html), et mettez à nouveau un élément `<script>` juste avant la balise de fermeture `</body>`. +2. Téléchargez nos fichiers sources ([coffee.jpg](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg), [tea.jpg](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/tea.jpg), et [description.txt](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/description.txt)), ou n'hésitez pas à y substituer les vôtres. +3. Dans notre script, nous allons d'abord définir une fonction qui retourne les promesses que nous voulons envoyer à `Promise.all()`. Cela serait facile si nous voulions simplement exécuter le bloc `Promise.all()` en réponse à trois opérations `fetch()` qui se terminent. Nous pourrions simplement faire quelque chose comme : -Promise.all([a, b, c]).then(values => { - ... -});</pre> - <p>Lorsque la promesse est réalisée, les <code>values</code> (valeurs) passées dans le gestionnaire de réalisation contiendraient trois objets <code>Response</code>, un pour chacune des opérations <code>fetch()</code> qui se sont terminées.</p> - <p>Cependant, nous ne voulons pas faire cela. Notre code ne se soucie pas de savoir quand les opérations <code>fetch()</code> sont effectuées. Au lieu de cela, ce que nous voulons, ce sont les données chargées. Cela signifie que nous voulons exécuter le bloc <code>Promise.all()</code> lorsque nous récupérons des blobs utilisables représentant les images, et une chaîne de texte utilisable. Nous pouvons écrire une fonction qui fait cela ; ajoutez ce qui suit à l'intérieur de votre élément <code><script></code> :</p> - <pre class="brush: js">function fetchAndDecode(url, type) { - return fetch(url).then(response => { - if(!response.ok) { - throw new Error(`Erreur HTTP ! statut : ${response.status}`); - } else { - if(type === 'blob') { - return response.blob(); - } else if(type === 'text') { - return response.text(); - } + ```js + let a = fetch(url1); + let b = fetch(url2); + let c = fetch(url3); + + Promise.all([a, b, c]).then(values => { + ... + }); + ``` + + Lorsque la promesse est réalisée, les `values` (valeurs) passées dans le gestionnaire de réalisation contiendraient trois objets `Response`, un pour chacune des opérations `fetch()` qui se sont terminées. + + Cependant, nous ne voulons pas faire cela. Notre code ne se soucie pas de savoir quand les opérations `fetch()` sont effectuées. Au lieu de cela, ce que nous voulons, ce sont les données chargées. Cela signifie que nous voulons exécuter le bloc `Promise.all()` lorsque nous récupérons des blobs utilisables représentant les images, et une chaîne de texte utilisable. Nous pouvons écrire une fonction qui fait cela ; ajoutez ce qui suit à l'intérieur de votre élément `<script>` : + + ```js + function fetchAndDecode(url, type) { + return fetch(url).then(response => { + if(!response.ok) { + throw new Error(`Erreur HTTP ! statut : ${response.status}`); + } else { + if(type === 'blob') { + return response.blob(); + } else if(type === 'text') { + return response.text(); + } + } + }) + .catch(e => { + console.log( + `Il y a eu un problème avec votre opération de récupération de la ressource "${url}" : ` + e.message); + }); } - }) - .catch(e => { - console.log( - `Il y a eu un problème avec votre opération de récupération de la ressource "${url}" : ` + e.message); - }); -}</pre> - <p>Cela semble un peu complexe, alors nous allons le faire étape par étape :</p> - <ol> - <li>Tout d'abord, nous définissons la fonction, en lui passant une URL et une chaîne représentant le type de ressource qu'elle va chercher.</li> - <li>À l'intérieur du corps de la fonction, nous avons une structure similaire à celle que nous avons vue dans le premier exemple — nous appelons la fonction <code>fetch()</code> pour récupérer la ressource à l'URL spécifiée, puis nous l'enchaînons sur une autre promesse qui renvoie le corps de réponse décodé (ou « lu »). Il s'agissait toujours de la méthode <code>blob()</code> dans l'exemple précédent.</li> - <li>Cependant, deux choses sont différentes ici : - <ul> - <li>Tout d'abord, la deuxième promesse que nous retournons est différente en fonction de la valeur <code>type</code>. À l'intérieur de la fonction de rappel <code>.then()</code>, nous incluons une simple déclaration <code>if ... else if</code> pour retourner une promesse différente selon le type de fichier que nous devons décoder (dans ce cas, nous avons le choix entre <code>blob</code> et <code>text</code>, mais il serait facile d'étendre cela pour traiter d'autres types également).</li> - <li>Deuxièmement, nous avons ajouté le mot-clé <code>return</code> avant l'appel <code>fetch()</code>. Cela a pour effet d'exécuter toute la chaîne, puis d'exécuter le résultat final (c'est-à-dire la promesse retournée par <code>blob()</code> ou <code>text()</code>) comme valeur de retour de la fonction que nous venons de définir. En effet, les instructions <code>return</code> font remonter les résultats au sommet de la chaîne.</li> - </ul> - </li> - <li> - <p>À la fin du bloc, nous enchaînons sur un appel <code>.catch()</code>, pour gérer les cas d'erreur qui peuvent survenir avec l'une des promesses passées dans le tableau à <code>.all()</code>. Si l'une des promesses est rejetée, le bloc <code>.catch()</code> vous fera savoir laquelle avait un problème. Le bloc <code>.all()</code> (voir ci-dessous) s'exécutera quand même, mais il n'affichera pas les ressources qui ont eu des problèmes. Rappelez-vous que, une fois que vous avez traité la promesse avec un bloc <code>.catch()</code>, la promesse résultante est considérée comme résolue mais avec une valeur de <code>undefined</code> ; c'est pourquoi, dans ce cas, le bloc <code>.all()</code> sera toujours rempli. Si vous vouliez que le bloc <code>.all()</code> rejette, vous devriez plutôt enchaîner le bloc <code>.catch()</code> à la fin du <code>.all()</code>.</p> - </li> - </ol> - <p>Le code à l'intérieur du corps de la fonction est asynchrone et basé sur une promesse, donc en fait, la fonction entière agit comme une promesse — pratique.</p> - </li> - <li> - <p>Ensuite, nous appelons notre fonction trois fois pour commencer le processus de récupération et de décodage des images et du texte et nous stockons chacune des promesses retournées dans une variable. Ajoutez le texte suivant sous votre code précédent :</p> - <pre class="brush: js">let coffee = fetchAndDecode('coffee.jpg', 'blob'); -let tea = fetchAndDecode('tea.jpg', 'blob'); -let description = fetchAndDecode('description.txt', 'text');</pre> - </li> - <li> - <p>Ensuite, nous allons définir un bloc <code>Promesse.all()</code> pour exécuter un certain code uniquement lorsque les trois promesses stockées ci-dessus se sont réalisées avec succès. Pour commencer, ajoutez un bloc avec une fonction de rappel vide à l'intérieur de l'appel <code>.then()</code>, comme ceci :</p> - <pre class="brush: js">Promise.all([coffee, tea, description]).then(values => { - -});</pre> - <p>Vous pouvez voir qu'elle prend un tableau contenant les promesses comme paramètre. La fonction de rappel <code>.then()</code> ne sera exécutée que lorsque les trois promesses seront résolues ; lorsque cela se produira, on lui transmettra un tableau contenant les résultats des promesses individuelles (c'est-à-dire les corps de réponse décodés), un peu comme suit [coffee-results, tea-results, description-results].</p> - </li> - <li> - <p>Enfin, ajoutez ce qui suit à l'intérieur de la fonction de rappel. Nous utilisons ici un code de synchronisation assez simple pour stocker les résultats dans des variables séparées (en créant des URL d'objets à partir des blobs), puis nous affichons les images et le texte sur la page.</p> - <pre class="brush: js">console.log(values); -// Stocke chaque valeur renvoyée par les promesses dans -// des variables distinctes ; crée des URL d'objets à partir des blobs. -let objectURL1 = URL.createObjectURL(values[0]); -let objectURL2 = URL.createObjectURL(values[1]); -let descText = values[2]; - -// Affiche les images dans les éléments <img> -let image1 = document.createElement('img'); -let image2 = document.createElement('img'); -image1.src = objectURL1; -image2.src = objectURL2; -document.body.appendChild(image1); -document.body.appendChild(image2); - -// Affiche le texte d'un paragraphe -let para = document.createElement('p'); -para.textContent = descText; -document.body.appendChild(para);</pre> - </li> - <li> - <p>Sauvegardez et actualisez et vous devriez voir vos composants d'interface utilisateur chargés, bien que d'une manière peu attrayante !</p> - </li> -</ol> - -<p>Le code que nous avons fourni ici pour l'affichage des articles est assez rudimentaire, mais il fonctionne comme une explication pour le moment.</p> - -<div class="note"> - <p><strong>Note :</strong> Si vous êtes bloqué, vous pouvez comparer votre version du code à la nôtre, pour voir à quoi elle est censée ressembler - <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html">voir en direct</a>, et voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">code source</a>.</p> -</div> - -<div class="note"> - <p><strong>Note :</strong> Si vous amélioriez ce code, vous pourriez vouloir boucler sur une liste d'éléments à afficher, en récupérant et en décodant chacun d'eux, puis boucler sur les résultats à l'intérieur de <code>Promise.all()</code>, en exécutant une fonction différente pour afficher chacun d'eux en fonction du type de code. Cela permettrait de fonctionner pour n'importe quel nombre d'éléments, pas seulement trois.</p> - <p>De plus, vous pourriez déterminer quel est le type de fichier récupéré sans avoir besoin d'une propriété <code>type</code> explicite. Vous pourriez, par exemple, vérifier l'en-tête HTTP <a href="/fr/docs/Web/HTTP/Headers/Content-Type"><code>Content-Type</code></a> de la réponse dans chaque cas en utilisant <a href="/fr/docs/Web/API/Headers/get"><code>response.headers.get("content-type")</code></a>, puis agir en conséquence.</p> -</div> - -<h2 id="running_some_final_code_after_a_promise_fulfillsrejects">Exécution d'un code final après l'accomplissement/le rejet d'une promesse.</h2> - -<p>Il y aura des cas où vous voudrez exécuter un bloc de code final après la fin d'une promesse, qu'elle se soit réalisée ou rejetée. Auparavant, vous deviez inclure le même code dans les deux fonctions de rappel <code>.then()</code> et <code>.catch()</code>, par exemple :</p> - -<pre class="brush: js">myPromise -.then(response => { + ``` + + Cela semble un peu complexe, alors nous allons le faire étape par étape : + + 1. Tout d'abord, nous définissons la fonction, en lui passant une URL et une chaîne représentant le type de ressource qu'elle va chercher. + 2. À l'intérieur du corps de la fonction, nous avons une structure similaire à celle que nous avons vue dans le premier exemple — nous appelons la fonction `fetch()` pour récupérer la ressource à l'URL spécifiée, puis nous l'enchaînons sur une autre promesse qui renvoie le corps de réponse décodé (ou « lu »). Il s'agissait toujours de la méthode `blob()` dans l'exemple précédent. + 3. Cependant, deux choses sont différentes ici : + + - Tout d'abord, la deuxième promesse que nous retournons est différente en fonction de la valeur `type`. À l'intérieur de la fonction de rappel `.then()`, nous incluons une simple déclaration `if ... else if` pour retourner une promesse différente selon le type de fichier que nous devons décoder (dans ce cas, nous avons le choix entre `blob` et `text`, mais il serait facile d'étendre cela pour traiter d'autres types également). + - Deuxièmement, nous avons ajouté le mot-clé `return` avant l'appel `fetch()`. Cela a pour effet d'exécuter toute la chaîne, puis d'exécuter le résultat final (c'est-à-dire la promesse retournée par `blob()` ou `text()`) comme valeur de retour de la fonction que nous venons de définir. En effet, les instructions `return` font remonter les résultats au sommet de la chaîne. + + 4. À la fin du bloc, nous enchaînons sur un appel `.catch()`, pour gérer les cas d'erreur qui peuvent survenir avec l'une des promesses passées dans le tableau à `.all()`. Si l'une des promesses est rejetée, le bloc `.catch()` vous fera savoir laquelle avait un problème. Le bloc `.all()` (voir ci-dessous) s'exécutera quand même, mais il n'affichera pas les ressources qui ont eu des problèmes. Rappelez-vous que, une fois que vous avez traité la promesse avec un bloc `.catch()`, la promesse résultante est considérée comme résolue mais avec une valeur de `undefined` ; c'est pourquoi, dans ce cas, le bloc `.all()` sera toujours rempli. Si vous vouliez que le bloc `.all()` rejette, vous devriez plutôt enchaîner le bloc `.catch()` à la fin du `.all()`. + + Le code à l'intérieur du corps de la fonction est asynchrone et basé sur une promesse, donc en fait, la fonction entière agit comme une promesse — pratique. + +4. Ensuite, nous appelons notre fonction trois fois pour commencer le processus de récupération et de décodage des images et du texte et nous stockons chacune des promesses retournées dans une variable. Ajoutez le texte suivant sous votre code précédent : + + ```js + let coffee = fetchAndDecode('coffee.jpg', 'blob'); + let tea = fetchAndDecode('tea.jpg', 'blob'); + let description = fetchAndDecode('description.txt', 'text'); + ``` + +5. Ensuite, nous allons définir un bloc `Promesse.all()` pour exécuter un certain code uniquement lorsque les trois promesses stockées ci-dessus se sont réalisées avec succès. Pour commencer, ajoutez un bloc avec une fonction de rappel vide à l'intérieur de l'appel `.then()`, comme ceci : + + ```js + Promise.all([coffee, tea, description]).then(values => { + + }); + ``` + + Vous pouvez voir qu'elle prend un tableau contenant les promesses comme paramètre. La fonction de rappel `.then()` ne sera exécutée que lorsque les trois promesses seront résolues ; lorsque cela se produira, on lui transmettra un tableau contenant les résultats des promesses individuelles (c'est-à-dire les corps de réponse décodés), un peu comme suit \[coffee-results, tea-results, description-results]. + +6. Enfin, ajoutez ce qui suit à l'intérieur de la fonction de rappel. Nous utilisons ici un code de synchronisation assez simple pour stocker les résultats dans des variables séparées (en créant des URL d'objets à partir des blobs), puis nous affichons les images et le texte sur la page. + + ```js + console.log(values); + // Stocke chaque valeur renvoyée par les promesses dans + // des variables distinctes ; crée des URL d'objets à partir des blobs. + let objectURL1 = URL.createObjectURL(values[0]); + let objectURL2 = URL.createObjectURL(values[1]); + let descText = values[2]; + + // Affiche les images dans les éléments <img> + let image1 = document.createElement('img'); + let image2 = document.createElement('img'); + image1.src = objectURL1; + image2.src = objectURL2; + document.body.appendChild(image1); + document.body.appendChild(image2); + + // Affiche le texte d'un paragraphe + let para = document.createElement('p'); + para.textContent = descText; + document.body.appendChild(para); + ``` + +7. Sauvegardez et actualisez et vous devriez voir vos composants d'interface utilisateur chargés, bien que d'une manière peu attrayante ! + +Le code que nous avons fourni ici pour l'affichage des articles est assez rudimentaire, mais il fonctionne comme une explication pour le moment. + +> **Note :** Si vous êtes bloqué, vous pouvez comparer votre version du code à la nôtre, pour voir à quoi elle est censée ressembler - [voir en direct](https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html), et voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html). + +> **Note :** Si vous amélioriez ce code, vous pourriez vouloir boucler sur une liste d'éléments à afficher, en récupérant et en décodant chacun d'eux, puis boucler sur les résultats à l'intérieur de `Promise.all()`, en exécutant une fonction différente pour afficher chacun d'eux en fonction du type de code. Cela permettrait de fonctionner pour n'importe quel nombre d'éléments, pas seulement trois. +> +> De plus, vous pourriez déterminer quel est le type de fichier récupéré sans avoir besoin d'une propriété `type` explicite. Vous pourriez, par exemple, vérifier l'en-tête HTTP [`Content-Type`](/fr/docs/Web/HTTP/Headers/Content-Type) de la réponse dans chaque cas en utilisant [`response.headers.get("content-type")`](/fr/docs/Web/API/Headers/get), puis agir en conséquence. + +## Exécution d'un code final après l'accomplissement/le rejet d'une promesse. + +Il y aura des cas où vous voudrez exécuter un bloc de code final après la fin d'une promesse, qu'elle se soit réalisée ou rejetée. Auparavant, vous deviez inclure le même code dans les deux fonctions de rappel `.then()` et `.catch()`, par exemple : + +```js +myPromise +.then(response => { doSomething(response); runFinalCode(); }) -.catch(e => { +.catch(e => { returnError(e); runFinalCode(); -});</pre> +}); +``` -<p>Dans les navigateurs modernes plus récents, la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally"><code>.finally()</code></a> est disponible, et peut être enchaînée à la fin de votre chaîne de promesses régulière, ce qui vous permet de réduire les répétitions de code et de faire les choses de manière plus élégante. Le code ci-dessus peut maintenant être écrit comme suit :</p> +Dans les navigateurs modernes plus récents, la méthode [`.finally()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally) est disponible, et peut être enchaînée à la fin de votre chaîne de promesses régulière, ce qui vous permet de réduire les répétitions de code et de faire les choses de manière plus élégante. Le code ci-dessus peut maintenant être écrit comme suit : -<pre class="brush: js">myPromise -.then(response => { +```js +myPromise +.then(response => { doSomething(response); }) -.catch(e => { +.catch(e => { returnError(e); }) -.finally(() => { +.finally(() => { runFinalCode(); -});</pre> +}); +``` -<p>Pour un exemple réel, jetez un œil à notre <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-finally.html">démonstration promesse-finally.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-finally.html">code source</a>). Cela fonctionne de la même manière que la démo <code>Promesse.all()</code> que nous avons examinée dans la section ci-dessus, sauf que dans la fonction <code>fetchAndDecode()</code>, nous enchaînons un appel <code>finally()</code> à la fin de la chaîne :</p> +Pour un exemple réel, jetez un œil à notre [démonstration promesse-finally.html](https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-finally.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-finally.html)). Cela fonctionne de la même manière que la démo `Promesse.all()` que nous avons examinée dans la section ci-dessus, sauf que dans la fonction `fetchAndDecode()`, nous enchaînons un appel `finally()` à la fin de la chaîne : -<pre class="brush: js">function fetchAndDecode(url, type) { - return fetch(url).then(response => { +```js +function fetchAndDecode(url, type) { + return fetch(url).then(response => { if(!response.ok) { throw new Error(`Erreur HTTP ! statut : ${response.status}`); } else { @@ -437,140 +453,139 @@ document.body.appendChild(para);</pre> } } }) - .catch(e => { + .catch(e => { console.log(`Il y a eu un problème avec votre opération de récupération de la ressource "${url}" : ` + e.message); }) - .finally(() => { + .finally(() => { console.log(`La tentative de récupération de "${url}" est terminée.`); }); -}</pre> +} +``` -<p>Cela permet d'envoyer un simple message à la console pour nous dire quand chaque tentative de récupération est terminée.</p> +Cela permet d'envoyer un simple message à la console pour nous dire quand chaque tentative de récupération est terminée. -<div class="note"> - <p><strong>Note :</strong> <code>then()</code>/<code>catch()</code>/<code>finally()</code> est l'équivalent asynchrone de <code>try</code>/<code>catch</code>/<code>finally</code> en code synchrone.</p> -</div> +> **Note :** `then()`/`catch()`/`finally()` est l'équivalent asynchrone de `try`/`catch`/`finally` en code synchrone. -<h2 id="building_your_own_custom_promises">Construire vos propres promesses personnalisées</h2> +## Construire vos propres promesses personnalisées -<p>La bonne nouvelle est que, d'une certaine manière, vous avez déjà construit vos propres promesses. Lorsque vous avez enchaîné plusieurs promesses avec des blocs <code>.then()</code>, ou que vous les avez autrement combinées pour créer une fonctionnalité personnalisée, vous créez déjà vos propres fonctions asynchrones personnalisées basées sur des promesses. Prenez notre fonction <code>fetchAndDecode()</code> des exemples précédents, par exemple.</p> +La bonne nouvelle est que, d'une certaine manière, vous avez déjà construit vos propres promesses. Lorsque vous avez enchaîné plusieurs promesses avec des blocs `.then()`, ou que vous les avez autrement combinées pour créer une fonctionnalité personnalisée, vous créez déjà vos propres fonctions asynchrones personnalisées basées sur des promesses. Prenez notre fonction `fetchAndDecode()` des exemples précédents, par exemple. -<p>La combinaison de différentes API basées sur les promesses pour créer des fonctionnalités personnalisées est de loin la façon la plus courante dont vous ferez des choses personnalisées avec les promesses, et montre la flexibilité et la puissance de la base de la plupart des API modernes autour du même principe. Il existe toutefois un autre moyen.</p> +La combinaison de différentes API basées sur les promesses pour créer des fonctionnalités personnalisées est de loin la façon la plus courante dont vous ferez des choses personnalisées avec les promesses, et montre la flexibilité et la puissance de la base de la plupart des API modernes autour du même principe. Il existe toutefois un autre moyen. -<h3 id="using_the_promise_constructor">Utilisation du constructeur Promise()</h3> +### Utilisation du constructeur Promise() -<p>Il est possible de construire vos propres promesses en utilisant le constructeur <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Promise()</code></a>. La principale situation dans laquelle vous voudrez faire cela est lorsque vous avez du code basé sur une API asynchrone de la vieille école qui n'est pas basée sur les promesses, et que vous voulez promettre. Cela s'avère pratique lorsque vous avez besoin d'utiliser du code, des bibliothèques ou des frameworks existants, plus anciens, avec du code moderne basé sur les promesses.</p> +Il est possible de construire vos propres promesses en utilisant le constructeur [`Promise()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise). La principale situation dans laquelle vous voudrez faire cela est lorsque vous avez du code basé sur une API asynchrone de la vieille école qui n'est pas basée sur les promesses, et que vous voulez promettre. Cela s'avère pratique lorsque vous avez besoin d'utiliser du code, des bibliothèques ou des frameworks existants, plus anciens, avec du code moderne basé sur les promesses. -<p>Examinons un exemple simple pour vous aider à démarrer — ici, nous enveloppons un appel <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout"><code>setTimeout()</code></a> avec une promesse — cela exécute une fonction après deux secondes qui résout la promesse (en passant l'appel <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve"><code>resolve()</code></a>) avec une chaîne de caractères de "Succès ! ".</p> +Examinons un exemple simple pour vous aider à démarrer — ici, nous enveloppons un appel [`setTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) avec une promesse — cela exécute une fonction après deux secondes qui résout la promesse (en passant l'appel [`resolve()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve)) avec une chaîne de caractères de "Succès ! ". -<pre class="brush: js">let timeoutPromise = new Promise((resolve, reject) => { - setTimeout(() => { +```js +let timeoutPromise = new Promise((resolve, reject) => { + setTimeout(() => { resolve('Succès !'); }, 2000); -});</pre> +}); +``` -<p><code>resolve()</code> et <code>reject()</code> sont des fonctions que vous appelez pour réaliser ou rejeter la promesse nouvellement créée. Dans ce cas, la promesse se réalise avec une chaîne de caractères "Succès !".</p> +`resolve()` et `reject()` sont des fonctions que vous appelez pour réaliser ou rejeter la promesse nouvellement créée. Dans ce cas, la promesse se réalise avec une chaîne de caractères "Succès !". -<p>Ainsi, lorsque vous appelez cette promesse, vous pouvez enchaîner un bloc <code>.then()</code> à la fin de celle-ci et on lui passera une chaîne de caractères "Succès !". Dans le code ci-dessous, nous alertons ce message :</p> +Ainsi, lorsque vous appelez cette promesse, vous pouvez enchaîner un bloc `.then()` à la fin de celle-ci et on lui passera une chaîne de caractères "Succès !". Dans le code ci-dessous, nous alertons ce message : -<pre class="brush: js">timeoutPromise -.then((message) => { +```js +timeoutPromise +.then((message) => { alert(message); -})</pre> +}) +``` -<p>ou même simplement</p> +ou même simplement -<pre class="brush: js">timeoutPromise.then(alert);</pre> +```js +timeoutPromise.then(alert); +``` -<p>Essayez <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise.html">de l'exécuter en direct</a> pour voir le résultat (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html">code source</a>).</p> +Essayez [de l'exécuter en direct](https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise.html) pour voir le résultat (voir aussi le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html)). -<p>L'exemple ci-dessus n'est pas très flexible - la promesse ne peut jamais s'accomplir qu'avec une seule chaîne de caractères, et elle n'a aucune sorte de condition <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject"><code>reject()</code></a> spécifiée (il est vrai que <code>setTimeout()</code> n'a pas vraiment de condition d'échec, donc cela n'a pas d'importance pour cet exemple).</p> +L'exemple ci-dessus n'est pas très flexible - la promesse ne peut jamais s'accomplir qu'avec une seule chaîne de caractères, et elle n'a aucune sorte de condition [`reject()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject) spécifiée (il est vrai que `setTimeout()` n'a pas vraiment de condition d'échec, donc cela n'a pas d'importance pour cet exemple). -<div class="note"> - <p><strong>Note :</strong> Pourquoi <code>resolve()</code>, et pas <code>fulfill()</code> ? La réponse que nous vous donnerons, pour l'instant, est <em>c'est compliqué</em>.</p> -</div> +> **Note :** Pourquoi `resolve()`, et pas `fulfill()` ? La réponse que nous vous donnerons, pour l'instant, est _c'est compliqué_. -<h3 id="rejecting_a_custom_promise">Rejeter une promesse personnalisée</h3> +### Rejeter une promesse personnalisée -<p>Nous pouvons créer une promesse rejetée à l'aide de la méthode <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject"><code>reject()</code></a> — tout comme <code>resolve()</code>, celle-ci prend une seule valeur, mais dans ce cas, c'est la raison du rejet, c'est-à-dire l'erreur qui sera transmise dans le bloc <code>.catch()</code>.</p> +Nous pouvons créer une promesse rejetée à l'aide de la méthode [`reject()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject) — tout comme `resolve()`, celle-ci prend une seule valeur, mais dans ce cas, c'est la raison du rejet, c'est-à-dire l'erreur qui sera transmise dans le bloc `.catch()`. -<p>Étendons l'exemple précédent pour avoir quelques conditions <code>reject()</code> ainsi que pour permettre de transmettre différents messages en cas de succès.</p> +Étendons l'exemple précédent pour avoir quelques conditions `reject()` ainsi que pour permettre de transmettre différents messages en cas de succès. -<p>Prenez une copie de l'<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html">exemple précédent</a>, et remplacez la définition de <code>timeoutPromise()</code> existante par celle-ci :</p> +Prenez une copie de l'[exemple précédent](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html), et remplacez la définition de `timeoutPromise()` existante par celle-ci : -<pre class="brush: js">function timeoutPromise(message, interval) { - return new Promise((resolve, reject) => { +```js +function timeoutPromise(message, interval) { + return new Promise((resolve, reject) => { if (message === '' || typeof message !== 'string') { reject('Le message est vide ou n'est pas une chaîne de caractères'); - } else if (interval < 0 || typeof interval !== 'number') { + } else if (interval < 0 || typeof interval !== 'number') { reject(`L'intervalle est négatif ou n'est pas un nombre`); } else { - setTimeout(() => { + setTimeout(() => { resolve(message); }, interval); } }); -};</pre> +}; +``` -<p>Ici, nous passons deux arguments dans une fonction personnalisée - un message pour faire quelque chose avec, et l'intervalle de temps à passer avant de faire la chose. À l'intérieur de la fonction, nous renvoyons un nouvel objet <code>Promise</code> — l'invocation de la fonction renverra la promesse que nous voulons utiliser.</p> +Ici, nous passons deux arguments dans une fonction personnalisée - un message pour faire quelque chose avec, et l'intervalle de temps à passer avant de faire la chose. À l'intérieur de la fonction, nous renvoyons un nouvel objet `Promise` — l'invocation de la fonction renverra la promesse que nous voulons utiliser. -<p>À l'intérieur du constructeur Promise, nous effectuons plusieurs vérifications dans des structures <code>if ... else</code> :</p> +À l'intérieur du constructeur Promise, nous effectuons plusieurs vérifications dans des structures `if ... else` : -<ol> - <li>Tout d'abord, nous vérifions si le message est approprié pour être alerté. Si c'est une chaîne de caractères vide ou pas une chaîne de caractères du tout, nous rejetons la promesse avec un message d'erreur approprié.</li> - <li>Ensuite, nous vérifions si l'intervalle est une valeur d'intervalle appropriée. S'il est négatif ou n'est pas un nombre, nous rejetons la promesse avec un message d'erreur approprié.</li> - <li>Enfin, si les paramètres semblent tous deux OK, nous résolvons la promesse avec le message spécifié après que l'intervalle spécifié se soit écoulé en utilisant <code>setTimeout()</code>.</li> -</ol> +1. Tout d'abord, nous vérifions si le message est approprié pour être alerté. Si c'est une chaîne de caractères vide ou pas une chaîne de caractères du tout, nous rejetons la promesse avec un message d'erreur approprié. +2. Ensuite, nous vérifions si l'intervalle est une valeur d'intervalle appropriée. S'il est négatif ou n'est pas un nombre, nous rejetons la promesse avec un message d'erreur approprié. +3. Enfin, si les paramètres semblent tous deux OK, nous résolvons la promesse avec le message spécifié après que l'intervalle spécifié se soit écoulé en utilisant `setTimeout()`. -<p>Puisque la fonction <code>timeoutPromise()</code> renvoie un objet <code>Promise</code>, nous pouvons enchaîner <code>.then()</code>, <code>.catch()</code>, etc. sur elle pour faire usage de ses fonctionnalités. Utilisons-le maintenant - remplaçons l'utilisation précédente de <code>timeoutPromise</code> par celle-ci :</p> +Puisque la fonction `timeoutPromise()` renvoie un objet `Promise`, nous pouvons enchaîner `.then()`, `.catch()`, etc. sur elle pour faire usage de ses fonctionnalités. Utilisons-le maintenant - remplaçons l'utilisation précédente de `timeoutPromise` par celle-ci : -<pre class="brush: js">timeoutPromise('Bonjour à tous !', 1000) -.then(message => { +```js +timeoutPromise('Bonjour à tous !', 1000) +.then(message => { alert(message); }) -.catch(e => { +.catch(e => { console.log('Erreur : ' + e); -});</pre> +}); +``` -<p>Lorsque vous enregistrez et exécutez le code tel quel, après une seconde, vous obtiendrez le message d'alerte. Essayez maintenant de définir le message sur une chaîne vide ou l'intervalle sur un nombre négatif, par exemple, et vous pourrez voir la promesse rejetée avec les messages d'erreur appropriés ! Vous pouvez également essayer de faire autre chose avec le message résolu plutôt que de simplement créer une alerte.</p> +Lorsque vous enregistrez et exécutez le code tel quel, après une seconde, vous obtiendrez le message d'alerte. Essayez maintenant de définir le message sur une chaîne vide ou l'intervalle sur un nombre négatif, par exemple, et vous pourrez voir la promesse rejetée avec les messages d'erreur appropriés ! Vous pouvez également essayer de faire autre chose avec le message résolu plutôt que de simplement créer une alerte. -<div class="note"> - <p><strong>Note :</strong> Vous pouvez trouver notre version de cet exemple sur GitHub sur <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise2.html">custom-promise2.html</a> (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise2.html">code source</a>).</p> -</div> +> **Note :** Vous pouvez trouver notre version de cet exemple sur GitHub sur [custom-promise2.html](https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise2.html) (voir aussi le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise2.html)). -<h3 id="a_more_real-world_example">Un exemple plus concret</h3> +### Un exemple plus concret -<p>L'exemple ci-dessus est resté volontairement simple pour rendre les concepts faciles à comprendre, mais il n'est pas vraiment très asynchrone. La nature asynchrone est essentiellement feinte en utilisant <code>setTimeout()</code>, bien qu'il montre quand même que les promesses sont utiles pour créer une fonction personnalisée avec un flux d'opérations raisonnable, une bonne gestion des erreurs, etc.</p> +L'exemple ci-dessus est resté volontairement simple pour rendre les concepts faciles à comprendre, mais il n'est pas vraiment très asynchrone. La nature asynchrone est essentiellement feinte en utilisant `setTimeout()`, bien qu'il montre quand même que les promesses sont utiles pour créer une fonction personnalisée avec un flux d'opérations raisonnable, une bonne gestion des erreurs, etc. -<p>Un exemple que nous aimerions vous inviter à étudier, qui montre effectivement une application asynchrone utile du constructeur <code>Promise()</code>, est <a href="https://github.com/jakearchibald/idb/">la bibliothèque idb de Jake Archibald</a>. Celle-ci prend l'API <a href="/fr/docs/Web/API/IndexedDB_API">IndexedDB API</a>, qui est une API à l'ancienne basée sur des callbacks pour stocker et récupérer des données côté client, et vous permet de l'utiliser avec des promesses. Dans le code, vous verrez que le même type de techniques que nous avons évoqué plus haut est utilisé. Le bloc suivant convertit le modèle de requête de base utilisé par de nombreuses méthodes IndexedDB pour utiliser des promesses (<a href="https://github.com/jakearchibald/idb/blob/01082ad696eef05e9c913f55a17cda7b3016b12c/build/esm/wrap-idb-value.js#L30">voir ce code, par exemple</a>).</p> +Un exemple que nous aimerions vous inviter à étudier, qui montre effectivement une application asynchrone utile du constructeur `Promise()`, est [la bibliothèque idb de Jake Archibald](https://github.com/jakearchibald/idb/). Celle-ci prend l'API [IndexedDB API](/fr/docs/Web/API/IndexedDB_API), qui est une API à l'ancienne basée sur des callbacks pour stocker et récupérer des données côté client, et vous permet de l'utiliser avec des promesses. Dans le code, vous verrez que le même type de techniques que nous avons évoqué plus haut est utilisé. Le bloc suivant convertit le modèle de requête de base utilisé par de nombreuses méthodes IndexedDB pour utiliser des promesses ([voir ce code, par exemple](https://github.com/jakearchibald/idb/blob/01082ad696eef05e9c913f55a17cda7b3016b12c/build/esm/wrap-idb-value.js#L30)). -<h2 id="conclusion">Conclusion</h2> +## Conclusion -<p>Les promesses sont un bon moyen de construire des applications asynchrones lorsque nous ne connaissons pas la valeur de retour d'une fonction ou le temps qu'elle prendra pour retourner une réponse. Elles permettent d'exprimer et de raisonner plus facilement sur des séquences d'opérations asynchrones sans callbacks profondément imbriqués, et elles supportent un style de gestion des erreurs qui est similaire à l'instruction synchrone <code>try...catch</code>.</p> +Les promesses sont un bon moyen de construire des applications asynchrones lorsque nous ne connaissons pas la valeur de retour d'une fonction ou le temps qu'elle prendra pour retourner une réponse. Elles permettent d'exprimer et de raisonner plus facilement sur des séquences d'opérations asynchrones sans callbacks profondément imbriqués, et elles supportent un style de gestion des erreurs qui est similaire à l'instruction synchrone `try...catch`. -<p>Les promesses fonctionnent dans les dernières versions de tous les navigateurs modernes ; le seul endroit où la prise en charge des promesses posera problème est Opera Mini et IE11 et les versions antérieures.</p> +Les promesses fonctionnent dans les dernières versions de tous les navigateurs modernes ; le seul endroit où la prise en charge des promesses posera problème est Opera Mini et IE11 et les versions antérieures. -<p>Nous n'avons pas abordé toutes les fonctionnalités des promesses dans cet article, mais seulement les plus intéressantes et les plus utiles. Au fur et à mesure que vous vous familiariserez avec les promesses, vous découvrirez d'autres fonctionnalités et techniques.</p> +Nous n'avons pas abordé toutes les fonctionnalités des promesses dans cet article, mais seulement les plus intéressantes et les plus utiles. Au fur et à mesure que vous vous familiariserez avec les promesses, vous découvrirez d'autres fonctionnalités et techniques. -<p>La plupart des API Web modernes sont basées sur des promesses, vous devrez donc comprendre les promesses pour en tirer le meilleur parti. Parmi ces API, citons <a href="/fr/docs/Web/API/WebRTC_API">WebRTC</a>, <a href="/fr/docs/Web/API/Web_Audio_API">Web Audio API</a>, <a href="/fr/docs/Web/API/Media_Streams_API">MediaStream API</a>, et bien d'autres encore. Les promesses seront de plus en plus importantes au fil du temps, donc apprendre à les utiliser et à les comprendre est une étape importante dans l'apprentissage du JavaScript moderne.</p> +La plupart des API Web modernes sont basées sur des promesses, vous devrez donc comprendre les promesses pour en tirer le meilleur parti. Parmi ces API, citons [WebRTC](/fr/docs/Web/API/WebRTC_API), [Web Audio API](/fr/docs/Web/API/Web_Audio_API), [MediaStream API](/fr/docs/Web/API/Media_Streams_API), et bien d'autres encore. Les promesses seront de plus en plus importantes au fil du temps, donc apprendre à les utiliser et à les comprendre est une étape importante dans l'apprentissage du JavaScript moderne. -<h2 id="see_also">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Promise()</code></a></li> - <li><a href="/fr/docs/Web/JavaScript/Guide/Using_promises">Utilisation des promesses</a></li> - <li><a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">Nous avons un problème avec les promesses</a> <small>(en)</small> par Nolan Lawson</li> -</ul> +- [`Promise()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Promise) +- [Utilisation des promesses](/fr/docs/Web/JavaScript/Guide/Using_promises) +- [Nous avons un problème avec les promesses](https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html) (en) par Nolan Lawson -<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}} -<h2 id="in_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li> -</ul> +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Faciliter la programmation asynchrone avec async et await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) diff --git a/files/fr/learn/javascript/asynchronous/timeouts_and_intervals/index.md b/files/fr/learn/javascript/asynchronous/timeouts_and_intervals/index.md index e2f90a12fb..c179da9e18 100644 --- a/files/fr/learn/javascript/asynchronous/timeouts_and_intervals/index.md +++ b/files/fr/learn/javascript/asynchronous/timeouts_and_intervals/index.md @@ -16,70 +16,71 @@ tags: - timeouts translation_of: Learn/JavaScript/Asynchronous/Timeouts_and_intervals --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</div> - -<p>Ce tutoriel présente les méthodes traditionnelles dont dispose JavaScript pour exécuter du code de manière asynchrone après l'écoulement d'une période de temps déterminée ou à un intervalle régulier (par exemple, un nombre déterminé de fois par seconde), discute de leur utilité et examine leurs problèmes inhérents.</p> +Ce tutoriel présente les méthodes traditionnelles dont dispose JavaScript pour exécuter du code de manière asynchrone après l'écoulement d'une période de temps déterminée ou à un intervalle régulier (par exemple, un nombre déterminé de fois par seconde), discute de leur utilité et examine leurs problèmes inhérents. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, compréhension raisonnable des principes fondamentaux de JavaScript.</td> + <td> + Connaissances informatiques de base, compréhension raisonnable des + principes fondamentaux de JavaScript. + </td> </tr> <tr> <th scope="row">Objectif :</th> - <td>Comprendre les boucles et les intervalles asynchrones et leur utilité.</td> + <td> + Comprendre les boucles et les intervalles asynchrones et leur utilité. + </td> </tr> </tbody> </table> -<h2 id="introduction">Introduction</h2> +## Introduction -<p>Depuis longtemps, la plate-forme Web offre aux programmeurs JavaScript un certain nombre de fonctions qui leur permettent d'exécuter du code de manière asynchrone après un certain intervalle de temps, et d'exécuter un bloc de code de manière asynchrone jusqu'à ce que vous lui demandiez de s'arrêter.</p> +Depuis longtemps, la plate-forme Web offre aux programmeurs JavaScript un certain nombre de fonctions qui leur permettent d'exécuter du code de manière asynchrone après un certain intervalle de temps, et d'exécuter un bloc de code de manière asynchrone jusqu'à ce que vous lui demandiez de s'arrêter. -<p>Ces fonctions sont :</p> +Ces fonctions sont : -<dl> - <dt><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout"><code>setTimeout()</code></a></dt> - <dd>Exécuter un bloc de code spécifié une fois, après qu'un temps spécifié se soit écoulé.</dd> - <dt><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval"><code>setInterval()</code></a></dt> - <dd>Exécuter un bloc de code spécifique de manière répétée, avec un délai fixe entre chaque appel.</dd> - <dt><a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</a></code></dt> - <dd>La version moderne de <code>setInterval()</code>. Exécute un bloc de code spécifié avant que le navigateur ne repeigne ensuite l'affichage, ce qui permet à une animation d'être exécutée à une fréquence d'images appropriée, quel que soit l'environnement dans lequel elle est exécutée.</dd> -</dl> +- [`setTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) + - : Exécuter un bloc de code spécifié une fois, après qu'un temps spécifié se soit écoulé. +- [`setInterval()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval) + - : Exécuter un bloc de code spécifique de manière répétée, avec un délai fixe entre chaque appel. +- [`requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame) + - : La version moderne de `setInterval()`. Exécute un bloc de code spécifié avant que le navigateur ne repeigne ensuite l'affichage, ce qui permet à une animation d'être exécutée à une fréquence d'images appropriée, quel que soit l'environnement dans lequel elle est exécutée. -<p>Le code asynchrone mis en place par ces fonctions s'exécute sur le processus principal (après l'écoulement de leur minuterie spécifiée).</p> +Le code asynchrone mis en place par ces fonctions s'exécute sur le processus principal (après l'écoulement de leur minuterie spécifiée). -<p>Il est important de savoir que vous pouvez (et allez souvent) exécuter un autre code avant qu'un appel <code>setTimeout()</code> ne s'exécute, ou entre les itérations de <code>setInterval()</code>. Selon l'intensité du processeur de ces opérations, elles peuvent retarder encore plus votre code asynchrone, car tout code asynchrone ne s'exécutera qu'<em>après</em> la disponibilité du processus principal. (En d'autres termes, lorsque la pile est vide.) Vous en apprendrez davantage à ce sujet au fur et à mesure que vous progresserez dans cet article.</p> +Il est important de savoir que vous pouvez (et allez souvent) exécuter un autre code avant qu'un appel `setTimeout()` ne s'exécute, ou entre les itérations de `setInterval()`. Selon l'intensité du processeur de ces opérations, elles peuvent retarder encore plus votre code asynchrone, car tout code asynchrone ne s'exécutera qu'_après_ la disponibilité du processus principal. (En d'autres termes, lorsque la pile est vide.) Vous en apprendrez davantage à ce sujet au fur et à mesure que vous progresserez dans cet article. -<p>Dans tous les cas, ces fonctions sont utilisées pour exécuter des animations constantes et d'autres traitements en arrière-plan sur un site Web ou une application. Dans les sections suivantes, nous allons vous montrer comment les utiliser.</p> +Dans tous les cas, ces fonctions sont utilisées pour exécuter des animations constantes et d'autres traitements en arrière-plan sur un site Web ou une application. Dans les sections suivantes, nous allons vous montrer comment les utiliser. -<h2 id="settimeout">setTimeout()</h2> +## setTimeout() -<p>Comme nous l'avons dit précédemment, <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout"><code>setTimeout()</code></a> exécute un bloc de code particulier une fois qu'un temps spécifié s'est écoulé. Il prend les paramètres suivants :</p> +Comme nous l'avons dit précédemment, [`setTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) exécute un bloc de code particulier une fois qu'un temps spécifié s'est écoulé. Il prend les paramètres suivants : -<ul> - <li>Une fonction à exécuter, ou une référence à une fonction définie ailleurs.</li> - <li>Un nombre représentant l'intervalle de temps en millisecondes (1000 millisecondes équivalent à 1 seconde) à attendre avant d'exécuter le code. Si vous spécifiez une valeur de <code>0</code> (ou omettez la valeur), la fonction sera exécutée dès que possible. (Voir la note ci-dessous sur la raison pour laquelle elle s'exécute "dès que possible" et non "immédiatement"). Plus d'informations sur les raisons pour lesquelles vous pourriez vouloir faire cela plus tard.</li> - <li>Zéro ou plusieurs valeurs représentant les paramètres que vous souhaitez transmettre à la fonction lors de son exécution.</li> -</ul> +- Une fonction à exécuter, ou une référence à une fonction définie ailleurs. +- Un nombre représentant l'intervalle de temps en millisecondes (1000 millisecondes équivalent à 1 seconde) à attendre avant d'exécuter le code. Si vous spécifiez une valeur de `0` (ou omettez la valeur), la fonction sera exécutée dès que possible. (Voir la note ci-dessous sur la raison pour laquelle elle s'exécute "dès que possible" et non "immédiatement"). Plus d'informations sur les raisons pour lesquelles vous pourriez vouloir faire cela plus tard. +- Zéro ou plusieurs valeurs représentant les paramètres que vous souhaitez transmettre à la fonction lors de son exécution. -<div class="note"> - <p><strong>Note :</strong> La quantité de temps spécifiée (ou le délai) n'est <strong>pas</strong> le <em>temps garanti</em> à l'exécution, mais plutôt le <em>temps minimum</em> à l'exécution. Les rappels que vous passez à ces fonctions ne peuvent pas s'exécuter tant que la pile du processus principal n'est pas vide.</p> - <p>En conséquence, un code comme <code>setTimeout(fn, 0)</code> s'exécutera dès que la pile sera vide, <strong>pas</strong> immédiatement. Si vous exécutez un code comme <code>setTimeout(fn, 0)</code> mais qu'immédiatement après vous exécutez une boucle qui compte de 1 à 10 milliards, votre rappel sera exécuté après quelques secondes.</p> -</div> +> **Note :** La quantité de temps spécifiée (ou le délai) n'est **pas** le _temps garanti_ à l'exécution, mais plutôt le _temps minimum_ à l'exécution. Les rappels que vous passez à ces fonctions ne peuvent pas s'exécuter tant que la pile du processus principal n'est pas vide. +> +> En conséquence, un code comme `setTimeout(fn, 0)` s'exécutera dès que la pile sera vide, **pas** immédiatement. Si vous exécutez un code comme `setTimeout(fn, 0)` mais qu'immédiatement après vous exécutez une boucle qui compte de 1 à 10 milliards, votre rappel sera exécuté après quelques secondes. -<p>Dans l'exemple suivant, le navigateur attendra deux secondes avant d'exécuter la fonction anonyme, puis affichera le message d'alerte (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">voir son exécution en direct</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">voir le code source</a>) :</p> +Dans l'exemple suivant, le navigateur attendra deux secondes avant d'exécuter la fonction anonyme, puis affichera le message d'alerte ([voir son exécution en direct](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html), et [voir le code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html)) : -<pre class="brush: js">let maSalutation = setTimeout(() => { +```js +let maSalutation = setTimeout(() => { console.log('Bonjour, M. Univers !'); -}, 2000);</pre> +}, 2000); +``` -<p>Les fonctions que vous spécifiez n'ont pas besoin d'être anonymes. Vous pouvez donner un nom à votre fonction, et même la définir ailleurs et passer une référence de fonction à <code>setTimeout()</code>. Les deux versions suivantes de l'extrait de code sont équivalentes à la première :</p> +Les fonctions que vous spécifiez n'ont pas besoin d'être anonymes. Vous pouvez donner un nom à votre fonction, et même la définir ailleurs et passer une référence de fonction à `setTimeout()`. Les deux versions suivantes de l'extrait de code sont équivalentes à la première : -<pre class="brush: js">// Avec une fonction nommée +```js +// Avec une fonction nommée let maSalutation = setTimeout(function direBonjour() { console.log('Bonjour, M. Univers !'); }, 2000); @@ -89,225 +90,235 @@ function direBonjour() { console.log('Bonjour, M. Univers !'); } -let maSalutation = setTimeout(direBonjour, 2000);</pre> +let maSalutation = setTimeout(direBonjour, 2000); +``` -<p>Cela peut être utile si vous avez une fonction qui doit être appelée à la fois à partir d'un délai d'attente et en réponse à un événement, par exemple. Mais cela peut aussi vous aider à garder votre code en ordre, surtout si le rappel du délai d'attente représente plus de quelques lignes de code.</p> +Cela peut être utile si vous avez une fonction qui doit être appelée à la fois à partir d'un délai d'attente et en réponse à un événement, par exemple. Mais cela peut aussi vous aider à garder votre code en ordre, surtout si le rappel du délai d'attente représente plus de quelques lignes de code. -<p><code>setTimeout()</code> renvoie une valeur d'identifiant qui peut être utilisée pour faire référence au délai d'attente ultérieurement, par exemple lorsque vous souhaitez l'arrêter. Voir <a href="#clearing_timeouts">Effacement des délais d'attente</a> (ci-dessous) pour apprendre comment faire cela.</p> +`setTimeout()` renvoie une valeur d'identifiant qui peut être utilisée pour faire référence au délai d'attente ultérieurement, par exemple lorsque vous souhaitez l'arrêter. Voir [Effacement des délais d'attente](#clearing_timeouts) (ci-dessous) pour apprendre comment faire cela. -<h3 id="passing_parameters_to_a_settimeout_function">Passage de paramètres à une fonction setTimeout()</h3> +### Passage de paramètres à une fonction setTimeout() -<p>Tous les paramètres que vous voulez passer à la fonction en cours d'exécution à l'intérieur du <code>setTimeout()</code> doivent lui être passés comme paramètres supplémentaires à la fin de la liste.</p> +Tous les paramètres que vous voulez passer à la fonction en cours d'exécution à l'intérieur du `setTimeout()` doivent lui être passés comme paramètres supplémentaires à la fin de la liste. -<p>Par exemple, vous pouvez remanier la fonction précédente pour qu'elle dise bonjour à la personne dont le nom lui est transmis :</p> +Par exemple, vous pouvez remanier la fonction précédente pour qu'elle dise bonjour à la personne dont le nom lui est transmis : -<pre class="brush: js">function direBonjour(who) { +```js +function direBonjour(who) { console.log(`Bonjour ${who} !`); -}</pre> +} +``` -<p>Maintenant, vous pouvez passer le nom de la personne dans l'appel <code>setTimeout()</code> comme troisième paramètre :</p> +Maintenant, vous pouvez passer le nom de la personne dans l'appel `setTimeout()` comme troisième paramètre : -<pre class="brush: js">let maSalutation = setTimeout(direBonjour, 2000, 'M. Univers');</pre> +```js +let maSalutation = setTimeout(direBonjour, 2000, 'M. Univers'); +``` -<h3 id="clearing_timeouts">Effacement des délais d'attente</h3> +### Effacement des délais d'attente -<p>Enfin, si un timeout a été créé, vous pouvez l'annuler avant que le temps spécifié ne se soit écoulé en appelant <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout"><code>clearTimeout()</code></a>, en lui passant en paramètre l'identifiant de l'appel <code>setTimeout()</code>. Donc pour annuler notre timeout ci-dessus, vous feriez ceci :</p> +Enfin, si un timeout a été créé, vous pouvez l'annuler avant que le temps spécifié ne se soit écoulé en appelant [`clearTimeout()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout), en lui passant en paramètre l'identifiant de l'appel `setTimeout()`. Donc pour annuler notre timeout ci-dessus, vous feriez ceci : -<pre class="brush: js">clearTimeout(maSalutation);</pre> +```js +clearTimeout(maSalutation); +``` -<div class="note"> - <p><strong>Note :</strong> Voir <code><a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/greeter-app.html">greeter-app.html</a></code> pour une démo un peu plus élaborée qui permet de définir le nom de la personne à saluer dans un formulaire, et d'annuler la salutation à l'aide d'un bouton séparé (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/greeter-app.html">voir aussi le code source</a>).</p> -</div> +> **Note :** Voir [`greeter-app.html`](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/greeter-app.html) pour une démo un peu plus élaborée qui permet de définir le nom de la personne à saluer dans un formulaire, et d'annuler la salutation à l'aide d'un bouton séparé ([voir aussi le code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/greeter-app.html)). -<h2 id="setinterval">setInterval()</h2> +## setInterval() -<p><code>setTimeout()</code> fonctionne parfaitement lorsque vous devez exécuter du code une fois après une période de temps définie. Mais que se passe-t-il lorsque vous avez besoin d'exécuter le code encore et encore - par exemple, dans le cas d'une animation ?</p> +`setTimeout()` fonctionne parfaitement lorsque vous devez exécuter du code une fois après une période de temps définie. Mais que se passe-t-il lorsque vous avez besoin d'exécuter le code encore et encore - par exemple, dans le cas d'une animation ? -<p>C'est là qu'intervient le <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval"><code>setInterval()</code></a>. Cela fonctionne de manière très similaire à <code>setTimeout()</code>, sauf que la fonction que vous passez comme premier paramètre est exécutée de manière répétée à une fréquence égale au nombre de millisecondes donné par le deuxième paramètre distinct, plutôt qu'une seule fois. Vous pouvez également passer tous les paramètres requis par la fonction en cours d'exécution comme paramètres ultérieurs de l'appel <code>setInterval()</code>.</p> +C'est là qu'intervient le [`setInterval()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/setInterval). Cela fonctionne de manière très similaire à `setTimeout()`, sauf que la fonction que vous passez comme premier paramètre est exécutée de manière répétée à une fréquence égale au nombre de millisecondes donné par le deuxième paramètre distinct, plutôt qu'une seule fois. Vous pouvez également passer tous les paramètres requis par la fonction en cours d'exécution comme paramètres ultérieurs de l'appel `setInterval()`. -<p>Prenons un exemple. La fonction suivante crée un nouvel objet <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date"><code>Date()</code></a>, en extrait une chaîne de temps en utilisant <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString"><code>toLocaleTimeString()</code></a>, puis l'affiche dans l'interface utilisateur. Elle exécute ensuite la fonction une fois par seconde à l'aide de <code>setInterval()</code>, créant l'effet d'une horloge numérique qui se met à jour une fois par seconde (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">voir cela en direct</a>, et aussi <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">voir la source</a>) :</p> +Prenons un exemple. La fonction suivante crée un nouvel objet [`Date()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Date), en extrait une chaîne de temps en utilisant [`toLocaleTimeString()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString), puis l'affiche dans l'interface utilisateur. Elle exécute ensuite la fonction une fois par seconde à l'aide de `setInterval()`, créant l'effet d'une horloge numérique qui se met à jour une fois par seconde ([voir cela en direct](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html), et aussi [voir la source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html)) : -<pre class="brush: js">function displayTime() { +```js +function displayTime() { let date = new Date(); let time = date.toLocaleTimeString(); document.getElementById('demo').textContent = time; } -const createClock = setInterval(displayTime, 1000);</pre> +const createClock = setInterval(displayTime, 1000); +``` + +Tout comme `setTimeout()`, `setInterval()` renvoie une valeur d'identification que vous pouvez utiliser plus tard lorsque vous devez effacer l'intervalle. -<p>Tout comme <code>setTimeout()</code>, <code>setInterval()</code> renvoie une valeur d'identification que vous pouvez utiliser plus tard lorsque vous devez effacer l'intervalle.</p> +### Effacement des intervalles -<h3 id="clearing_intervals">Effacement des intervalles</h3> +`setInterval()` continue à exécuter une tâche pour toujours, à moins que vous ne fassiez quelque chose à ce sujet. Vous voudrez probablement un moyen d'arrêter de telles tâches, sinon vous pouvez finir par obtenir des erreurs lorsque le navigateur ne peut pas compléter d'autres versions de la tâche, ou si l'animation gérée par la tâche est terminée. Vous pouvez le faire de la même manière que vous arrêtez les temporisations - en passant l'identifiant renvoyé par l'appel `setInterval()` à la fonction [`clearInterval()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval) : -<p><code>setInterval()</code> continue à exécuter une tâche pour toujours, à moins que vous ne fassiez quelque chose à ce sujet. Vous voudrez probablement un moyen d'arrêter de telles tâches, sinon vous pouvez finir par obtenir des erreurs lorsque le navigateur ne peut pas compléter d'autres versions de la tâche, ou si l'animation gérée par la tâche est terminée. Vous pouvez le faire de la même manière que vous arrêtez les temporisations - en passant l'identifiant renvoyé par l'appel <code>setInterval()</code> à la fonction <a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval"><code>clearInterval()</code></a> :</p> +```js +const myInterval = setInterval(myFunction, 2000); -<pre class="brush: js">const myInterval = setInterval(myFunction, 2000); +clearInterval(myInterval); +``` -clearInterval(myInterval);</pre> +#### Apprentissage actif : Créez votre propre chronomètre ! -<h4 id="Active_learning_Creating_your_own_stopwatch!">Apprentissage actif : Créez votre propre chronomètre !</h4> +Tout ceci étant dit, nous avons un défi à vous proposer. Prenez une copie de notre exemple [`setInterval-clock.html`](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html), et modifiez-le pour créer votre propre chronomètre simple. -<p>Tout ceci étant dit, nous avons un défi à vous proposer. Prenez une copie de notre exemple <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">setInterval-clock.html</a></code>, et modifiez-le pour créer votre propre chronomètre simple.</p> +Vous devez afficher une heure comme précédemment, mais dans cet exemple, vous avez besoin : -<p>Vous devez afficher une heure comme précédemment, mais dans cet exemple, vous avez besoin :</p> +- Un bouton "Start" pour lancer le chronomètre. +- Un bouton "Stop" pour le mettre en pause/arrêter. +- Un bouton "Reset" pour réinitialiser le temps à `0`. +- L'affichage du temps pour indiquer le nombre de secondes écoulées, plutôt que le temps réel. -<ul> - <li>Un bouton "Start" pour lancer le chronomètre.</li> - <li>Un bouton "Stop" pour le mettre en pause/arrêter.</li> - <li>Un bouton "Reset" pour réinitialiser le temps à <code>0</code>.</li> - <li>L'affichage du temps pour indiquer le nombre de secondes écoulées, plutôt que le temps réel.</li> -</ul> +Voici quelques conseils pour vous : -<p>Voici quelques conseils pour vous :</p> +- Vous pouvez structurer et styliser le balisage du bouton comme vous le souhaitez ; veillez simplement à utiliser du HTML sémantique, avec des crochets vous permettant de saisir les références du bouton à l'aide de JavaScript. +- Vous voulez probablement créer une variable qui commence à `0`, puis s'incrémente d'une unité toutes les secondes en utilisant une boucle constante. +- Il est plus facile de créer cet exemple sans utiliser un objet `Date()`, comme nous l'avons fait dans notre version, mais moins précis - vous ne pouvez pas garantir que le rappel se déclenchera après exactement `1000`ms. Une façon plus précise serait d'exécuter `startTime = Date.now()` pour obtenir un horodatage du moment exact où l'utilisateur a cliqué sur le bouton de démarrage, puis de faire `Date.now() - startTime` pour obtenir le nombre de millisecondes après le clic sur le bouton de démarrage. +- Vous souhaitez également calculer le nombre d'heures, de minutes et de secondes sous forme de valeurs distinctes, puis les afficher ensemble dans une chaîne de caractères après chaque itération de la boucle. À partir du deuxième compteur, vous pouvez calculer chacune de ces valeurs. +- Comment les calculeriez-vous ? Réfléchissez-y : -<ul> - <li>Vous pouvez structurer et styliser le balisage du bouton comme vous le souhaitez ; veillez simplement à utiliser du HTML sémantique, avec des crochets vous permettant de saisir les références du bouton à l'aide de JavaScript.</li> - <li>Vous voulez probablement créer une variable qui commence à <code>0</code>, puis s'incrémente d'une unité toutes les secondes en utilisant une boucle constante.</li> - <li>Il est plus facile de créer cet exemple sans utiliser un objet <code>Date()</code>, comme nous l'avons fait dans notre version, mais moins précis - vous ne pouvez pas garantir que le rappel se déclenchera après exactement <code>1000</code>ms. Une façon plus précise serait d'exécuter <code>startTime = Date.now()</code> pour obtenir un horodatage du moment exact où l'utilisateur a cliqué sur le bouton de démarrage, puis de faire <code>Date.now() - startTime</code> pour obtenir le nombre de millisecondes après le clic sur le bouton de démarrage.</li> - <li>Vous souhaitez également calculer le nombre d'heures, de minutes et de secondes sous forme de valeurs distinctes, puis les afficher ensemble dans une chaîne de caractères après chaque itération de la boucle. À partir du deuxième compteur, vous pouvez calculer chacune de ces valeurs.</li> - <li>Comment les calculeriez-vous ? Réfléchissez-y : - <ul> - <li>Le nombre de secondes dans une heure est de <code>3600</code>.</li> - <li>Le nombre de minutes sera le nombre de secondes restantes lorsque toutes les heures auront été retirées, divisé par <code>60</code>.</li> - <li>Le nombre de secondes sera le nombre de secondes restantes lorsque toutes les minutes auront été retirées.</li> - </ul> - </li> - <li>Vous devrez inclure un zéro de tête sur vos valeurs d'affichage si le montant est inférieur à <code>10</code>, afin que cela ressemble davantage à une horloge/chronomètre traditionnel.</li> - <li>Pour mettre le chronomètre en pause, il faut effacer l'intervalle. Pour le réinitialiser, vous devrez remettre le compteur à <code>0</code>, effacer l'intervalle, puis mettre immédiatement à jour l'affichage.</li> - <li>Vous devriez probablement désactiver le bouton de démarrage après l'avoir pressé une fois, et le réactiver après l'avoir arrêté/réinitialisé. Sinon, les pressions multiples sur le bouton de démarrage appliqueront plusieurs <code>setInterval()</code> à l'horloge, ce qui entraînera un comportement erroné.</li> -</ul> + - Le nombre de secondes dans une heure est de `3600`. + - Le nombre de minutes sera le nombre de secondes restantes lorsque toutes les heures auront été retirées, divisé par `60`. + - Le nombre de secondes sera le nombre de secondes restantes lorsque toutes les minutes auront été retirées. -<div class="note"> - <p><strong>Note :</strong> Si vous êtes bloqué, vous pouvez <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">trouver notre version ici</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">code source</a>).</p> -</div> +- Vous devrez inclure un zéro de tête sur vos valeurs d'affichage si le montant est inférieur à `10`, afin que cela ressemble davantage à une horloge/chronomètre traditionnel. +- Pour mettre le chronomètre en pause, il faut effacer l'intervalle. Pour le réinitialiser, vous devrez remettre le compteur à `0`, effacer l'intervalle, puis mettre immédiatement à jour l'affichage. +- Vous devriez probablement désactiver le bouton de démarrage après l'avoir pressé une fois, et le réactiver après l'avoir arrêté/réinitialisé. Sinon, les pressions multiples sur le bouton de démarrage appliqueront plusieurs `setInterval()` à l'horloge, ce qui entraînera un comportement erroné. -<h2 id="things_to_keep_in_mind_about_settimeout_and_setinterval">Choses à garder à l'esprit concernant setTimeout() et setInterval()</h2> +> **Note :** Si vous êtes bloqué, vous pouvez [trouver notre version ici](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html)). -<p>Il y a quelques éléments à garder à l'esprit lorsque vous travaillez avec <code>setTimeout()</code> et <code>setInterval()</code>. Passons-les en revue maintenant.</p> +## Choses à garder à l'esprit concernant setTimeout() et setInterval() -<h3 id="recursive_timeouts">Délais récursifs</h3> +Il y a quelques éléments à garder à l'esprit lorsque vous travaillez avec `setTimeout()` et `setInterval()`. Passons-les en revue maintenant. -<p>Il existe une autre façon d'utiliser <code>setTimeout()</code> : vous pouvez l'appeler de manière récursive pour exécuter le même code de manière répétée, au lieu d'utiliser <code>setInterval()</code>.</p> +### Délais récursifs -<p>L'exemple ci-dessous utilise un <code>setTimeout()</code> récursif pour exécuter la fonction passée toutes les <code>100</code> millisecondes :</p> +Il existe une autre façon d'utiliser `setTimeout()` : vous pouvez l'appeler de manière récursive pour exécuter le même code de manière répétée, au lieu d'utiliser `setInterval()`. -<pre class="brush: js">let i = 1; +L'exemple ci-dessous utilise un `setTimeout()` récursif pour exécuter la fonction passée toutes les `100` millisecondes : + +```js +let i = 1; setTimeout(function run() { console.log(i); i++; setTimeout(run, 100); -}, 100);</pre> +}, 100); +``` -<p>Comparez l'exemple ci-dessus à celui qui suit - celui-ci utilise <code>setInterval()</code> pour accomplir le même effet :</p> +Comparez l'exemple ci-dessus à celui qui suit - celui-ci utilise `setInterval()` pour accomplir le même effet : -<pre class="brush: js">let i = 1; +```js +let i = 1; setInterval(function run() { console.log(i); i++; -}, 100);</pre> +}, 100); +``` -<h4 id="how_do_recursive_settimeout_and_setinterval_differ">Quelle est la différence entre le <code>setTimeout()</code> récursif et le <code>setInterval()</code> ?</h4> +#### Quelle est la différence entre le `setTimeout()` récursif et le `setInterval()` ? -<p>La différence entre les deux versions du code ci-dessus est subtile.</p> +La différence entre les deux versions du code ci-dessus est subtile. -<ul> - <li>Le <code>setTimeout()</code> récursif garantit le délai indiqué entre les exécutions. L'attente de la prochaine exécution commencera uniquement après que le code ait fini de s'exécuter. Dans cet exemple, le code s'exécutera, puis attendra <code>100</code> millisecondes avant de s'exécuter à nouveau - l'intervalle sera donc le même, quelle que soit la durée d'exécution du code.</li> - <li>L'exemple utilisant <code>setInterval()</code> fait les choses un peu différemment. L'intervalle que vous avez choisi <em>inclut</em> le temps d'exécution du code que vous voulez exécuter. Disons que le code prend <code>40</code> millisecondes pour s'exécuter - l'intervalle finit alors par être seulement de <code>60</code> millisecondes.</li> - <li>Lorsque vous utilisez <code>setTimeout()</code> de manière récursive, chaque itération peut calculer un délai différent avant d'exécuter l'itération suivante. En d'autres termes, la valeur du deuxième paramètre peut spécifier un temps différent en millisecondes à attendre avant d'exécuter à nouveau le code.</li> -</ul> +- Le `setTimeout()` récursif garantit le délai indiqué entre les exécutions. L'attente de la prochaine exécution commencera uniquement après que le code ait fini de s'exécuter. Dans cet exemple, le code s'exécutera, puis attendra `100` millisecondes avant de s'exécuter à nouveau - l'intervalle sera donc le même, quelle que soit la durée d'exécution du code. +- L'exemple utilisant `setInterval()` fait les choses un peu différemment. L'intervalle que vous avez choisi _inclut_ le temps d'exécution du code que vous voulez exécuter. Disons que le code prend `40` millisecondes pour s'exécuter - l'intervalle finit alors par être seulement de `60` millisecondes. +- Lorsque vous utilisez `setTimeout()` de manière récursive, chaque itération peut calculer un délai différent avant d'exécuter l'itération suivante. En d'autres termes, la valeur du deuxième paramètre peut spécifier un temps différent en millisecondes à attendre avant d'exécuter à nouveau le code. -<p>Lorsque votre code a le potentiel de prendre plus de temps à s'exécuter que l'intervalle de temps que vous avez assigné, il est préférable d'utiliser le <code>setTimeout()</code> récursif - cela maintiendra l'intervalle de temps constant entre les exécutions, quelle que soit la durée d'exécution du code, et vous n'obtiendrez pas d'erreurs.</p> +Lorsque votre code a le potentiel de prendre plus de temps à s'exécuter que l'intervalle de temps que vous avez assigné, il est préférable d'utiliser le `setTimeout()` récursif - cela maintiendra l'intervalle de temps constant entre les exécutions, quelle que soit la durée d'exécution du code, et vous n'obtiendrez pas d'erreurs. -<h3 id="immediate_timeouts">Délais immédiats</h3> +### Délais immédiats -<p>En utilisant <code>0</code> comme valeur pour <code>setTimeout()</code>, on planifie l'exécution de la fonction de rappel spécifiée dès que possible, mais seulement après l'exécution du processus de code principal.</p> +En utilisant `0` comme valeur pour `setTimeout()`, on planifie l'exécution de la fonction de rappel spécifiée dès que possible, mais seulement après l'exécution du processus de code principal. -<p>Par exemple, le code ci-dessous (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/zero-settimeout.html">voir en direct</a>) produit une alerte contenant <code>"Hello"</code>, puis une alerte contenant <code>"World"</code> dès que vous cliquez sur OK sur la première alerte.</p> +Par exemple, le code ci-dessous ([voir en direct](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/zero-settimeout.html)) produit une alerte contenant `"Hello"`, puis une alerte contenant `"World"` dès que vous cliquez sur OK sur la première alerte. -<pre class="brush: js">setTimeout(() => { +```js +setTimeout(() => { alert('World'); }, 0); -alert('Hello');</pre> +alert('Hello'); +``` -<p>Cela peut être utile dans les cas où vous souhaitez définir un bloc de code à exécuter dès que l'ensemble du thread principal a terminé son exécution - placez-le dans la boucle d'événement asynchrone, de sorte qu'il s'exécutera immédiatement après.</p> +Cela peut être utile dans les cas où vous souhaitez définir un bloc de code à exécuter dès que l'ensemble du thread principal a terminé son exécution - placez-le dans la boucle d'événement asynchrone, de sorte qu'il s'exécutera immédiatement après. -<h3 id="clearing_with_cleartimeout_or_clearinterval">Effacement avec clearTimeout() ou clearInterval()</h3> +### Effacement avec clearTimeout() ou clearInterval() -<p><code>clearTimeout()</code> et <code>clearInterval()</code> utilisent toutes deux la même liste d'entrées pour effacer. Il est intéressant de noter que cela signifie que vous pouvez utiliser l'une comme l'autre méthode pour effacer un <code>setTimeout()</code> ou <code>setInterval()</code>.</p> +`clearTimeout()` et `clearInterval()` utilisent toutes deux la même liste d'entrées pour effacer. Il est intéressant de noter que cela signifie que vous pouvez utiliser l'une comme l'autre méthode pour effacer un `setTimeout()` ou `setInterval()`. -<p>Par souci de cohérence, vous devriez utiliser <code>clearTimeout()</code> pour effacer les entrées <code>setTimeout()</code> et <code>clearInterval()</code> pour effacer les entrées <code>setInterval()</code>. Cela permettra d'éviter toute confusion.</p> +Par souci de cohérence, vous devriez utiliser `clearTimeout()` pour effacer les entrées `setTimeout()` et `clearInterval()` pour effacer les entrées `setInterval()`. Cela permettra d'éviter toute confusion. -<h2 id="requestanimationframe">requestAnimationFrame()</h2> +## requestAnimationFrame() -<p><a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</code></a> est une fonction de bouclage spécialisée, créée pour exécuter des animations de manière efficace dans le navigateur. Elle exécute un bloc de code spécifié avant que le navigateur ne repeigne ensuite l'affichage, ce qui permet d'exécuter une animation à une fréquence de rafraîchissement appropriée, quel que soit l'environnement dans lequel elle est exécutée.</p> +[`requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame) est une fonction de bouclage spécialisée, créée pour exécuter des animations de manière efficace dans le navigateur. Elle exécute un bloc de code spécifié avant que le navigateur ne repeigne ensuite l'affichage, ce qui permet d'exécuter une animation à une fréquence de rafraîchissement appropriée, quel que soit l'environnement dans lequel elle est exécutée. -<p>Elle a été créée en réponse aux problèmes perçus avec les fonctions asynchrones antérieures comme <code>setInterval()</code>, qui, par exemple, ne s'exécute pas à une fréquence d'images optimisée pour le matériel et continue à s'exécuter alors qu'elle pourrait s'arrêter lorsque l'onglet n'est plus actif ou si l'animation se déroule hors de la page, etc.</p> +Elle a été créée en réponse aux problèmes perçus avec les fonctions asynchrones antérieures comme `setInterval()`, qui, par exemple, ne s'exécute pas à une fréquence d'images optimisée pour le matériel et continue à s'exécuter alors qu'elle pourrait s'arrêter lorsque l'onglet n'est plus actif ou si l'animation se déroule hors de la page, etc. -<p>(<a href="http://creativejs.com/resources/requestanimationframe/index.html">Plus d'informations à ce sujet sur CreativeJS</a> <small>(en)</small>.)</p> +([Plus d'informations à ce sujet sur CreativeJS](http://creativejs.com/resources/requestanimationframe/index.html) (en).) -<div class="note"> - <p><strong>Note :</strong> Vous trouverez des exemples d'utilisation de <code>requestAnimationFrame()</code> ailleurs dans le cours - voir par exemple <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a>, et <a href="/fr/docs/Learn/JavaScript/Objects/Object_building_practice">La construction d'objet en pratique</a>.</p> -</div> +> **Note :** Vous trouverez des exemples d'utilisation de `requestAnimationFrame()` ailleurs dans le cours - voir par exemple [Dessiner des éléments graphiques](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics), et [La construction d'objet en pratique](/fr/docs/Learn/JavaScript/Objects/Object_building_practice). -<p>La méthode prend comme argument un rappel à invoquer avant le repeignage. C'est le modèle général dans lequel vous le verrez utilisé :</p> +La méthode prend comme argument un rappel à invoquer avant le repeignage. C'est le modèle général dans lequel vous le verrez utilisé : -<pre class="brush: js">function draw() { +```js +function draw() { // Le code du dessin va ici requestAnimationFrame(draw); } -draw();</pre> +draw(); +``` -<p>L'idée est de définir une fonction dans laquelle votre animation est mise à jour (par exemple, vos sprites sont déplacés, le score est mis à jour, les données sont rafraîchies, ou autre). Ensuite, vous l'appelez pour lancer le processus. À la fin du bloc de fonctions, vous appelez <code>requestAnimationFrame()</code> avec la référence de la fonction passée en paramètre, et cela indique au navigateur de rappeler la fonction lors du prochain rafraîchissement de l'affichage. Ceci est ensuite exécuté en continu, car le code appelle <code>requestAnimationFrame()</code> de manière récursive.</p> +L'idée est de définir une fonction dans laquelle votre animation est mise à jour (par exemple, vos sprites sont déplacés, le score est mis à jour, les données sont rafraîchies, ou autre). Ensuite, vous l'appelez pour lancer le processus. À la fin du bloc de fonctions, vous appelez `requestAnimationFrame()` avec la référence de la fonction passée en paramètre, et cela indique au navigateur de rappeler la fonction lors du prochain rafraîchissement de l'affichage. Ceci est ensuite exécuté en continu, car le code appelle `requestAnimationFrame()` de manière récursive. -<div class="note"> - <p><strong>Note :</strong> Si vous souhaitez réaliser une sorte d'animation DOM simple et constante, <a href="/fr/docs/Web/CSS/CSS_Animations">les animations CSS</a> sont probablement plus rapides. Elles sont calculées directement par le code interne du navigateur, plutôt que par JavaScript.</p> - <p>Si, toutefois, vous faites quelque chose de plus complexe et impliquant des objets qui ne sont pas directement accessibles à l'intérieur du DOM (comme les objets <a href="/fr/docs/Web/API/Canvas_API">2D Canvas API</a> ou <a href="/fr/docs/Web/API/WebGL_API">WebGL</a>), <code>requestAnimationFrame()</code> est la meilleure option dans la plupart des cas.</p> -</div> +> **Note :** Si vous souhaitez réaliser une sorte d'animation DOM simple et constante, [les animations CSS](/fr/docs/Web/CSS/CSS_Animations) sont probablement plus rapides. Elles sont calculées directement par le code interne du navigateur, plutôt que par JavaScript. +> +> Si, toutefois, vous faites quelque chose de plus complexe et impliquant des objets qui ne sont pas directement accessibles à l'intérieur du DOM (comme les objets [2D Canvas API](/fr/docs/Web/API/Canvas_API) ou [WebGL](/fr/docs/Web/API/WebGL_API)), `requestAnimationFrame()` est la meilleure option dans la plupart des cas. -<h3 id="how_fast_does_your_animation_run">Quelle est la vitesse de votre animation ?</h3> +### Quelle est la vitesse de votre animation ? -<p>La fluidité de votre animation dépend directement de la fréquence d'images de votre animation, qui est mesurée en images par seconde (ips). Plus ce nombre est élevé, plus votre animation sera fluide, jusqu'à un certain point.</p> +La fluidité de votre animation dépend directement de la fréquence d'images de votre animation, qui est mesurée en images par seconde (ips). Plus ce nombre est élevé, plus votre animation sera fluide, jusqu'à un certain point. -<p>Comme la plupart des écrans ont une fréquence de rafraîchissement de 60 Hz, la fréquence d'images la plus rapide que vous pouvez viser est de 60 images par seconde (IPS) lorsque vous travaillez avec des navigateurs Web. Cependant, plus d'images signifie plus de traitement, ce qui peut souvent provoquer des saccades et des sauts - également connus sous le nom de <em>dégradation des images</em>, ou <em>saccades</em>.</p> +Comme la plupart des écrans ont une fréquence de rafraîchissement de 60 Hz, la fréquence d'images la plus rapide que vous pouvez viser est de 60 images par seconde (IPS) lorsque vous travaillez avec des navigateurs Web. Cependant, plus d'images signifie plus de traitement, ce qui peut souvent provoquer des saccades et des sauts - également connus sous le nom de _dégradation des images_, ou _saccades_. -<p>Si vous disposez d'un moniteur avec une fréquence de rafraîchissement de 60 Hz et que vous souhaitez obtenir 60 IPS, vous disposez d'environ 16,7 millisecondes (<code>1000 / 60</code>) pour exécuter votre code d'animation et rendre chaque image. Ceci est un rappel que vous devrez être attentif à la quantité de code que vous essayez d'exécuter pendant chaque passage dans la boucle d'animation.</p> +Si vous disposez d'un moniteur avec une fréquence de rafraîchissement de 60 Hz et que vous souhaitez obtenir 60 IPS, vous disposez d'environ 16,7 millisecondes (`1000 / 60`) pour exécuter votre code d'animation et rendre chaque image. Ceci est un rappel que vous devrez être attentif à la quantité de code que vous essayez d'exécuter pendant chaque passage dans la boucle d'animation. -<p><code>requestAnimationFrame()</code> essaie toujours de se rapprocher le plus possible de cette valeur magique de 60 IPS. Parfois, ce n'est pas possible - si vous avez une animation vraiment complexe et que vous l'exécutez sur un ordinateur lent, votre fréquence d'images sera inférieure. Dans tous les cas, <code>requestAnimationFrame()</code> fera toujours du mieux qu'il peut avec ce dont il dispose.</p> +`requestAnimationFrame()` essaie toujours de se rapprocher le plus possible de cette valeur magique de 60 IPS. Parfois, ce n'est pas possible - si vous avez une animation vraiment complexe et que vous l'exécutez sur un ordinateur lent, votre fréquence d'images sera inférieure. Dans tous les cas, `requestAnimationFrame()` fera toujours du mieux qu'il peut avec ce dont il dispose. -<h3 id="how_does_requestanimationframe_differ_from_setinterval_and_settimeout">En quoi requestAnimationFrame() diffère-t-il de setInterval() et setTimeout() ?</h3> +### En quoi requestAnimationFrame() diffère-t-il de setInterval() et setTimeout() ? -<p>Parlons un peu plus de la façon dont la méthode <code>requestAnimationFrame()</code> diffère des autres méthodes utilisées précédemment. En regardant notre code d'en haut :</p> +Parlons un peu plus de la façon dont la méthode `requestAnimationFrame()` diffère des autres méthodes utilisées précédemment. En regardant notre code d'en haut : -<pre class="brush: js">function draw() { +```js +function draw() { // Le code du dessin va ici requestAnimationFrame(draw); } -draw();</pre> +draw(); +``` -<p>Voyons maintenant comment faire la même chose en utilisant <code>setInterval()</code> :</p> +Voyons maintenant comment faire la même chose en utilisant `setInterval()` : -<pre class="brush: js">function draw() { +```js +function draw() { // Le code du dessin va ici } -setInterval(draw, 17);</pre> +setInterval(draw, 17); +``` -<p>Comme nous l'avons couvert précédemment, vous ne spécifiez pas d'intervalle de temps pour <code>requestAnimationFrame()</code>. Il l'exécute simplement aussi vite et aussi bien que possible dans les conditions actuelles. Le navigateur ne perd pas non plus de temps à l'exécuter si l'animation est hors écran pour une raison quelconque, etc.</p> +Comme nous l'avons couvert précédemment, vous ne spécifiez pas d'intervalle de temps pour `requestAnimationFrame()`. Il l'exécute simplement aussi vite et aussi bien que possible dans les conditions actuelles. Le navigateur ne perd pas non plus de temps à l'exécuter si l'animation est hors écran pour une raison quelconque, etc. -<p><code>setInterval()</code>, d'autre part <em>exige</em> qu'un intervalle soit spécifié. Nous sommes arrivés à notre valeur finale de 17 via la formule <em>1000 millisecondes / 60Hz</em>, puis nous l'avons arrondie. Arrondir vers le haut est une bonne idée ; si vous arrondissez vers le bas, le navigateur pourrait essayer d'exécuter l'animation à une vitesse supérieure à 60 FPS, et cela ne ferait de toute façon aucune différence pour la fluidité de l'animation. Comme nous l'avons déjà dit, 60 Hz est la fréquence de rafraîchissement standard.</p> +`setInterval()`, d'autre part _exige_ qu'un intervalle soit spécifié. Nous sommes arrivés à notre valeur finale de 17 via la formule _1000 millisecondes / 60Hz_, puis nous l'avons arrondie. Arrondir vers le haut est une bonne idée ; si vous arrondissez vers le bas, le navigateur pourrait essayer d'exécuter l'animation à une vitesse supérieure à 60 FPS, et cela ne ferait de toute façon aucune différence pour la fluidité de l'animation. Comme nous l'avons déjà dit, 60 Hz est la fréquence de rafraîchissement standard. -<h3 id="including_a_timestamp">Inclure un horodatage</h3> +### Inclure un horodatage -<p>Le rappel réel passé à la fonction <code>requestAnimationFrame()</code> peut également recevoir un paramètre : une valeur <em>timestamp</em>, qui représente le temps depuis que le <code>requestAnimationFrame()</code> a commencé à s'exécuter.</p> +Le rappel réel passé à la fonction `requestAnimationFrame()` peut également recevoir un paramètre : une valeur _timestamp_, qui représente le temps depuis que le `requestAnimationFrame()` a commencé à s'exécuter. -<p>C'est utile car cela vous permet d'exécuter des choses à des moments précis et à un rythme constant, quelle que soit la vitesse ou la lenteur de votre appareil. Le modèle général que vous utiliserez ressemble à quelque chose comme ceci :</p> +C'est utile car cela vous permet d'exécuter des choses à des moments précis et à un rythme constant, quelle que soit la vitesse ou la lenteur de votre appareil. Le modèle général que vous utiliserez ressemble à quelque chose comme ceci : -<pre class="brush: js">let startTime = null; +```js +let startTime = null; function draw(timestamp) { if (!startTime) { @@ -321,279 +332,316 @@ function draw(timestamp) { requestAnimationFrame(draw); } -draw();</pre> +draw(); +``` -<h3 id="browser_support">Prise en charge des navigateurs</h3> +### Prise en charge des navigateurs -<p><code>requestAnimationFrame()</code> est supporté par des navigateurs plus récents que pour <code>setInterval()</code>/<code>setTimeout()</code>. Il est intéressant de noter qu'elle est disponible dans Internet Explorer 10 et plus.</p> +`requestAnimationFrame()` est supporté par des navigateurs plus récents que pour `setInterval()`/`setTimeout()`. Il est intéressant de noter qu'elle est disponible dans Internet Explorer 10 et plus. -<p>Ainsi, à moins que vous ne deviez prendre en charge d'anciennes versions d'IE, il y a peu de raisons de ne pas utiliser <code>requestAnimationFrame()</code>.</p> +Ainsi, à moins que vous ne deviez prendre en charge d'anciennes versions d'IE, il y a peu de raisons de ne pas utiliser `requestAnimationFrame()`. -<h3 id="a_simple_example">Un exemple simple</h3> +### Un exemple simple -<p>Assez avec la théorie ! Construisons votre propre exemple personnel de <code>requestAnimationFrame()</code>. Vous allez créer une simple "animation de toupie" - le genre que vous pourriez voir affiché dans une application lorsqu'elle est occupée à se connecter au serveur, etc.</p> +Assez avec la théorie ! Construisons votre propre exemple personnel de `requestAnimationFrame()`. Vous allez créer une simple "animation de toupie" - le genre que vous pourriez voir affiché dans une application lorsqu'elle est occupée à se connecter au serveur, etc. -<div class="note"> - <p><strong>Note :</strong> Dans un exemple du monde réel, vous devriez probablement utiliser des animations CSS pour exécuter ce type d'animation simple. Cependant, ce genre d'exemple est très utile pour démontrer l'utilisation de <code>requestAnimationFrame()</code>, et vous seriez plus susceptible d'utiliser ce genre de technique lorsque vous faites quelque chose de plus complexe comme la mise à jour de l'affichage d'un jeu à chaque image.</p> -</div> +> **Note :** Dans un exemple du monde réel, vous devriez probablement utiliser des animations CSS pour exécuter ce type d'animation simple. Cependant, ce genre d'exemple est très utile pour démontrer l'utilisation de `requestAnimationFrame()`, et vous seriez plus susceptible d'utiliser ce genre de technique lorsque vous faites quelque chose de plus complexe comme la mise à jour de l'affichage d'un jeu à chaque image. -<ol> - <li><p>Prenez un modèle HTML de base (<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">comme celui-ci</a>).</p></li> - <li><p>Placez un élément <a href="/fr/docs/Web/HTML/Element/div"><code><div></code></a> vide à l'intérieur de l'élément <a href="/fr/docs/Web/HTML/Element/body"><code><body></code></a>, puis ajoutez un caractère ↻ à l'intérieur. Ce caractère de flèche circulaire fera office de notre toupie pour cet exemple.</p></li> - <li><p>Appliquez le CSS suivant au modèle HTML (de la manière que vous préférez). Cela définit un fond rouge sur la page, définit la hauteur du <code><body></code> à <code>100%</code> de la hauteur de <a href="/fr/docs/Web/HTML/Element/html"><code><html></code></a>, et centre le <code><div></code> à l'intérieur du <code><body></code>, horizontalement et verticalement.</p> - <pre class="brush: css">html { - background-color: white; - height: 100%; -} +1. Prenez un modèle HTML de base ([comme celui-ci](https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html)). +2. Placez un élément [`<div>`](/fr/docs/Web/HTML/Element/div) vide à l'intérieur de l'élément [`<body>`](/fr/docs/Web/HTML/Element/body), puis ajoutez un caractère ↻ à l'intérieur. Ce caractère de flèche circulaire fera office de notre toupie pour cet exemple. +3. Appliquez le CSS suivant au modèle HTML (de la manière que vous préférez). Cela définit un fond rouge sur la page, définit la hauteur du `<body>` à `100%` de la hauteur de [`<html>`](/fr/docs/Web/HTML/Element/html), et centre le `<div>` à l'intérieur du `<body>`, horizontalement et verticalement. -body { - height: inherit; - background-color: red; - margin: 0; - display: flex; - justify-content: center; - align-items: center; -} + ```css + html { + background-color: white; + height: 100%; + } -div { - display: inline-block; - font-size: 10rem; -}</pre> - </li> - <li><p>Insérez un élément <a href="/fr/docs/Web/HTML/Element/script"><code><script></code></a> juste au-dessus de la balise de fermeture <code></body></code>.</p></li> - <li><p>Insérez le JavaScript suivant dans votre élément <code><script></code>. Ici, vous stockez une référence à l'élément <code><div> ; </code> à l'intérieur d'une constante, définissez une variable <code>rotateCount</code> à <code>0</code>, définissez une variable non initialisée qui sera utilisée plus tard pour contenir une référence à l'appel <code>requestAnimationFrame()</code>, et en définissant une variable <code>startTime</code> à <code>null</code>, qui sera plus tard utilisée pour stocker l'heure de début de l'appel <code>requestAnimationFrame()</code>.</p> - <pre class="brush: js">const spinner = document.querySelector('div'); -let rotateCount = 0; -let startTime = null; -let rAF; -</pre> - </li> - <li> - <p>Sous le code précédent, insérez une fonction <code>draw()</code> qui sera utilisée pour contenir notre code d'animation, qui inclut le paramètre <code>timestamp</code> :</p> - <pre class="brush: js">function draw(timestamp) { - -}</pre> - </li> - <li><p>À l'intérieur de <code>draw()</code>, ajoutez les lignes suivantes. Elles définiront l'heure de départ si elle n'est pas déjà définie (cela ne se produira que lors de la première itération de la boucle), et définiront le <code>rotateCount</code> à une valeur pour faire tourner le spinner par (l'horodatage actuel, prendre l'horodatage de départ, divisé par trois pour que cela n'aille pas trop vite) :</p> - <pre class="brush: js"> if(!startTime) { - startTime = timestamp; - } + body { + height: inherit; + background-color: red; + margin: 0; + display: flex; + justify-content: center; + align-items: center; + } + + div { + display: inline-block; + font-size: 10rem; + } + ``` + +4. Insérez un élément [`<script>`](/fr/docs/Web/HTML/Element/script) juste au-dessus de la balise de fermeture `</body>`. +5. Insérez le JavaScript suivant dans votre élément `<script>`. Ici, vous stockez une référence à l'élément `<div> ; `à l'intérieur d'une constante, définissez une variable `rotateCount` à `0`, définissez une variable non initialisée qui sera utilisée plus tard pour contenir une référence à l'appel `requestAnimationFrame()`, et en définissant une variable `startTime` à `null`, qui sera plus tard utilisée pour stocker l'heure de début de l'appel `requestAnimationFrame()`. + + ```js + const spinner = document.querySelector('div'); + let rotateCount = 0; + let startTime = null; + let rAF; + ``` - rotateCount = (timestamp - startTime) / 3; -</pre> - </li> - <li><p>Sous la ligne précédente à l'intérieur de <code>draw()</code>, ajoutez le bloc suivant - il s'assure que la valeur de <code>rotateCount</code> est comprise entre <code>0</code> et <code>360</code> en utilisant le modulo à 360 (c'est-à-dire le reste restant lorsque la valeur est divisée par <code>360</code>) afin que l'animation du cercle puisse continuer sans interruption, à une valeur basse et raisonnable. Notez que ce n'est pas strictement nécessaire, mais il est plus facile de travailler avec des valeurs de 0-359 degrés que des valeurs comme <code>"128000 degrés"</code>.</p> - <pre class="brush: js">rotateCount %= 360;</pre> - </li> - <li>Ensuite, sous le bloc précédent, ajoutez la ligne suivante pour faire tourner le spinner : - <pre class="brush: js">spinner.style.transform = `rotate(${rotateCount}deg)`;</pre> - </li> - <li><p>Tout en bas, à l'intérieur de la fonction <code>draw()</code>, insérez la ligne suivante. C'est la clé de toute l'opération - vous définissez la variable définie précédemment à un appel actif <code>requestAnimation()</code>, qui prend la fonction <code>draw()</code> comme paramètre. Cela fait démarrer l'animation, en exécutant constamment la fonction <code>draw()</code> à un taux aussi proche que possible de 60 IPS.</p> - <pre class="brush: js">rAF = requestAnimationFrame(draw);</pre> - </li> - <li><p>Sous la définition de la fonction <code>draw()</code>, ajoutez un appel à la fonction <code>draw()</code> pour lancer l'animation.</p> - <pre class="brush: js">draw();</pre> - </li> -</ol> +6. Sous le code précédent, insérez une fonction `draw()` qui sera utilisée pour contenir notre code d'animation, qui inclut le paramètre `timestamp` : -<div class="note"> - <p><strong>Note :</strong> Vous pouvez trouver l'<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">exemple terminé en direct sur GitHub</a>. (Vous pouvez également voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">code source</a>).</p> -</div> + ```js + function draw(timestamp) { -<h3 id="clearing_a_requestanimationframe_call">Effacer un appel de requestAnimationFrame()</h3> + } + ``` + +7. À l'intérieur de `draw()`, ajoutez les lignes suivantes. Elles définiront l'heure de départ si elle n'est pas déjà définie (cela ne se produira que lors de la première itération de la boucle), et définiront le `rotateCount` à une valeur pour faire tourner le spinner par (l'horodatage actuel, prendre l'horodatage de départ, divisé par trois pour que cela n'aille pas trop vite) : + + ```js + if(!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; + ``` + +8. Sous la ligne précédente à l'intérieur de `draw()`, ajoutez le bloc suivant - il s'assure que la valeur de `rotateCount` est comprise entre `0` et `360` en utilisant le modulo à 360 (c'est-à-dire le reste restant lorsque la valeur est divisée par `360`) afin que l'animation du cercle puisse continuer sans interruption, à une valeur basse et raisonnable. Notez que ce n'est pas strictement nécessaire, mais il est plus facile de travailler avec des valeurs de 0-359 degrés que des valeurs comme `"128000 degrés"`. + + ```js + rotateCount %= 360; + ``` + +9. Ensuite, sous le bloc précédent, ajoutez la ligne suivante pour faire tourner le spinner : + + ```js + spinner.style.transform = `rotate(${rotateCount}deg)`; + ``` -<p>Effacer un appel de <code>requestAnimationFrame()</code> peut être fait en appelant la méthode <code>cancelAnimationFrame()</code> correspondante. (Notez que le nom de la fonction commence par "cancel", et non par "clear" comme pour les méthodes "set...").</p> +10. Tout en bas, à l'intérieur de la fonction `draw()`, insérez la ligne suivante. C'est la clé de toute l'opération - vous définissez la variable définie précédemment à un appel actif `requestAnimation()`, qui prend la fonction `draw()` comme paramètre. Cela fait démarrer l'animation, en exécutant constamment la fonction `draw()` à un taux aussi proche que possible de 60 IPS. -<p>Il suffit de lui passer la valeur renvoyée par l'appel <code>requestAnimationFrame()</code> à annuler, que vous avez stockée dans la variable <code>rAF</code> :</p> + ```js + rAF = requestAnimationFrame(draw); + ``` -<pre class="brush: js">cancelAnimationFrame(rAF);</pre> +11. Sous la définition de la fonction `draw()`, ajoutez un appel à la fonction `draw()` pour lancer l'animation. -<h3 id="active_learning_starting_and_stopping_our_spinner">Apprentissage actif : Démarrer et arrêter la toupie</h3> + ```js + draw(); + ``` -<p>Dans cet exercice, nous aimerions que vous testiez la méthode <code>cancelAnimationFrame()</code> en prenant notre exemple précédent et en le mettant à jour, en ajoutant un écouteur d'événements pour démarrer et arrêter le spinner lorsque la souris est cliquée n'importe où sur la page.</p> +> **Note :** Vous pouvez trouver l'[exemple terminé en direct sur GitHub](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html). (Vous pouvez également voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html)). -<p>Quelques conseils :</p> +### Effacer un appel de requestAnimationFrame() -<ul> - <li>Un écouteur d'événements <code>click</code> peut être ajouté à la plupart des éléments, y compris le document <code><body></code>. Il est plus logique de le placer sur l'élément <code><body></code> si vous voulez maximiser la zone cliquable - l'événement remonte jusqu'à ses éléments enfants.</li> - <li>Vous voudrez ajouter une variable de suivi pour vérifier si la toupie tourne ou non, effacer le cadre d'animation si c'est le cas, et le rappeler si ce n'est pas le cas.</li> -</ul> +Effacer un appel de `requestAnimationFrame()` peut être fait en appelant la méthode `cancelAnimationFrame()` correspondante. (Notez que le nom de la fonction commence par "cancel", et non par "clear" comme pour les méthodes "set..."). -<div class="note"> - <p><strong>Note :</strong> Essayez d'abord vous-même ; si vous êtes vraiment bloqué, consultez nos pages <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">exemple en direct</a> et <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">code source</a>.</p> -</div> +Il suffit de lui passer la valeur renvoyée par l'appel `requestAnimationFrame()` à annuler, que vous avez stockée dans la variable `rAF` : -<h3 id="throttling_a_requestanimationframe_animation">Ralentissement d'une animation requestAnimationFrame()</h3> +```js +cancelAnimationFrame(rAF); +``` -<p>Une limitation de <code>requestAnimationFrame()</code> est que vous ne pouvez pas choisir votre fréquence d'images. Ce n'est pas un problème la plupart du temps, car en général, vous voulez que votre animation se déroule de la manière la plus fluide possible. Mais qu'en est-il lorsque vous souhaitez créer une animation old school, de style 8 bits ?</p> +### Apprentissage actif : Démarrer et arrêter la toupie -<p>C'était un problème, par exemple, dans l'animation de marche inspirée de Monkey Island de notre article <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a> :</p> +Dans cet exercice, nous aimerions que vous testiez la méthode `cancelAnimationFrame()` en prenant notre exemple précédent et en le mettant à jour, en ajoutant un écouteur d'événements pour démarrer et arrêter le spinner lorsque la souris est cliquée n'importe où sur la page. -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}}</p> +Quelques conseils : -<p>Dans cet exemple, vous devez animer à la fois la position du personnage à l'écran et le sprite affiché. Il n'y a que 6 images dans l'animation du sprite. Si vous montriez une image différente du sprite pour chaque image affichée à l'écran par <code>requestAnimationFrame()</code>, Guybrush bougerait ses membres trop vite et l'animation aurait l'air ridicule. Cet exemple étrangle la vitesse à laquelle le sprite cycle ses images en utilisant le code suivant :</p> +- Un écouteur d'événements `click` peut être ajouté à la plupart des éléments, y compris le document `<body>`. Il est plus logique de le placer sur l'élément `<body>` si vous voulez maximiser la zone cliquable - l'événement remonte jusqu'à ses éléments enfants. +- Vous voudrez ajouter une variable de suivi pour vérifier si la toupie tourne ou non, effacer le cadre d'animation si c'est le cas, et le rappeler si ce n'est pas le cas. -<pre class="brush: js">if (posX % 13 === 0) { +> **Note :** Essayez d'abord vous-même ; si vous êtes vraiment bloqué, consultez nos pages [exemple en direct](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html) et [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html). + +### Ralentissement d'une animation requestAnimationFrame() + +Une limitation de `requestAnimationFrame()` est que vous ne pouvez pas choisir votre fréquence d'images. Ce n'est pas un problème la plupart du temps, car en général, vous voulez que votre animation se déroule de la manière la plus fluide possible. Mais qu'en est-il lorsque vous souhaitez créer une animation old school, de style 8 bits ? + +C'était un problème, par exemple, dans l'animation de marche inspirée de Monkey Island de notre article [Dessiner des éléments graphiques](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics) : + +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}} + +Dans cet exemple, vous devez animer à la fois la position du personnage à l'écran et le sprite affiché. Il n'y a que 6 images dans l'animation du sprite. Si vous montriez une image différente du sprite pour chaque image affichée à l'écran par `requestAnimationFrame()`, Guybrush bougerait ses membres trop vite et l'animation aurait l'air ridicule. Cet exemple étrangle la vitesse à laquelle le sprite cycle ses images en utilisant le code suivant : + +```js +if (posX % 13 === 0) { if (sprite === 5) { sprite = 0; } else { sprite++; } -}</pre> +} +``` -<p>Ainsi, le code ne cycle le sprite qu'une fois toutes les 13 images d'animation.</p> +Ainsi, le code ne cycle le sprite qu'une fois toutes les 13 images d'animation. -<p>...En fait, c'est environ toutes les 6,5 images, car nous mettons à jour <code>posX</code> (position du personnage sur l'écran) par deux à chaque image :</p> +...En fait, c'est environ toutes les 6,5 images, car nous mettons à jour `posX` (position du personnage sur l'écran) par deux à chaque image : -<pre class="brush: js">if (posX > width/2) { +```js +if (posX > width/2) { newStartPos = -( (width/2) + 102 ); posX = Math.ceil(newStartPos / 13) * 13; console.log(posX); } else { posX += 2; -}</pre> +} +``` -<p>C'est le code qui calcule comment mettre à jour la position dans chaque image d'animation.</p> +C'est le code qui calcule comment mettre à jour la position dans chaque image d'animation. -<p>La méthode que vous utilisez pour accélérer votre animation dépendra de votre code particulier. Par exemple, dans l'exemple précédent de la toupie, vous pourriez faire en sorte qu'elle semble se déplacer plus lentement en n'augmentant le <code>rotateCount</code> que de un à chaque image, au lieu de deux.</p> +La méthode que vous utilisez pour accélérer votre animation dépendra de votre code particulier. Par exemple, dans l'exemple précédent de la toupie, vous pourriez faire en sorte qu'elle semble se déplacer plus lentement en n'augmentant le `rotateCount` que de un à chaque image, au lieu de deux. -<h2 id="active_learning_a_reaction_game">Apprentissage actif : un jeu de réaction</h2> +## Apprentissage actif : un jeu de réaction -<p>Pour la dernière section de cet article, vous allez créer un jeu de réaction à 2 joueurs. Le jeu aura deux joueurs, dont l'un contrôlera le jeu à l'aide de la touche <kbd>A</kbd>, et l'autre avec la touche <kbd>L</kbd>.</p> +Pour la dernière section de cet article, vous allez créer un jeu de réaction à 2 joueurs. Le jeu aura deux joueurs, dont l'un contrôlera le jeu à l'aide de la touche <kbd>A</kbd>, et l'autre avec la touche <kbd>L</kbd>. -<p>Lorsque l'on appuie sur le bouton <em>Start</em>, une toupie comme celle que nous avons vue précédemment s'affiche pendant un temps aléatoire compris entre 5 et 10 secondes. Après ce temps, un message apparaîtra disant <code>"PLAYERS GO !!"</code> - une fois que cela se produit, le premier joueur à appuyer sur son bouton de contrôle gagnera la partie.</p> +Lorsque l'on appuie sur le bouton _Start_, une toupie comme celle que nous avons vue précédemment s'affiche pendant un temps aléatoire compris entre 5 et 10 secondes. Après ce temps, un message apparaîtra disant `"PLAYERS GO !!"` - une fois que cela se produit, le premier joueur à appuyer sur son bouton de contrôle gagnera la partie. -<p>{{EmbedGHLiveSample("learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html", '100%', 500)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html", '100%', 500)}} -<p>Travaillons ensemble :</p> +Travaillons ensemble : -<ol> - <li><p>Tout d'abord, téléchargez le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game-starter.html">fichier de démarrage de l'application</a>. Celui-ci contient la structure HTML et le style CSS finis, ce qui nous donne un plateau de jeu qui affiche les informations des deux joueurs (comme vu ci-dessus), mais avec le spinner et le paragraphe des résultats affichés l'un au-dessus de l'autre. Il ne vous reste plus qu'à écrire le code JavaScript.</p></li> - <li><p>À l'intérieur de l'élément vide <a href="/fr/docs/Web/HTML/Element/script"><code><script></code></a> de votre page, commencez par ajouter les lignes de code suivantes qui définissent certaines constantes et variables dont vous aurez besoin dans le reste du code :</p> - <pre class="brush: js">const spinner = document.querySelector('.spinner p'); -const spinnerContainer = document.querySelector('.spinner'); -let rotateCount = 0; -let startTime = null; -let rAF; -const btn = document.querySelector('button'); -const result = document.querySelector('.result');</pre> - <p>Dans l'ordre, ce sont :</p> - <ol> - <li>Une référence à la toupie, afin que vous puissiez l'animer.</li> - <li>Une référence à l'élément <a href="/fr/docs/Web/HTML/Element/div"><code><div></code></a> qui contient la toupie, utilisée pour l'afficher et la masquer.</li> - <li>Un nombre de rotations. Ce paramètre détermine le nombre de rotations de la toupie que vous souhaitez afficher à chaque image de l'animation.</li> - <li>Un temps de démarrage nul. Il sera rempli avec une heure de début lorsque la toupie commencera à tourner.</li> - <li>Une variable non initialisée pour stocker ultérieurement l'appel <a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame()</code></a> qui anime la toupie.</li> - <li>Une référence au bouton de démarrage.</li> - <li>Une référence au paragraphe des résultats.</li> - </ol> - </li> - <li><p>Ensuite, sous les lignes de code précédentes, ajoutez la fonction suivante. Elle prend deux nombres et retourne un nombre aléatoire entre les deux. Vous en aurez besoin pour générer un intervalle de temps aléatoire plus tard.</p> - <pre class="brush: js">function random(min,max) { - var num = Math.floor(Math.random()*(max-min)) + min; - return num; -}</pre> - </li> - <li><p>Ajoutez ensuite la fonction <code>draw()</code>, qui anime la toupie. Cette version est très similaire à celle de l'exemple simple de la toupie, plus haut :</p> - <pre class="brush: js">function draw(timestamp) { - if(!startTime) { - startTime = timestamp; - } +1. Tout d'abord, téléchargez le [fichier de démarrage de l'application](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game-starter.html). Celui-ci contient la structure HTML et le style CSS finis, ce qui nous donne un plateau de jeu qui affiche les informations des deux joueurs (comme vu ci-dessus), mais avec le spinner et le paragraphe des résultats affichés l'un au-dessus de l'autre. Il ne vous reste plus qu'à écrire le code JavaScript. +2. À l'intérieur de l'élément vide [`<script>`](/fr/docs/Web/HTML/Element/script) de votre page, commencez par ajouter les lignes de code suivantes qui définissent certaines constantes et variables dont vous aurez besoin dans le reste du code : + + ```js + const spinner = document.querySelector('.spinner p'); + const spinnerContainer = document.querySelector('.spinner'); + let rotateCount = 0; + let startTime = null; + let rAF; + const btn = document.querySelector('button'); + const result = document.querySelector('.result'); + ``` + + Dans l'ordre, ce sont : + + 1. Une référence à la toupie, afin que vous puissiez l'animer. + 2. Une référence à l'élément [`<div>`](/fr/docs/Web/HTML/Element/div) qui contient la toupie, utilisée pour l'afficher et la masquer. + 3. Un nombre de rotations. Ce paramètre détermine le nombre de rotations de la toupie que vous souhaitez afficher à chaque image de l'animation. + 4. Un temps de démarrage nul. Il sera rempli avec une heure de début lorsque la toupie commencera à tourner. + 5. Une variable non initialisée pour stocker ultérieurement l'appel [`requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame) qui anime la toupie. + 6. Une référence au bouton de démarrage. + 7. Une référence au paragraphe des résultats. + +3. Ensuite, sous les lignes de code précédentes, ajoutez la fonction suivante. Elle prend deux nombres et retourne un nombre aléatoire entre les deux. Vous en aurez besoin pour générer un intervalle de temps aléatoire plus tard. + + ```js + function random(min,max) { + var num = Math.floor(Math.random()*(max-min)) + min; + return num; + } + ``` + +4. Ajoutez ensuite la fonction `draw()`, qui anime la toupie. Cette version est très similaire à celle de l'exemple simple de la toupie, plus haut : + + ```js + function draw(timestamp) { + if(!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; + + rotateCount %= 360; + + spinner.style.transform = 'rotate(' + rotateCount + 'deg)'; + rAF = requestAnimationFrame(draw); + } + ``` + +5. Il est maintenant temps de mettre en place l'état initial de l'application lors du premier chargement de la page. Ajoutez les deux lignes suivantes, qui masquent le paragraphe des résultats et le conteneur de la toupie en utilisant `display : none;`. + + ```js + result.style.display = 'none'; + spinnerContainer.style.display = 'none'; + ``` - rotateCount = (timestamp - startTime) / 3; - - rotateCount %= 360; - - spinner.style.transform = 'rotate(' + rotateCount + 'deg)'; - rAF = requestAnimationFrame(draw); -}</pre> - </li> - <li><p>Il est maintenant temps de mettre en place l'état initial de l'application lors du premier chargement de la page. Ajoutez les deux lignes suivantes, qui masquent le paragraphe des résultats et le conteneur de la toupie en utilisant <code>display : none;</code>.</p> - <pre class="brush: js">result.style.display = 'none'; -spinnerContainer.style.display = 'none';</pre> - </li> - <li><p>Ensuite, définissez une fonction <code>reset()</code>, qui remet l'application dans l'état initial nécessaire pour relancer le jeu après qu'il a été joué. Ajoutez ce qui suit au bas de votre code :</p> - <pre class="brush: js">function reset() { - btn.style.display = 'block'; - result.textContent = ''; - result.style.display = 'none'; -}</pre> - </li> - <li><p>Bon, assez de préparation ! Il est temps de rendre le jeu jouable ! Ajoutez le bloc suivant à votre code. La fonction <code>start()</code> appelle <code>draw()</code> pour commencer à faire tourner la toupie et l'afficher dans l'interface utilisateur, cache le bouton <em>Start</em> pour que vous ne puissiez pas perturber le jeu en le démarrant plusieurs fois simultanément, et exécute un appel <code>setTimeout()</code> qui exécute une fonction <code>setEndgame()</code> après qu'un intervalle aléatoire entre 5 et 10 secondes se soit écoulé. Le bloc suivant ajoute également un écouteur d'événements à votre bouton pour exécuter la fonction <code>start()</code> lorsqu'il est cliqué.</p> - <pre class="brush: js">btn.addEventListener('click', start); - -function start() { - draw(); - spinnerContainer.style.display = 'block'; - btn.style.display = 'none'; - setTimeout(setEndgame, random(5000,10000)); -}</pre> - <div class="note"> - <p><strong>Note :</strong> Vous verrez que cet exemple appelle <code>setTimeout()</code> sans stocker la valeur de retour. (Donc, pas <code>let myTimeout = setTimeout(functionName, interval)</code>.)</p> - <p>Cela fonctionne très bien, tant que vous n'avez pas besoin d'effacer votre intervalle/temps d'attente à un moment donné. Si vous le faites, vous devrez sauvegarder l'identifiant renvoyé !</p> - </div> - <p>Le résultat net du code précédent est que lorsque le bouton <em>Start</em> est pressé, la toupie est affichée et les joueurs sont amenés à attendre un temps aléatoire avant d'être invités à appuyer sur leur bouton. Cette dernière partie est gérée par la fonction <code>setEndgame()</code>, que vous allez définir ensuite.</p> - </li> - <li><p>Ajoutez ensuite la fonction suivante à votre code :</p> - <pre class="brush: js">function setEndgame() { - cancelAnimationFrame(rAF); - spinnerContainer.style.display = 'none'; - result.style.display = 'block'; - result.textContent = 'JOUEURS : ALLEZ-Y !!'; - - document.addEventListener('keydown', keyHandler); - - function keyHandler(e) { - let isOver = false; - console.log(e.key); - - if (e.key === "a") { - result.textContent = 'Le joueur 1 a gagné !!'; - isOver = true; - } else if (e.key === "l") { - result.textContent = 'Le joueur 2 a gagné !!'; - isOver = true; +6. Ensuite, définissez une fonction `reset()`, qui remet l'application dans l'état initial nécessaire pour relancer le jeu après qu'il a été joué. Ajoutez ce qui suit au bas de votre code : + + ```js + function reset() { + btn.style.display = 'block'; + result.textContent = ''; + result.style.display = 'none'; } + ``` + +7. Bon, assez de préparation ! Il est temps de rendre le jeu jouable ! Ajoutez le bloc suivant à votre code. La fonction `start()` appelle `draw()` pour commencer à faire tourner la toupie et l'afficher dans l'interface utilisateur, cache le bouton _Start_ pour que vous ne puissiez pas perturber le jeu en le démarrant plusieurs fois simultanément, et exécute un appel `setTimeout()` qui exécute une fonction `setEndgame()` après qu'un intervalle aléatoire entre 5 et 10 secondes se soit écoulé. Le bloc suivant ajoute également un écouteur d'événements à votre bouton pour exécuter la fonction `start()` lorsqu'il est cliqué. - if (isOver) { - document.removeEventListener('keydown', keyHandler); - setTimeout(reset, 5000); + ```js + btn.addEventListener('click', start); + + function start() { + draw(); + spinnerContainer.style.display = 'block'; + btn.style.display = 'none'; + setTimeout(setEndgame, random(5000,10000)); + } + ``` + + > **Note :** Vous verrez que cet exemple appelle `setTimeout()` sans stocker la valeur de retour. (Donc, pas `let myTimeout = setTimeout(functionName, interval)`.) + > + > Cela fonctionne très bien, tant que vous n'avez pas besoin d'effacer votre intervalle/temps d'attente à un moment donné. Si vous le faites, vous devrez sauvegarder l'identifiant renvoyé ! + + Le résultat net du code précédent est que lorsque le bouton _Start_ est pressé, la toupie est affichée et les joueurs sont amenés à attendre un temps aléatoire avant d'être invités à appuyer sur leur bouton. Cette dernière partie est gérée par la fonction `setEndgame()`, que vous allez définir ensuite. + +8. Ajoutez ensuite la fonction suivante à votre code : + + ```js + function setEndgame() { + cancelAnimationFrame(rAF); + spinnerContainer.style.display = 'none'; + result.style.display = 'block'; + result.textContent = 'JOUEURS : ALLEZ-Y !!'; + + document.addEventListener('keydown', keyHandler); + + function keyHandler(e) { + let isOver = false; + console.log(e.key); + + if (e.key === "a") { + result.textContent = 'Le joueur 1 a gagné !!'; + isOver = true; + } else if (e.key === "l") { + result.textContent = 'Le joueur 2 a gagné !!'; + isOver = true; + } + + if (isOver) { + document.removeEventListener('keydown', keyHandler); + setTimeout(reset, 5000); + } + }; } - }; -}</pre> - <p>Son fonctionnement :</p> - <ol> - <li>Tout d'abord, annule l'animation de la toupie avec <a href="/fr/docs/Web/API/Window/cancelAnimationFrame"><code>cancelAnimationFrame()</code></a> (il est toujours bon de nettoyer les processus inutiles), et cache le conteneur de la toupie.</li> - <li>Ensuite, affiche le paragraphe des résultats et définissez son contenu textuel sur "JOUEURS : ALLEZ-Y !!" pour signaler aux joueurs qu'ils peuvent maintenant appuyer sur leur bouton pour gagner.</li> - <li>Attache un écouteur d'événements <a href="/fr/docs/Web/API/Document/keydown_event"><code>keydown</code></a> au document. Lorsqu'un bouton quelconque est enfoncé, la fonction <code>keyHandler()</code> est exécutée.</li> - <li>À l'intérieur de <code>keyHandler()</code>, le code inclut l'objet événement en tant que paramètre (représenté par <code>e</code>) - sa propriété <a href="/fr/docs/Web/API/KeyboardEvent/key"><code>key</code></a> contient la touche qui vient d'être pressée, et vous pouvez l'utiliser pour répondre à des pressions de touche spécifiques par des actions spécifiques.</li> - <li>Définit la variable <code>isOver</code> à false, afin que nous puissions suivre si les bonnes touches ont été pressées pour que le joueur 1 ou 2 gagne. Nous ne voulons pas que le jeu se termine lorsqu'une mauvaise touche a été pressée.</li> - <li>Enregistre <code>e.key</code> dans la console, ce qui est un moyen utile de connaître la valeur <code>key</code> des différentes touches sur lesquelles vous appuyez.</li> - <li>Lorsque <code>e.key</code> est "a", affiche un message pour dire que le joueur 1 a gagné, et lorsque <code>e.key</code> est "l", affiche un message pour dire que le joueur 2 a gagné. (<strong>Note:</strong> Cela ne fonctionnera qu'avec les minuscules a et l - si un A ou un L majuscule est soumis (la touche plus <kbd>Shift</kbd>), il est compté comme une touche différente !). Si une de ces touches a été pressée, mettez <code>isOver</code> à <code>true</code>.</li> - <li>Seulement si <code>isOver</code> est <code>true</code>, supprime l'écouteur d'événements <code>keydown</code> en utilisant <a href="/fr/docs/Web/API/EventTarget/removeEventListener"><code>removeEventListener()</code></a> de sorte qu'une fois que l'appui gagnant s'est produit, plus aucune entrée clavier n'est possible pour perturber le résultat final du jeu. Vous utilisez également <code>setTimeout()</code> pour appeler <code>reset()</code> après 5 secondes - comme expliqué précédemment, cette fonction réinitialise le jeu à son état initial afin qu'une nouvelle partie puisse être lancée.</li> - </ol> - </li> -</ol> - -<p>Voilà, c'est fait !</p> - -<div class="note"> - <p><strong>Note :</strong> Si vous êtes bloqué, consultez <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html">notre version du jeu en live</a> (voir également le <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game.html">code source</a>).</p> -</div> - -<h2 id="conclusion">Conclusion</h2> - -<p>Voilà, tous les éléments essentiels des boucles et des intervalles asynchrones sont couverts dans un seul article. Vous trouverez ces méthodes utiles dans de nombreuses situations, mais veillez à ne pas en abuser ! Parce qu'ils s'exécutent toujours sur le processus principal, les rappels lourds et intensifs (en particulier ceux qui manipulent le DOM) peuvent vraiment ralentir une page si vous ne faites pas attention.</p> - -<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</p> - -<h2 id="in_this_module">Dans ce module</h2> - -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Concepts">Concepts généraux de programmation asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Introducing">Introduction au JavaScript asynchrone</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asynchrone coopératif : Délais et intervalles</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Promises">Gérer les opérations asynchrones avec élégance grâce aux Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Async_await">Faciliter la programmation asynchrone avec async et await</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choisir la bonne approche</a></li> -</ul> + ``` + + Son fonctionnement : + + 1. Tout d'abord, annule l'animation de la toupie avec [`cancelAnimationFrame()`](/fr/docs/Web/API/Window/cancelAnimationFrame) (il est toujours bon de nettoyer les processus inutiles), et cache le conteneur de la toupie. + 2. Ensuite, affiche le paragraphe des résultats et définissez son contenu textuel sur "JOUEURS : ALLEZ-Y !!" pour signaler aux joueurs qu'ils peuvent maintenant appuyer sur leur bouton pour gagner. + 3. Attache un écouteur d'événements [`keydown`](/fr/docs/Web/API/Document/keydown_event) au document. Lorsqu'un bouton quelconque est enfoncé, la fonction `keyHandler()` est exécutée. + 4. À l'intérieur de `keyHandler()`, le code inclut l'objet événement en tant que paramètre (représenté par `e`) - sa propriété [`key`](/fr/docs/Web/API/KeyboardEvent/key) contient la touche qui vient d'être pressée, et vous pouvez l'utiliser pour répondre à des pressions de touche spécifiques par des actions spécifiques. + 5. Définit la variable `isOver` à false, afin que nous puissions suivre si les bonnes touches ont été pressées pour que le joueur 1 ou 2 gagne. Nous ne voulons pas que le jeu se termine lorsqu'une mauvaise touche a été pressée. + 6. Enregistre `e.key` dans la console, ce qui est un moyen utile de connaître la valeur `key` des différentes touches sur lesquelles vous appuyez. + 7. Lorsque `e.key` est "a", affiche un message pour dire que le joueur 1 a gagné, et lorsque `e.key` est "l", affiche un message pour dire que le joueur 2 a gagné. (**Note:** Cela ne fonctionnera qu'avec les minuscules a et l - si un A ou un L majuscule est soumis (la touche plus + + <kbd>Shift</kbd> + + ), il est compté comme une touche différente !). Si une de ces touches a été pressée, mettez `isOver` à `true`. + + 8. Seulement si `isOver` est `true`, supprime l'écouteur d'événements `keydown` en utilisant [`removeEventListener()`](/fr/docs/Web/API/EventTarget/removeEventListener) de sorte qu'une fois que l'appui gagnant s'est produit, plus aucune entrée clavier n'est possible pour perturber le résultat final du jeu. Vous utilisez également `setTimeout()` pour appeler `reset()` après 5 secondes - comme expliqué précédemment, cette fonction réinitialise le jeu à son état initial afin qu'une nouvelle partie puisse être lancée. + +Voilà, c'est fait ! + +> **Note :** Si vous êtes bloqué, consultez [notre version du jeu en live](https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html) (voir également le [code source](https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game.html)). + +## Conclusion + +Voilà, tous les éléments essentiels des boucles et des intervalles asynchrones sont couverts dans un seul article. Vous trouverez ces méthodes utiles dans de nombreuses situations, mais veillez à ne pas en abuser ! Parce qu'ils s'exécutent toujours sur le processus principal, les rappels lourds et intensifs (en particulier ceux qui manipulent le DOM) peuvent vraiment ralentir une page si vous ne faites pas attention. + +{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}} + +## Dans ce module + +- [Concepts généraux de programmation asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Concepts) +- [Introduction au JavaScript asynchrone](/fr/docs/Learn/JavaScript/Asynchronous/Introducing) +- [JavaScript asynchrone coopératif : Délais et intervalles](/fr/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals) +- [Gérer les opérations asynchrones avec élégance grâce aux Promesses](/fr/docs/Learn/JavaScript/Asynchronous/Promises) +- [Faciliter la programmation asynchrone avec async et await](/fr/docs/Learn/JavaScript/Asynchronous/Async_await) +- [Choisir la bonne approche](/fr/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach) diff --git a/files/fr/learn/javascript/building_blocks/build_your_own_function/index.md b/files/fr/learn/javascript/building_blocks/build_your_own_function/index.md index 696c4d50d3..96c62c5ff3 100644 --- a/files/fr/learn/javascript/building_blocks/build_your_own_function/index.md +++ b/files/fr/learn/javascript/building_blocks/build_your_own_function/index.md @@ -15,61 +15,110 @@ tags: translation_of: Learn/JavaScript/Building_blocks/Build_your_own_function original_slug: Apprendre/JavaScript/Building_blocks/Build_your_own_function --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}</div> - -<p>Dans l'article précédent, nous avons traité essentiellement de la théorie. Le présent article fournira une expérience pratique. Ici vous allez mettre en pratique ces connaissances en construisant vos propres fonctions. Tout au long, nous expliquerons également quelques détails supplémentaires concernant les fonctions.</p> +Dans l'article précédent, nous avons traité essentiellement de la théorie. Le présent article fournira une expérience pratique. Ici vous allez mettre en pratique ces connaissances en construisant vos propres fonctions. Tout au long, nous expliquerons également quelques détails supplémentaires concernant les fonctions. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Savoir-faire de base, une compréhension minimale HTML et CSS, <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas en JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions">Fonctions — blocs de code réutilisables</a>.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Fournir quelques pratiques de création de fonctions, et expliquer un peu plus les détails associés.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Savoir-faire de base, une compréhension minimale HTML et CSS, + <a href="/fr/docs/Learn/JavaScript/First_steps" + >premiers pas en JavaScript</a + >, + <a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions" + >Fonctions — blocs de code réutilisables</a + >. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Fournir quelques pratiques de création de fonctions, et expliquer un peu + plus les détails associés. + </td> + </tr> + </tbody> </table> -<h2 id="Apprentissage_actif_Construisons_une_fonction">Apprentissage actif : Construisons une fonction</h2> +## Apprentissage actif : Construisons une fonction -<p>La fonction que nous allons construire sera nommée <code>displayMessage()</code>. Elle affichera une boîte de message personnalisée sur une page web. Elle fonctionnera comme un substitut personnalisé de la fonction <a href="/fr/docs/Web/API/Window/alert">alert()</a> du navigateur. Vous avez déjà vu cela avant, mais nous allons simplement nous rafraîchir la mémoire — essayez le code qui suit dans la console JavaScript de votre navigateur, sur n'importe quelle page que vous aimez :</p> +La fonction que nous allons construire sera nommée `displayMessage()`. Elle affichera une boîte de message personnalisée sur une page web. Elle fonctionnera comme un substitut personnalisé de la fonction [alert()](/fr/docs/Web/API/Window/alert) du navigateur. Vous avez déjà vu cela avant, mais nous allons simplement nous rafraîchir la mémoire — essayez le code qui suit dans la console JavaScript de votre navigateur, sur n'importe quelle page que vous aimez : -<pre class="brush: js">alert('This is a message');</pre> +```js +alert('This is a message'); +``` -<p>La fonction prend un seul argument en paramètre — la chaîne de caractères qui est affichée dans la boîte d'alerte. Vous pouvez essayer de varier la syntaxe de la chaîne pour modifier le message.</p> +La fonction prend un seul argument en paramètre — la chaîne de caractères qui est affichée dans la boîte d'alerte. Vous pouvez essayer de varier la syntaxe de la chaîne pour modifier le message. -<p>La fonction <a href="/fr/docs/Web/API/Window/alert">alert()</a> est assez limitée : vous pouvez modifier le message, mais vous ne pouvez pas facilement faire varier autre chose, comme la couleur, une icône, ou autre chose. Nous en construirons une qui s'avérera plus amusante.</p> +La fonction [alert()](/fr/docs/Web/API/Window/alert) est assez limitée : vous pouvez modifier le message, mais vous ne pouvez pas facilement faire varier autre chose, comme la couleur, une icône, ou autre chose. Nous en construirons une qui s'avérera plus amusante. -<div class="note"> -<p><strong>Note :</strong> Cet exemple devrait fonctionner correctement dans tous les navigateurs modernes, mais elle pourrait avoir un comportement un peu plus inattendu dans un navigateur ancien. Nous recommandons donc de faire cet exercice dans un navigateur moderne tel que Firefox, Opera, ou Chrome.</p> -</div> +> **Note :** Cet exemple devrait fonctionner correctement dans tous les navigateurs modernes, mais elle pourrait avoir un comportement un peu plus inattendu dans un navigateur ancien. Nous recommandons donc de faire cet exercice dans un navigateur moderne tel que Firefox, Opera, ou Chrome. -<h2 id="La_fonction_de_base">La fonction de base</h2> +## La fonction de base -<p>Pour commencer, mettons en place une fonction de base.</p> +Pour commencer, mettons en place une fonction de base. -<div class="note"> -<p><strong>Note :</strong> Pour les conventions de nommage des fonctions, vous devez suivre les mêmes règles que les <a href="/fr/Learn/JavaScript/First_steps/Variables#An_aside_on_variable_naming_rules">conventions de noms de variables</a>. Ce qui est bien, c'est que vous pouvez les différencier — les noms de fonctions se terminent par des parenthèses, pas les variables.</p> -</div> +> **Note :** Pour les conventions de nommage des fonctions, vous devez suivre les mêmes règles que les [conventions de noms de variables](/fr/Learn/JavaScript/First_steps/Variables#An_aside_on_variable_naming_rules). Ce qui est bien, c'est que vous pouvez les différencier — les noms de fonctions se terminent par des parenthèses, pas les variables. + +1. Commencez par faire une copie locale du fichier [function-start.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-start.html). Vous pourrez voir que le code HTML est simple — l'élément body ne contient qu'un seul bouton. Nous avons également ajouté quelques règles CSS de base pour styliser la boîte de message personnalisée, et un élément {{htmlelement("script")}} pour écrire notre code JavaScript. +2. Ensuite, ajoutez le code ci-dessous à l'intérieur de l'élément `<script> `: + + ```js + function displayMessage() { + + } + ``` + + Nous commençons avec le mot-clé `function`, qui signifie que nous définissons une fonction. Celui-ci est suivi par le nom que nous voulons donner à notre fonction, des parenthèses et des accolades. Tous les paramètres que nous voulons donner à notre fonction vont à l'intérieur des parenthèses, et le code qui s'exécute lorsque nous appelons la fonction va à l'intérieur des accolades. + +3. Enfin, ajoutez le code suivant à l'intérieur des accolades : + + ```js + var html = document.querySelector('html'); -<ol> - <li>Commencez par faire une copie locale du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-start.html">function-start.html</a>. Vous pourrez voir que le code HTML est simple — l'élément body ne contient qu'un seul bouton. Nous avons également ajouté quelques règles CSS de base pour styliser la boîte de message personnalisée, et un élément {{htmlelement("script")}} pour écrire notre code JavaScript.</li> - <li>Ensuite, ajoutez le code ci-dessous à l'intérieur de l'élément <code><script> </code>: - <pre class="brush: js">function displayMessage() { + var panel = document.createElement('div'); + panel.setAttribute('class', 'msgBox'); + html.appendChild(panel); -}</pre> - Nous commençons avec le mot-clé <code>function</code>, qui signifie que nous définissons une fonction. Celui-ci est suivi par le nom que nous voulons donner à notre fonction, des parenthèses et des accolades. Tous les paramètres que nous voulons donner à notre fonction vont à l'intérieur des parenthèses, et le code qui s'exécute lorsque nous appelons la fonction va à l'intérieur des accolades.</li> - <li>Enfin, ajoutez le code suivant à l'intérieur des accolades : - <pre class="brush: js">var html = document.querySelector('html'); + var msg = document.createElement('p'); + msg.textContent = 'This is a message box'; + panel.appendChild(msg); + var closeBtn = document.createElement('button'); + closeBtn.textContent = 'x'; + panel.appendChild(closeBtn); + + closeBtn.onclick = function() { + panel.parentNode.removeChild(panel); + } + ``` + +Étant donné qu'il y a pas mal de code à analyser, allons-y pas à pas. + +La première ligne utilise une fonction de l'API DOM appelée {{domxref("document.querySelector()")}} pour sélectionner l'élément {{htmlelement("html")}} et stocker une référence vers cet élément dans une variable appelée `html`, de façon à pouvoir l'utiliser plus tard : + +```js +var html = document.querySelector('html'); +``` + +La section suivante utilise une autre fonction de l'API DOM appelée {{domxref("Document.createElement()")}} pour créer un élément {{htmlelement("div")}} et stocker une référence vers lui dans une variable appelée `panel` (Dans la suite de l'article, nous parlerons simplement du panneau `<div>`.). Cet élément sera le conteneur extérieur de notre boîte de message. + +Puis, nous utilisons encore une autre fonction de l'API DOM appelée {{domxref("Element.setAttribute()")}} pour ajouter un attribut `class` à notre panneau qui aura pour valeur `msgBox`. Ceci rendra plus facile la mise en forme de l'élément — si vous regardez le CSS de la page, vous verrez que nous utilisons un sélecteur de classe `.msgBox` dans le but de styliser la boîte de message ainsi que son contenu. + +Finallement, nous appelons une fonction du DOM nommée {{domxref("Node.appendChild()")}} sur la variable `html` créée précédemment, qui insère un élément, en tant qu'enfant, à l'intérieur d'un autre. Nous spécifions le panneau `<div>` (panel) comme l'enfant que nous voulons ajouter à l'intérieur de l'élément `<html>`. Nous avons besoin de le faire puisque l'élément que nous avons créé ne peut pas apparaître de lui-même sur la page — nous avons besoin de préciser où le mettre. + +```js var panel = document.createElement('div'); panel.setAttribute('class', 'msgBox'); html.appendChild(panel); +``` + +Les deux sections suivantes font usage des mêmes fonctions `createElement()` et `appendChild()` que nous avons déjà vu pour créer deux nouveaux éléments — l'un {{htmlelement("p")}} et l'autre {{htmlelement("button")}} — et pour les insèrer dans la page en tant qu'enfant du panneau `<div>`. On utilise leur propriété {{domxref("Node.textContent")}} — qui représente le contenu textuel d'un élément — pour insérer un message à l'intérieur du paragraphe, ainsi qu'un 'x' à l'intérieur du bouton. Ce bouton sera cliqué / activé quand l'utilisateur voudra fermer la boîte de message. +```js var msg = document.createElement('p'); msg.textContent = 'This is a message box'; panel.appendChild(msg); @@ -77,167 +126,185 @@ panel.appendChild(msg); var closeBtn = document.createElement('button'); closeBtn.textContent = 'x'; panel.appendChild(closeBtn); +``` +Finalement, nous utilisons un gestionnaire d'évènements {{domxref("GlobalEventHandlers.onclick")}} de sorte qu'un clic sur le bouton déclenche le bout de code chargé de supprimer la totalité du panneau de la page — c'est-à-dire fermer la boîte de message. + +Le gestionnaire `onclick` est une propriété disponible sur le bouton (en fait, sur n'importe quel élément de la page) qui pourra se voir transmettre une fonction en paramètre pour spécifier quel morceau de code sera déclenché quand le bouton sera cliqué. Vous en apprendrez bien plus dans notre article sur les évènements. Nous avons passé à notre gestionnaire `onclick` une fonction anonyme, qui contient le code exécuté quand le bouton est cliqué. L'instruction définie dans la fonction utilise la fonction de l'API DOM {{domxref("Node.removeChild()")}} pour indiquer que nous tenons à supprimer un élément enfant spécifique de l'élément HTML — dans notre cas le panneau `<div>`. + +```js closeBtn.onclick = function() { panel.parentNode.removeChild(panel); -}</pre> - </li> -</ol> +} +``` -<p>Étant donné qu'il y a pas mal de code à analyser, allons-y pas à pas.</p> +Au final, l'intégralité du bloc de code génère un bloc de code HTML et l'insère dans la page, ce qui ressemble à ça : -<p>La première ligne utilise une fonction de l'API DOM appelée {{domxref("document.querySelector()")}} pour sélectionner l'élément {{htmlelement("html")}} et stocker une référence vers cet élément dans une variable appelée <code>html</code>, de façon à pouvoir l'utiliser plus tard :</p> +```html +<div class="msgBox"> + <p>This is a message box</p> + <button>x</button> +</div> +``` -<pre class="brush: js">var html = document.querySelector('html');</pre> +Ça nous a fait beaucoup de code à passer en revue — ne vous inquiétez pas trop si vous ne vous souvenez pas exactement de comment chaque instruction fonctionne ! Bien que la partie principale sur laquelle nous voulions mettre l'accent ici est la structure de la fonction et son utilisation, nous avons voulu montrer quelque chose d'intéressant pour mettre en valeur cet exemple. -<p>La section suivante utilise une autre fonction de l'API DOM appelée {{domxref("Document.createElement()")}} pour créer un élément {{htmlelement("div")}} et stocker une référence vers lui dans une variable appelée <code>panel</code> (Dans la suite de l'article, nous parlerons simplement du panneau <code><div></code>.). Cet élément sera le conteneur extérieur de notre boîte de message.</p> +## Appeler la fonction -<p>Puis, nous utilisons encore une autre fonction de l'API DOM appelée {{domxref("Element.setAttribute()")}} pour ajouter un attribut <code>class</code> à notre panneau qui aura pour valeur <code>msgBox</code>. Ceci rendra plus facile la mise en forme de l'élément — si vous regardez le CSS de la page, vous verrez que nous utilisons un sélecteur de classe <code>.msgBox</code> dans le but de styliser la boîte de message ainsi que son contenu.</p> +À présent, nous avons notre fonction définie comme il faut dans notre balise `<script>`, mais il ne se passera rien si on laisse les choses en l'état. -<p>Finallement, nous appelons une fonction du DOM nommée {{domxref("Node.appendChild()")}} sur la variable <code>html</code> créée précédemment, qui insère un élément, en tant qu'enfant, à l'intérieur d'un autre. Nous spécifions le panneau <code><div></code> (panel) comme l'enfant que nous voulons ajouter à l'intérieur de l'élément <code><html></code>. Nous avons besoin de le faire puisque l'élément que nous avons créé ne peut pas apparaître de lui-même sur la page — nous avons besoin de préciser où le mettre.</p> +1. Ajoutez la ligne suivante au-dessous de votre fonction pour l'appeler : -<pre class="brush: js">var panel = document.createElement('div'); -panel.setAttribute('class', 'msgBox'); -html.appendChild(panel);</pre> + ```js + displayMessage(); + ``` -<p>Les deux sections suivantes font usage des mêmes fonctions <code>createElement()</code> et <code>appendChild()</code> que nous avons déjà vu pour créer deux nouveaux éléments — l'un {{htmlelement("p")}} et l'autre {{htmlelement("button")}} — et pour les insèrer dans la page en tant qu'enfant du panneau <code><div></code>. On utilise leur propriété {{domxref("Node.textContent")}} — qui représente le contenu textuel d'un élément — pour insérer un message à l'intérieur du paragraphe, ainsi qu'un 'x' à l'intérieur du bouton. Ce bouton sera cliqué / activé quand l'utilisateur voudra fermer la boîte de message.</p> + Cette ligne appelle la fonction en la faisant fonctionner immédiatement. Lorsque vous enregistrez votre code et rechargez la page dans le navigateur, vous voyez la petite boîte de message apparaître immédiatement, une seule fois. Après tout, nous ne l'appelons bien qu'une fois. -<pre class="brush: js">var msg = document.createElement('p'); -msg.textContent = 'This is a message box'; -panel.appendChild(msg); +2. Maintenant, ouvrez vos outils de développement sur la page d'exemple, allez à la console JavaScript et tapez-y la ligne à nouveau, vous verrez qu'elle apparaît encore une fois ! C'est génial, nous avons maintenant une fonction réutilisable que nous pouvons appeler chaque fois que nous le voulons. -var closeBtn = document.createElement('button'); -closeBtn.textContent = 'x'; -panel.appendChild(closeBtn);</pre> + Cela dit, nous voulons probablement qu'elle apparaisse en réponse aux actions de l'utilisateur ou du système. Dans une application réelle, une telle boîte de message serait probablement appelée en réponse à de nouvelles données disponibles, si une erreur s'est produite, si l'utilisateur essaie de supprimer son profil ("Êtes vous sûr de vouloir réaliser cette action ?"), ou encore si l'utilisateur ajoute un nouveau contact et que l'opération se termine avec succès, etc. -<p>Finalement, nous utilisons un gestionnaire d'évènements {{domxref("GlobalEventHandlers.onclick")}} de sorte qu'un clic sur le bouton déclenche le bout de code chargé de supprimer la totalité du panneau de la page — c'est-à-dire fermer la boîte de message.</p> + Dans cette démo, nous faisons apparaître le message quand l'utilisateur clique sur le bouton. -<p>Le gestionnaire <code>onclick</code> est une propriété disponible sur le bouton (en fait, sur n'importe quel élément de la page) qui pourra se voir transmettre une fonction en paramètre pour spécifier quel morceau de code sera déclenché quand le bouton sera cliqué. Vous en apprendrez bien plus dans notre article sur les évènements. Nous avons passé à notre gestionnaire <code>onclick</code> une fonction anonyme, qui contient le code exécuté quand le bouton est cliqué. L'instruction définie dans la fonction utilise la fonction de l'API DOM {{domxref("Node.removeChild()")}} pour indiquer que nous tenons à supprimer un élément enfant spécifique de l'élément HTML — dans notre cas le panneau <code><div></code>.</p> +3. Supprimez la ligne précédente que vous avez ajoutée. +4. Ensuite, vous sélectionnerez le bouton et stockerez une référence vers celui-ci dans une variable. Ajoutez la ligne suivante à votre code, au-dessus de la définition de fonction : -<pre class="brush: js">closeBtn.onclick = function() { - panel.parentNode.removeChild(panel); -}</pre> - -<p>Au final, l'intégralité du bloc de code génère un bloc de code HTML et l'insère dans la page, ce qui ressemble à ça :</p> - -<pre class="brush: html"><div class="msgBox"> - <p>This is a message box</p> - <button>x</button> -</div></pre> - -<p>Ça nous a fait beaucoup de code à passer en revue — ne vous inquiétez pas trop si vous ne vous souvenez pas exactement de comment chaque instruction fonctionne ! Bien que la partie principale sur laquelle nous voulions mettre l'accent ici est la structure de la fonction et son utilisation, nous avons voulu montrer quelque chose d'intéressant pour mettre en valeur cet exemple.</p> - -<h2 id="Appeler_la_fonction">Appeler la fonction</h2> - -<p>À présent, nous avons notre fonction définie comme il faut dans notre balise <code><script></code>, mais il ne se passera rien si on laisse les choses en l'état.</p> - -<ol> - <li>Ajoutez la ligne suivante au-dessous de votre fonction pour l'appeler : - <pre class="brush: js">displayMessage();</pre> - Cette ligne appelle la fonction en la faisant fonctionner immédiatement. Lorsque vous enregistrez votre code et rechargez la page dans le navigateur, vous voyez la petite boîte de message apparaître immédiatement, une seule fois. Après tout, nous ne l'appelons bien qu'une fois.</li> - <li> - <p>Maintenant, ouvrez vos outils de développement sur la page d'exemple, allez à la console JavaScript et tapez-y la ligne à nouveau, vous verrez qu'elle apparaît encore une fois ! C'est génial, nous avons maintenant une fonction réutilisable que nous pouvons appeler chaque fois que nous le voulons.</p> - - <p>Cela dit, nous voulons probablement qu'elle apparaisse en réponse aux actions de l'utilisateur ou du système. Dans une application réelle, une telle boîte de message serait probablement appelée en réponse à de nouvelles données disponibles, si une erreur s'est produite, si l'utilisateur essaie de supprimer son profil ("Êtes vous sûr de vouloir réaliser cette action ?"), ou encore si l'utilisateur ajoute un nouveau contact et que l'opération se termine avec succès, etc.</p> - - <p>Dans cette démo, nous faisons apparaître le message quand l'utilisateur clique sur le bouton.</p> - </li> - <li>Supprimez la ligne précédente que vous avez ajoutée.</li> - <li>Ensuite, vous sélectionnerez le bouton et stockerez une référence vers celui-ci dans une variable. Ajoutez la ligne suivante à votre code, au-dessus de la définition de fonction : - <pre class="brush: js">var btn = document.querySelector('button');</pre> - </li> - <li>Enfin, ajoutez la ligne suivante à la précédente : - <pre class="brush: js">btn.onclick = displayMessage;</pre> - D'une manière similaire à notre ligne <code>closeBtn.onclick...</code> à l'intérieur de la fonction, ici, nous appelons un certain code en réponse à un clic sur un bouton. Mais dans ce cas, au lieu d'appeler une fonction anonyme contenant du code, nous appelons directement notre nom de fonction.</li> - <li>Essayez d'enregistrer et de rafraîchir la page, maintenant vous devriez voir la boîte de message s'afficher lorsque vous cliquez sur le bouton.</li> -</ol> - -<p>Vous vous demandez peut-être pourquoi nous n'avons pas inclus les parenthèses après le nom de la fonction. C'est parce que nous ne voulons pas appeler la fonction immédiatement, seulement après que le bouton aura été cliqué. Si vous modifiez la ligne pour :</p> - -<pre class="brush: js">btn.onclick = displayMessage();</pre> - -<p>Enregistrez et rafraîchissez la page, vous verrez que la boîte de message apparaît sans que le bouton ait été cliqué ! Dans ce contexte, les parenthèses sont parfois appelées "opérateur d'appel / invocation de fonction". Vous ne les utilisez que lorsque vous souhaitez exécuter la fonction immédiatement dans la portée actuelle. Dans le même ordre d'idée, le code à l'intérieur de la fonction anonyme n'est pas exécuté immédiatement, car il se trouve à l'intérieur de la portée de la fonction.</p> - -<p>Si vous avez essayé la dernière expérimentation, assurez-vous d'annuler la dernière modification avant de poursuivre.</p> - -<h2 id="Améliorer_la_fonction_à_laide_de_paramètres">Améliorer la fonction à l'aide de paramètres</h2> - -<p>En l'état, la fonction n'est pas très utile — on ne veut pas montrer le même message par défaut à chaque fois. Améliorons la en ajoutant quelques paramètres, ils permettront d'appeler la fonction avec différentes options.</p> - -<ol> - <li>Premièrement, mettons à jour la première ligne : - <pre class="brush: js">function displayMessage() {</pre> - par : - - <pre class="brush: js">function displayMessage(msgText, msgType) {</pre> - Maintenant, quand nous appelons la fonction, nous pouvons fournir deux valeurs de variables entre les parenthèses : une pour spécifier le message à afficher dans la boîte, l'autre pour le type de message.</li> - <li>Pour faire usage du premier paramètre, mettez à jour la ligne suivante à l'intérieur de votre fonction : - <pre class="brush: js">msg.textContent = 'This is a message box';</pre> - avec : - - <pre class="brush: js">msg.textContent = msgText;</pre> - </li> - <li>Vous devez maintenant mettre à jour votre appel de fonction pour inclure un texte de message mis à jour. Modifiez la ligne suivante : - <pre class="brush: js">btn.onclick = displayMessage;</pre> - par ce bloc : - - <pre class="brush: js">btn.onclick = function() { - displayMessage('Woo, this is a different message!'); -};</pre> - Si nous voulons spécifier des paramètres à l'intérieur des parenthèses pour la fonction que nous appelons, alors nous ne pouvons pas l'appeler directement — nous avons besoin de la mettre à l'intérieur d'une fonction anonyme de sorte qu'elle n'est pas dans la portée immédiate et n'est donc pas appelée immédiatement. Maintenant, elle ne sera pas appelée tant que le bouton ne sera pas cliqué.</li> - <li>Rechargez et essayez le code à nouveau et vous verrez qu'il fonctionne toujours très bien, sauf que maintenant vous pouvez également modifier le message à l'intérieur du paramètre pour obtenir des messages différents affichés dans la boîte !</li> -</ol> - -<h3 id="Un_paramètre_plus_complexe">Un paramètre plus complexe</h3> - -<p>Passons au paramètre suivant. Celui-ci va demander un peu plus de travail — selon la valeur du paramètre <code>msgType</code>, la fonction affichera une icône et une couleur d'arrière-plan différentes.</p> - -<ol> - <li>Tout d'abord, téléchargez les icônes nécessaires à cet exercice (<a href="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/warning.png">warning</a> et <a href="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/chat.png">chat</a>) depuis GitHub. Enregistrez-les dans un nouveau dossier appelé <code>icons</code> dans le même répertoire que votre fichier HTML. - - <div class="note"> - <p><strong>Note :</strong> icônes <a href="https://www.iconfinder.com/icons/1031466/alarm_alert_error_warning_icon">warning</a> et <a href="https://www.iconfinder.com/icons/1031441/chat_message_text_icon">chat</a> trouvés sur iconfinder.com, et créés par <a href="https://www.iconfinder.com/nazarr">Nazarrudin Ansyari</a>. Merci !</p></div> - </li> - <li>Ensuite, trouvez le CSS à l'intérieur de votre fichier HTML. Nous ferons quelques changements pour faire place aux icônes. Tout d'abord, mettez à jour la largeur <code>.msgBox</code> en changeant : - <pre class="brush: css">width: 200px;</pre> - par : - - <pre class="brush: css">width: 242px;</pre> - </li> - <li>Ensuite, ajoutez les lignes à l'intérieur de la règle CSS <code>.msgBox p { ... }</code> : - <pre class="brush: css">padding-left: 82px; -background-position: 25px center; -background-repeat: no-repeat;</pre> - </li> - <li>Maintenant, nous devons ajouter du code à notre fonction <code>displayMessage()</code> pour gérer l'affichage de l'icône. Ajoutez le bloc suivant juste au dessus de l'accolade fermante "<code>}</code>" de votre fonction : - <pre class="brush: js">if (msgType === 'warning') { - msg.style.backgroundImage = 'url(icons/warning.png)'; - panel.style.backgroundColor = 'red'; -} else if (msgType === 'chat') { - msg.style.backgroundImage = 'url(icons/chat.png)'; - panel.style.backgroundColor = 'aqua'; -} else { - msg.style.paddingLeft = '20px'; -}</pre> - Ici, quand <code>msgType</code> a la valeur <code>'warning'</code>, l'icône d'avertissement est affichée et le fond du panneau prend la couleur rouge. Si <code>msgType</code> a la valeur <code>'chat'</code>, l'icône de chat est affichée et l'arrière-plan du panneau est bleu. Si le paramètre <code>msgType</code> n'a pas de valeur du tout (ou s'il a une valeur totalement différente), alors la partie du code contenue dans <code>else { ... }</code> est exécutée : le paragraphe prend un padding par défaut et il n'y a ni icône ni couleur d'arrière-plan. En fait, on fournit un état par défaut si aucun paramètre <code>msgType</code> n'est fourni, ce qui signifie qu'il s'agit d'un paramètre facultatif !</li> - <li>Nous allons tester notre fonction mise à jour, essayez de mettre à jour l'appel <code>displayMessage()</code> : - <pre class="brush: js">displayMessage('Woo, this is a different message!');</pre> - par soit l'un ou l'autre : - - <pre class="brush: js">displayMessage('Your inbox is almost full — delete some mails', 'warning'); -displayMessage('Brian: Hi there, how are you today?','chat');</pre> - Vous pouvez voir à quel point notre petite (plus tant que cela maintenant) fonction est devenue utile :</li> -</ol> - -<div class="note"> -<p><strong>Note :</strong> Si vous avez des difficultés à mettre en œuvre cet exemple, n'hésitez pas à verifier votre code par rapport à la <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html">version définitive sur GitHub</a> (aussi, vous pouvez tester la <a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-stage-4.html">démo</a>), ou nous demander de l'aide.</p> -</div> + ```js + var btn = document.querySelector('button'); + ``` + +5. Enfin, ajoutez la ligne suivante à la précédente : + + ```js + btn.onclick = displayMessage; + ``` + + D'une manière similaire à notre ligne `closeBtn.onclick...` à l'intérieur de la fonction, ici, nous appelons un certain code en réponse à un clic sur un bouton. Mais dans ce cas, au lieu d'appeler une fonction anonyme contenant du code, nous appelons directement notre nom de fonction. + +6. Essayez d'enregistrer et de rafraîchir la page, maintenant vous devriez voir la boîte de message s'afficher lorsque vous cliquez sur le bouton. + +Vous vous demandez peut-être pourquoi nous n'avons pas inclus les parenthèses après le nom de la fonction. C'est parce que nous ne voulons pas appeler la fonction immédiatement, seulement après que le bouton aura été cliqué. Si vous modifiez la ligne pour : + +```js +btn.onclick = displayMessage(); +``` + +Enregistrez et rafraîchissez la page, vous verrez que la boîte de message apparaît sans que le bouton ait été cliqué ! Dans ce contexte, les parenthèses sont parfois appelées "opérateur d'appel / invocation de fonction". Vous ne les utilisez que lorsque vous souhaitez exécuter la fonction immédiatement dans la portée actuelle. Dans le même ordre d'idée, le code à l'intérieur de la fonction anonyme n'est pas exécuté immédiatement, car il se trouve à l'intérieur de la portée de la fonction. + +Si vous avez essayé la dernière expérimentation, assurez-vous d'annuler la dernière modification avant de poursuivre. + +## Améliorer la fonction à l'aide de paramètres + +En l'état, la fonction n'est pas très utile — on ne veut pas montrer le même message par défaut à chaque fois. Améliorons la en ajoutant quelques paramètres, ils permettront d'appeler la fonction avec différentes options. + +1. Premièrement, mettons à jour la première ligne : + + ```js + function displayMessage() { + ``` + + par : + + ```js + function displayMessage(msgText, msgType) { + ``` + + Maintenant, quand nous appelons la fonction, nous pouvons fournir deux valeurs de variables entre les parenthèses : une pour spécifier le message à afficher dans la boîte, l'autre pour le type de message. + +2. Pour faire usage du premier paramètre, mettez à jour la ligne suivante à l'intérieur de votre fonction : + + ```js + msg.textContent = 'This is a message box'; + ``` + + avec : + + ```js + msg.textContent = msgText; + ``` + +3. Vous devez maintenant mettre à jour votre appel de fonction pour inclure un texte de message mis à jour. Modifiez la ligne suivante : + + ```js + btn.onclick = displayMessage; + ``` + + par ce bloc : + + ```js + btn.onclick = function() { + displayMessage('Woo, this is a different message!'); + }; + ``` + + Si nous voulons spécifier des paramètres à l'intérieur des parenthèses pour la fonction que nous appelons, alors nous ne pouvons pas l'appeler directement — nous avons besoin de la mettre à l'intérieur d'une fonction anonyme de sorte qu'elle n'est pas dans la portée immédiate et n'est donc pas appelée immédiatement. Maintenant, elle ne sera pas appelée tant que le bouton ne sera pas cliqué. + +4. Rechargez et essayez le code à nouveau et vous verrez qu'il fonctionne toujours très bien, sauf que maintenant vous pouvez également modifier le message à l'intérieur du paramètre pour obtenir des messages différents affichés dans la boîte ! + +### Un paramètre plus complexe + +Passons au paramètre suivant. Celui-ci va demander un peu plus de travail — selon la valeur du paramètre `msgType`, la fonction affichera une icône et une couleur d'arrière-plan différentes. + +1. Tout d'abord, téléchargez les icônes nécessaires à cet exercice ([warning](https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/warning.png) et [chat](https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/chat.png)) depuis GitHub. Enregistrez-les dans un nouveau dossier appelé `icons` dans le même répertoire que votre fichier HTML. + + > **Note :** icônes [warning](https://www.iconfinder.com/icons/1031466/alarm_alert_error_warning_icon) et [chat](https://www.iconfinder.com/icons/1031441/chat_message_text_icon) trouvés sur iconfinder.com, et créés par [Nazarrudin Ansyari](https://www.iconfinder.com/nazarr). Merci ! + +2. Ensuite, trouvez le CSS à l'intérieur de votre fichier HTML. Nous ferons quelques changements pour faire place aux icônes. Tout d'abord, mettez à jour la largeur `.msgBox` en changeant : + + ```css + width: 200px; + ``` + + par : + + ```css + width: 242px; + ``` + +3. Ensuite, ajoutez les lignes à l'intérieur de la règle CSS `.msgBox p { ... }` : + + ```css + padding-left: 82px; + background-position: 25px center; + background-repeat: no-repeat; + ``` + +4. Maintenant, nous devons ajouter du code à notre fonction `displayMessage()` pour gérer l'affichage de l'icône. Ajoutez le bloc suivant juste au dessus de l'accolade fermante "`}`" de votre fonction : + + ```js + if (msgType === 'warning') { + msg.style.backgroundImage = 'url(icons/warning.png)'; + panel.style.backgroundColor = 'red'; + } else if (msgType === 'chat') { + msg.style.backgroundImage = 'url(icons/chat.png)'; + panel.style.backgroundColor = 'aqua'; + } else { + msg.style.paddingLeft = '20px'; + } + ``` + + Ici, quand `msgType` a la valeur `'warning'`, l'icône d'avertissement est affichée et le fond du panneau prend la couleur rouge. Si `msgType` a la valeur `'chat'`, l'icône de chat est affichée et l'arrière-plan du panneau est bleu. Si le paramètre `msgType` n'a pas de valeur du tout (ou s'il a une valeur totalement différente), alors la partie du code contenue dans `else { ... }` est exécutée : le paragraphe prend un padding par défaut et il n'y a ni icône ni couleur d'arrière-plan. En fait, on fournit un état par défaut si aucun paramètre `msgType` n'est fourni, ce qui signifie qu'il s'agit d'un paramètre facultatif ! + +5. Nous allons tester notre fonction mise à jour, essayez de mettre à jour l'appel `displayMessage()` : + + ```js + displayMessage('Woo, this is a different message!'); + ``` + + par soit l'un ou l'autre : + + ```js + displayMessage('Your inbox is almost full — delete some mails', 'warning'); + displayMessage('Brian: Hi there, how are you today?','chat'); + ``` + + Vous pouvez voir à quel point notre petite (plus tant que cela maintenant) fonction est devenue utile : -<h2 id="Conclusion">Conclusion</h2> +> **Note :** Si vous avez des difficultés à mettre en œuvre cet exemple, n'hésitez pas à verifier votre code par rapport à la [version définitive sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html) (aussi, vous pouvez tester la [démo](http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-stage-4.html)), ou nous demander de l'aide. -<p>Vous êtes venu à bout de cette activité, félicitations ! Cet article vous a amené à travers tout le processus de construction d'une fonction pratique personnalisée, qui avec un peu plus de travail pourrait être transposée dans un projet réel. Dans l'article suivant, nous allons conclure l'apprentissage des fonctions en expliquant un autre concept connexe essentiel — les valeurs de retour.</p> +## Conclusion -<ul> -</ul> +Vous êtes venu à bout de cette activité, félicitations ! Cet article vous a amené à travers tout le processus de construction d'une fonction pratique personnalisée, qui avec un peu plus de travail pourrait être transposée dans un projet réel. Dans l'article suivant, nous allons conclure l'apprentissage des fonctions en expliquant un autre concept connexe essentiel — les valeurs de retour. -<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}} diff --git a/files/fr/learn/javascript/building_blocks/conditionals/index.md b/files/fr/learn/javascript/building_blocks/conditionals/index.md index 5a6a89cc13..cfa97937f9 100644 --- a/files/fr/learn/javascript/building_blocks/conditionals/index.md +++ b/files/fr/learn/javascript/building_blocks/conditionals/index.md @@ -15,112 +15,122 @@ tags: translation_of: Learn/JavaScript/Building_blocks/conditionals original_slug: Apprendre/JavaScript/Building_blocks/conditionals --- -<p>{{LearnSidebar}}</p> +{{LearnSidebar}} -<p>{{NextMenu("Apprendre/JavaScript/Building_blocks/Looping_code", "Apprendre/JavaScript/Building_blocks")}}</p> +{{NextMenu("Apprendre/JavaScript/Building_blocks/Looping_code", "Apprendre/JavaScript/Building_blocks")}} -<p>Dans tout langage de programmation, le code doit prendre des décisions et agir en fonction des différents paramètres. Par exemple dans un jeu, si le nombre de vies du joueur atteint 0, alors le jeu est terminé. Dans une application météo, si elle est consultée le matin, l'application montrera une image du lever de soleil ; l'application proposera des étoiles et la lune s'il fait nuit. Dans cet article nous allons découvrir comment ces instructions conditionnelles fonctionnent en JavaScript.</p> +Dans tout langage de programmation, le code doit prendre des décisions et agir en fonction des différents paramètres. Par exemple dans un jeu, si le nombre de vies du joueur atteint 0, alors le jeu est terminé. Dans une application météo, si elle est consultée le matin, l'application montrera une image du lever de soleil ; l'application proposera des étoiles et la lune s'il fait nuit. Dans cet article nous allons découvrir comment ces instructions conditionnelles fonctionnent en JavaScript. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Connaissances du vocabulaire informatique, compréhension des bases du HTML et des CSS, <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript</a>.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre comment utiliser les structures conditionnelles en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Connaissances du vocabulaire informatique, compréhension des bases du + HTML et des CSS, + <a href="/fr/docs/Learn/JavaScript/First_steps" + >Premiers pas en JavaScript</a + >. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Comprendre comment utiliser les structures conditionnelles en + JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Vous_laurez_à_une_condition_!..">Vous l'aurez à une condition !..</h2> +## Vous l'aurez à une condition !.. -<p>Les êtres humains (et d'autres animaux) prennent tout le temps des décisions qui affectent leur vie, de la plus insignifiante (« Est‑ce que je devrais prendre un biscuit ou deux ? ») à la plus importante (« Est‑ce que je dois rester dans mon pays natal et travailler à la ferme de mon père, ou déménager aux États-Unis et étudier l'astrophysique ? »)</p> +Les êtres humains (et d'autres animaux) prennent tout le temps des décisions qui affectent leur vie, de la plus insignifiante (« Est‑ce que je devrais prendre un biscuit ou deux ? ») à la plus importante (« Est‑ce que je dois rester dans mon pays natal et travailler à la ferme de mon père, ou déménager aux États-Unis et étudier l'astrophysique ? ») -<p>Les instructions conditionnelles nous permettent de représenter ce genre de prise de décision en JavaScript, du choix qui doit être fait (par ex. « un biscuit ou deux »), à la conséquence de ces choix (il se peut que la conséquence de « manger un biscuit » soit « avoir encore faim », et celle de « manger deux biscuits » soit « se sentir rassasié, mais se faire gronder par maman pour avoir mangé tous les biscuits ».)</p> +Les instructions conditionnelles nous permettent de représenter ce genre de prise de décision en JavaScript, du choix qui doit être fait (par ex. « un biscuit ou deux »), à la conséquence de ces choix (il se peut que la conséquence de « manger un biscuit » soit « avoir encore faim », et celle de « manger deux biscuits » soit « se sentir rassasié, mais se faire gronder par maman pour avoir mangé tous les biscuits ».) -<p><img alt="" src="cookie-choice-small.png"></p> + -<h2 id="Instruction_if_..._else">Instruction if ... else</h2> +## Instruction if ... else -<p>Intéressons nous de plus près à la forme la plus répandue d'instruction conditionnelle que vous utiliserez en JavaScript — la modeste <a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">instruction</a> <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">if ... else</a></code>.</p> +Intéressons nous de plus près à la forme la plus répandue d'instruction conditionnelle que vous utiliserez en JavaScript — la modeste [instruction](/fr/docs/Web/JavaScript/Reference/Instructions/if...else) [`if ... else`](/fr/docs/Web/JavaScript/Reference/Instructions/if...else). -<h3 id="Syntaxe_élémentaire_if_..._else">Syntaxe élémentaire if ... else</h3> +### Syntaxe élémentaire if ... else -<p>La syntaxe élémentaire de <code>if...else</code> ressemble à cela en {{glossary("pseudocode")}}:</p> +La syntaxe élémentaire de `if...else` ressemble à cela en {{glossary("pseudocode")}}: -<pre>if (condition) { - code à exécuter si la condition est true -} else { - sinon exécuter cet autre code à la place -}</pre> + if (condition) { + code à exécuter si la condition est true + } else { + sinon exécuter cet autre code à la place + } -<p>Ici nous avons:</p> +Ici nous avons: -<ol> - <li>Le mot‑clé <code>if</code> suivie de parenthèses.</li> - <li>Une condition à évaluer, placée entre les parenthèses (typiquement « cette valeur est‑elle plus grande que cet autre valeur ? » ou « cette valeur existe‑t‑elle ? »). Cette condition se servira des <a href="/fr/docs/Learn/JavaScript/First_steps/Math#Comparison_operators">opérateurs de comparaison</a> que nous avons étudié dans le précédent module, et renverra <code>true</code> ou <code>false</code>.</li> - <li>Une paire d'accolades, à l'intérieur de laquelle se trouve du code — cela peut être n'importe quel code voulu ; il sera exécuté seulement si la condition renvoie <code>true</code>.</li> - <li>Le mot‑clé <code>else</code>.</li> - <li>Une autre paire d'accolades, à l'intérieur de laquelle se trouve du code différent — tout code souhaité et il sera exécuté seulement si la condition ne renvoie pas <code>true</code>.</li> -</ol> +1. Le mot‑clé `if` suivie de parenthèses. +2. Une condition à évaluer, placée entre les parenthèses (typiquement « cette valeur est‑elle plus grande que cet autre valeur ? » ou « cette valeur existe‑t‑elle ? »). Cette condition se servira des [opérateurs de comparaison](/fr/docs/Learn/JavaScript/First_steps/Math#Comparison_operators) que nous avons étudié dans le précédent module, et renverra `true` ou `false`. +3. Une paire d'accolades, à l'intérieur de laquelle se trouve du code — cela peut être n'importe quel code voulu ; il sera exécuté seulement si la condition renvoie `true`. +4. Le mot‑clé `else`. +5. Une autre paire d'accolades, à l'intérieur de laquelle se trouve du code différent — tout code souhaité et il sera exécuté seulement si la condition ne renvoie pas `true`. -<p>Ce code est facile à lire pour une personne — il dit « <strong>si</strong> la <strong>condition</strong> renvoie <code>true</code>, exécuter le code A, <strong>sinon</strong> exécuter le code B ».</p> +Ce code est facile à lire pour une personne — il dit « **si** la **condition** renvoie `true`, exécuter le code A, **sinon** exécuter le code B ». -<p>Notez qu'il n'est pas nécessaire d'inclure une instruction <code>else</code> et le deuxième bloc entre accolades — le code suivant est aussi parfaitement correct :</p> +Notez qu'il n'est pas nécessaire d'inclure une instruction `else` et le deuxième bloc entre accolades — le code suivant est aussi parfaitement correct : -<pre>if (condition) { - code à exécuter si la condition est true -} + if (condition) { + code à exécuter si la condition est true + } -exécuter un autre code</pre> + exécuter un autre code -<p>Cependant, vous devez faire attention ici — dans ce cas, le deuxième bloc de code n'est pas controlé par l'instruction conditionnelle, donc il sera <strong>toujours</strong> exécuté, que la condition ait renvoyé <code>true</code> ou <code>false</code>. Ce n'est pas nécessairement une mauvaise chose, mais il se peut que ce ne soit pas ce que vous vouliez — le plus souvent vous voudrez exécuter un bloc de code <em>ou</em> l'autre, et non les deux.</p> +Cependant, vous devez faire attention ici — dans ce cas, le deuxième bloc de code n'est pas controlé par l'instruction conditionnelle, donc il sera **toujours** exécuté, que la condition ait renvoyé `true` ou `false`. Ce n'est pas nécessairement une mauvaise chose, mais il se peut que ce ne soit pas ce que vous vouliez — le plus souvent vous voudrez exécuter un bloc de code *ou* l'autre, et non les deux. -<p>Une dernière remarque, vous verrez quelques fois les instructions <code>if...else</code> écrites sans accolades, de manière abrégée, ainsi :</p> +Une dernière remarque, vous verrez quelques fois les instructions `if...else` écrites sans accolades, de manière abrégée, ainsi : -<pre>if (condition) code à exécuter si la condition est true -else exécute un autre code à la place</pre> + if (condition) code à exécuter si la condition est true + else exécute un autre code à la place -<p>Ce code est parfaitement valide, mais il n'est pas recommandé — il est nettement plus facile de lire le code et d'en déduire ce qui se passe si vous utilisez des accolades pour délimiter les blocs de code, des lignes séparées et des indentations.</p> +Ce code est parfaitement valide, mais il n'est pas recommandé — il est nettement plus facile de lire le code et d'en déduire ce qui se passe si vous utilisez des accolades pour délimiter les blocs de code, des lignes séparées et des indentations. -<h3 id="Un_exemple_concret">Un exemple concret</h3> +### Un exemple concret -<p>Pour mieux comprendre cette syntaxe, prenons un exemple concret. Imaginez un enfant à qui le père ou la mère demande de l'aide pour une tâche. Le parent pourrait dire « Mon chéri, si tu m'aides en allant faire les courses, je te donnerai un peu plus d'argent de poche pour que tu puisses t'acheter ce jouet que tu voulais ». En JavaScript, on pourrait le représenter de cette manière :</p> +Pour mieux comprendre cette syntaxe, prenons un exemple concret. Imaginez un enfant à qui le père ou la mère demande de l'aide pour une tâche. Le parent pourrait dire « Mon chéri, si tu m'aides en allant faire les courses, je te donnerai un peu plus d'argent de poche pour que tu puisses t'acheter ce jouet que tu voulais ». En JavaScript, on pourrait le représenter de cette manière : -<pre class="brush: js">let coursesFaites = false; +```js +let coursesFaites = false; if (coursesFaites === true) { let argentDePoche = 10; } else { let argentDePoche = 5; -}</pre> +} +``` -<p>Avec un tel code, la variable <code>coursesFaites</code> renvoie toujours <code>false</code>, imaginez la déception de ce pauvre enfant. Il ne tient qu'à nous de fournir un mécanisme pour que le parent assigne <code>true</code> à la variable <code>coursesFaites</code> si l'enfant a fait les courses.</p> +Avec un tel code, la variable `coursesFaites` renvoie toujours `false`, imaginez la déception de ce pauvre enfant. Il ne tient qu'à nous de fournir un mécanisme pour que le parent assigne `true` à la variable `coursesFaites` si l'enfant a fait les courses. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez voir une <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/allowance-updater.html">version plus complète de cet exemple sur GitHub</a> (ainsi qu'en <a href="http://mdn.github.io/learning-area/javascript/building-blocks/allowance-updater.html">version live</a>.)</p> -</div> +> **Note :** Vous pouvez voir une [version plus complète de cet exemple sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/allowance-updater.html) (ainsi qu'en [version live](http://mdn.github.io/learning-area/javascript/building-blocks/allowance-updater.html).) -<h3 id="else_if">else if</h3> +### else if -<p>Il n'y a qu'une alternative dans l'exemple précédent — mais qu'en est‑il si l'on souhaite plus de choix ?</p> +Il n'y a qu'une alternative dans l'exemple précédent — mais qu'en est‑il si l'on souhaite plus de choix ? -<p>Il existe un moyen d'enchaîner des choix / résultats supplémentaires à <code>if...else</code> — en utilisant <code>else if</code> entre. Chaque choix supplémentaire nécessite un bloc additionnel à placer entre <code>if() { ... }</code> et <code>else { ... }</code> — regardez l'exemple suivant plus élaboré, qui pourrait faire partie d'une simple application de prévisions météo:</p> +Il existe un moyen d'enchaîner des choix / résultats supplémentaires à `if...else` — en utilisant `else if` entre. Chaque choix supplémentaire nécessite un bloc additionnel à placer entre `if() { ... }` et `else { ... }` — regardez l'exemple suivant plus élaboré, qui pourrait faire partie d'une simple application de prévisions météo: -<pre class="brush: html"><label for="weather">Select the weather type today: </label> -<select id="weather"> - <option value="">--Make a choice--</option> - <option value="sunny">Sunny</option> - <option value="rainy">Rainy</option> - <option value="snowing">Snowing</option> - <option value="overcast">Overcast</option> -</select> +```html +<label for="weather">Select the weather type today: </label> +<select id="weather"> + <option value="">--Make a choice--</option> + <option value="sunny">Sunny</option> + <option value="rainy">Rainy</option> + <option value="snowing">Snowing</option> + <option value="overcast">Overcast</option> +</select> -<p></p></pre> +<p></p> +``` -<pre class="brush: js">const select = document.querySelector('select'); +```js +const select = document.querySelector('select'); const para = document.querySelector('p'); select.addEventListener('change', setWeather); @@ -139,178 +149,188 @@ function setWeather() { } else { para.textContent = ''; } -}</pre> +} +``` -<p>{{ EmbedLiveSample('else_if', '100%', 100) }}</p> +{{ EmbedLiveSample('else_if', '100%', 100) }} -<ol> - <li>Ici nous avons l'élément HTML {{htmlelement("select")}} nous permettant de sélectionner divers choix de temps et un simple paragraphe.</li> - <li>Dans le JavaScript, nous conservons une référence aussi bien à l'élément {{htmlelement("select")}} qu'à l'élément {{htmlelement("p")}}, et ajoutons un écouteur d'évènement à l'élément <code><select></code> de sorte que la fonction <code>setWeather()</code> soit exécutée quand sa valeur change.</li> - <li>Quand cette fonction est exécutée, nous commençons par assigner à la variable <code>choice</code> la valeur actuellement sélectionnée dans l'élément <code><select></code>. Nous utilisons ensuite une instruction conditionnelle pour montrer différents textes dans le paragraphe en fonction de la valeur de <code>choice</code>. Remarquez comment toutes les conditions sont testées avec des blocs <code>else if() {...}</code>, mis à part le tout premier testé avec un <code>bloc if() {...}</code>.</li> - <li>Le tout dernier choix, à l'intérieur du bloc <code>else {...}</code>, est simplement une option de "secours" — le code qui s'y trouve ne sera exécuté que si aucune des conditions n'est <code>true</code>. Dans ce cas, il faut vider le texte du paragraphe si rien n'est sélectionné, par exemple si un utilisateur décide de resélectionner le texte à substituer « --Choisir-- » présenté au début.</li> -</ol> +1. Ici nous avons l'élément HTML {{htmlelement("select")}} nous permettant de sélectionner divers choix de temps et un simple paragraphe. +2. Dans le JavaScript, nous conservons une référence aussi bien à l'élément {{htmlelement("select")}} qu'à l'élément {{htmlelement("p")}}, et ajoutons un écouteur d'évènement à l'élément `<select>` de sorte que la fonction `setWeather()` soit exécutée quand sa valeur change. +3. Quand cette fonction est exécutée, nous commençons par assigner à la variable `choice` la valeur actuellement sélectionnée dans l'élément `<select>`. Nous utilisons ensuite une instruction conditionnelle pour montrer différents textes dans le paragraphe en fonction de la valeur de `choice`. Remarquez comment toutes les conditions sont testées avec des blocs `else if() {...}`, mis à part le tout premier testé avec un `bloc if() {...}`. +4. Le tout dernier choix, à l'intérieur du bloc `else {...}`, est simplement une option de "secours" — le code qui s'y trouve ne sera exécuté que si aucune des conditions n'est `true`. Dans ce cas, il faut vider le texte du paragraphe si rien n'est sélectionné, par exemple si un utilisateur décide de resélectionner le texte à substituer « --Choisir-- » présenté au début. -<div class="note"> -<p><strong>Note :</strong> Vous trouverez également <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-else-if.html">cet exemple sur GitHub</a> (ainsi qu'en <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-else-if.html">version live</a> ici.)</p> -</div> +> **Note :** Vous trouverez également [cet exemple sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-else-if.html) (ainsi qu'en [version live](http://mdn.github.io/learning-area/javascript/building-blocks/simple-else-if.html) ici.) -<h3 id="Une_note_sur_les_opérateurs_de_comparaison">Une note sur les opérateurs de comparaison</h3> +### Une note sur les opérateurs de comparaison -<p>Les opérateurs de comparaison sont utilisés pour tester les conditions dans nos instructions conditionnelles. Nous avons d'abord regardé les opérateurs de comparaison dans notre <a href="/fr/docs/Learn/JavaScript/First_steps/Math#Opérateurs_de_comparaison">Mathématiques de base en JavaScript — nombres et opérateurs</a> article. Nos choix sont :</p> +Les opérateurs de comparaison sont utilisés pour tester les conditions dans nos instructions conditionnelles. Nous avons d'abord regardé les opérateurs de comparaison dans notre [Mathématiques de base en JavaScript — nombres et opérateurs](/fr/docs/Learn/JavaScript/First_steps/Math#Opérateurs_de_comparaison) article. Nos choix sont : -<ul> - <li><code>===</code> et <code>!==</code> — teste si une valeur est identique ou non à une autre.</li> - <li><code><</code> and <code>></code> —teste si une valeur est inférieure ou non à une autre.</li> - <li><code><=</code> and <code>>=</code> — teste si une valeur est inférieur ou égal, ou égal à, ou supérieur ou égal à une autre.</li> -</ul> +- `===` et `!==` — teste si une valeur est identique ou non à une autre. +- `<` and `>` —teste si une valeur est inférieure ou non à une autre. +- `<=` and `>=` — teste si une valeur est inférieur ou égal, ou égal à, ou supérieur ou égal à une autre. -<div class="note"> -<p><strong>Note :</strong> Revoyez le contenu du lien précédent si vous voulez vous rafraîchir la mémoire.</p> -</div> +> **Note :** Revoyez le contenu du lien précédent si vous voulez vous rafraîchir la mémoire. -<p>Nous souhaitons mentionner à propos des tests des valeurs booléennes (<code>true</code>/<code>false</code>) un modèle courant que vous rencontrerez souvent. Toute valeur autre que <code>false</code>, <code>undefined</code>, <code>null</code>, <code>0</code>, <code>NaN</code> ou une chaîne vide (<code>''</code>) renvoie <code>true</code> lorsqu'elle est testée dans une structure conditionnelle, vous pouvez donc simplement utiliser un nom de variable pour tester si elle est <code>true</code>, ou même si elle existe (c'est-à-dire si elle n'est pas <code>undefined</code>).<br> - Par exemple :</p> +Nous souhaitons mentionner à propos des tests des valeurs booléennes (`true`/`false`) un modèle courant que vous rencontrerez souvent. Toute valeur autre que `false`, `undefined`, `null`, `0`, `NaN` ou une chaîne vide (`''`) renvoie `true` lorsqu'elle est testée dans une structure conditionnelle, vous pouvez donc simplement utiliser un nom de variable pour tester si elle est `true`, ou même si elle existe (c'est-à-dire si elle n'est pas `undefined`). +Par exemple : -<pre class="brush: js">const fromage = 'Comté'; +```js +const fromage = 'Comté'; if (fromage) { console.log('Ouaips ! Du fromage pour mettre sur un toast.'); } else { console.log('Pas de fromage sur le toast pour vous aujourd\'hui.'); -}</pre> +} +``` -<p>Et, revenant à notre exemple précédent sur l'enfant rendant service à ses parents, vous pouvez l'écrire ainsi :</p> +Et, revenant à notre exemple précédent sur l'enfant rendant service à ses parents, vous pouvez l'écrire ainsi : -<pre class="brush: js">let coursesFaites = false; +```js +let coursesFaites = false; if (coursesFaites) { // pas besoin d'écrire explicitement '=== true' let argentDePoche = 10; } else { let argentDePoche = 5; -}</pre> +} +``` -<h3 id="if_..._else_imbriqué"> if ... else imbriqué</h3> +### if ... else imbriqué -<p>Il est parfaitement correct d'ajouter une déclaration <code>if...else</code> à l'intérieur d'une autre — pour les imbriquer. Par exemple, nous pourrions mettre à jour notre application de prévisions météo pour montrer un autre ensemble de choix en fonction de la température :</p> +Il est parfaitement correct d'ajouter une déclaration `if...else` à l'intérieur d'une autre — pour les imbriquer. Par exemple, nous pourrions mettre à jour notre application de prévisions météo pour montrer un autre ensemble de choix en fonction de la température : -<pre class="brush: js">if (choice === 'sunny') { - if (temperature < 86) { +```js +if (choice === 'sunny') { + if (temperature < 86) { para.textContent = 'Il fait ' + temperature + ' degrés dehors — beau et ensoleillé. Allez à la plage ou au parc et achetez une crème glacée.'; - } else if (temperature >= 86) { + } else if (temperature >= 86) { para.textContent = 'Il fait ' + temperature + ' degrés dehors — VRAIMENT CHAUD ! si vous voulez sortir, n\'oubliez pas de mettre de la crème solaire.'; } -}</pre> +} +``` -<p>Même si tout le code fonctionne ensemble, chaque déclaration <code>if...else</code> fonctionne indépendamment de l'autre.</p> +Même si tout le code fonctionne ensemble, chaque déclaration `if...else` fonctionne indépendamment de l'autre. -<h3 id="Opérateurs_logiques_AND_OR_et_NOT">Opérateurs logiques AND, OR et NOT</h3> +### Opérateurs logiques AND, OR et NOT -<p>Si vous voulez tester plusieurs conditions sans imbriquer des instructions <code>if...else</code> , les <a href="/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Op%C3%A9rateurs_logiques">opérateurs logiques</a> pourront vous rendre service. Quand ils sont utilisés dans des conditions, les deux premiers sont représentés comme ci dessous :</p> +Si vous voulez tester plusieurs conditions sans imbriquer des instructions `if...else` , les [opérateurs logiques](/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Op%C3%A9rateurs_logiques) pourront vous rendre service. Quand ils sont utilisés dans des conditions, les deux premiers sont représentés comme ci dessous : -<ul> - <li><code>&&</code> — AND ; vous permet d'enchaîner deux ou plusieurs expressions de sorte que toutes doivent être individuellement égales à <code>true</code> pour que l'enemble de l'expression retourne <code>true</code>.</li> - <li><code>||</code> — OR ; vous permet d'enchaîner deux ou plusieurs expressions ensemble de sorte qu'il suffit qu'une au plus soit évaluée comme étant <code>true</code> pour que l'ensemble de l'expression renvoie <code>true</code>.</li> -</ul> +- `&&` — AND ; vous permet d'enchaîner deux ou plusieurs expressions de sorte que toutes doivent être individuellement égales à `true` pour que l'enemble de l'expression retourne `true`. +- `||` — OR ; vous permet d'enchaîner deux ou plusieurs expressions ensemble de sorte qu'il suffit qu'une au plus soit évaluée comme étant `true` pour que l'ensemble de l'expression renvoie `true`. -<p>Pour vous donner un exemple de AND, le morceau de code précedent peut être réécrit ainsi :</p> +Pour vous donner un exemple de AND, le morceau de code précedent peut être réécrit ainsi : -<pre class="brush: js">if (choice === 'sunny' && temperature < 86) { +```js +if (choice === 'sunny' && temperature < 86) { para.textContent = 'Il fait ' + temperature + ' degrés dehors — beau temps ensoleillé. Allez à la plage ou au parc et achetez une crème glacée.'; -} else if (choice === 'sunny' && temperature >= 86) { +} else if (choice === 'sunny' && temperature >= 86) { para.textContent = 'Il fait ' + temperature + ' degrés dehors — VRAIMENT CHAUD ! Si vous voulez sortir, assurez‑vous d'avoir passé une crème solaire.'; -}</pre> +} +``` -<p>Ainsi, par exemple, le premier bloc de code ne sera exécuté que si <code>choice === 'sunny'</code> <em>ET</em> <code>temperature < 86</code> renvoient tous deux <code>true</code>.</p> +Ainsi, par exemple, le premier bloc de code ne sera exécuté que si `choice === 'sunny'` _ET_ `temperature < 86` renvoient tous deux `true`. -<p>Voyons un petit exemple avec OR :</p> +Voyons un petit exemple avec OR : -<pre class="brush: js">if (camionDeGlaces || etatDeLaMaison === 'on fire') { +```js +if (camionDeGlaces || etatDeLaMaison === 'on fire') { console.log('Vous devriez sortir de la maison rapidement.'); } else { console.log('Vous pouvez probablement rester dedans.'); -}</pre> +} +``` -<p>Le dernier type d'opérateur logique, NOT, exprimé par l'opérateur <code>!</code>, peut s'utiliser pour nier une expression. Combinons‑le avec OR dans cet exemple :</p> +Le dernier type d'opérateur logique, NOT, exprimé par l'opérateur `!`, peut s'utiliser pour nier une expression. Combinons‑le avec OR dans cet exemple : -<pre class="brush: js">if (!(camionDeGlaces || etatDeLaMaison === 'on fire')) { +```js +if (!(camionDeGlaces || etatDeLaMaison === 'on fire')) { console.log('Vous pouvez probablement rester dedans.'); } else { console.log('Vous devriez sortir de la maison rapidement.'); -}</pre> +} +``` -<p>Dans cet extrait, si la déclaration avec OR renvoie <code>true</code>, l'opérateur NOT va nier l'ensemble : l'expression retournera donc <code>false</code>.</p> +Dans cet extrait, si la déclaration avec OR renvoie `true`, l'opérateur NOT va nier l'ensemble : l'expression retournera donc `false`. -<p>Vous pouvez combiner autant d'instructions logiques que vous le souhaitez, quelle que soit la structure. L'exemple suivant n'exécute le code entre accolades que si les deux instructions OR renvoient true, l'instruction AND recouvrante renvoie alors <code>true</code> :</p> +Vous pouvez combiner autant d'instructions logiques que vous le souhaitez, quelle que soit la structure. L'exemple suivant n'exécute le code entre accolades que si les deux instructions OR renvoient true, l'instruction AND recouvrante renvoie alors `true` : -<pre class="brush: js">if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'Steve')) { +```js +if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'Steve')) { // exécuter le code -}</pre> +} +``` -<p>Une erreur fréquente avec l'opérateur OR dans des instructions conditionnelles est de n'indiquer la variable dont vous testez la valeur qu'une fois, puis de donner une liste de valeurs sensées renvoyer <code>true</code> séparées par des || (OR) opérateurs. Par exemple :</p> +Une erreur fréquente avec l'opérateur OR dans des instructions conditionnelles est de n'indiquer la variable dont vous testez la valeur qu'une fois, puis de donner une liste de valeurs sensées renvoyer `true` séparées par des || (OR) opérateurs. Par exemple : -<pre class="example-bad brush: js">if (x === 5 || 7 || 10 || 20) { +```js example-bad +if (x === 5 || 7 || 10 || 20) { // exécuter le code -}</pre> +} +``` -<p>Dans ce cas, la condition dans le <code>if(...) </code>sera toujours évaluée à vrai puisque 7 (ou toute autre valeur non nulle) est toujours <code>true</code>. Cette condition dit en réalité « si x est égal à 5, ou bien 7 est vrai » — ce qui est toujours le cas. Ce n'est pas ce que nous voulons logiquement ! Pour que cela fonctionne, vous devez définir un test complet entre chaque opérateur OR :</p> +Dans ce cas, la condition dans le `if(...) `sera toujours évaluée à vrai puisque 7 (ou toute autre valeur non nulle) est toujours `true`. Cette condition dit en réalité « si x est égal à 5, ou bien 7 est vrai » — ce qui est toujours le cas. Ce n'est pas ce que nous voulons logiquement ! Pour que cela fonctionne, vous devez définir un test complet entre chaque opérateur OR : -<pre class="brush: js">if (x === 5 || x === 7 || x === 10 ||x === 20) { +```js +if (x === 5 || x === 7 || x === 10 ||x === 20) { // exécuter le code -}</pre> +} +``` -<h2 id="Instruction_switch">Instruction switch</h2> +## Instruction switch -<p>Les Instructions <code>if...else</code> font bien le travail d'aiguiller la programmation selon des conditions, mais elles ne sont pas sans inconvénient. Elles sont principalement adaptées aux cas où vous avez un choix binaire, chacun nécessitant une quantité raisonnable de code à exécuter, et/ou au cas où les conditions sont complexes (par ex. plusieurs opérateurs logiques). Si vous voulez juste fixer la valeur d'une variable à un choix donné ou afficher une déclaration particulière en fonction d'une condition, cette syntaxe peut devenir un peu lourde, surtout si le nombre de choix est important.</p> +Les Instructions `if...else` font bien le travail d'aiguiller la programmation selon des conditions, mais elles ne sont pas sans inconvénient. Elles sont principalement adaptées aux cas où vous avez un choix binaire, chacun nécessitant une quantité raisonnable de code à exécuter, et/ou au cas où les conditions sont complexes (par ex. plusieurs opérateurs logiques). Si vous voulez juste fixer la valeur d'une variable à un choix donné ou afficher une déclaration particulière en fonction d'une condition, cette syntaxe peut devenir un peu lourde, surtout si le nombre de choix est important. -<p>Les <a href="/fr/docs/Web/JavaScript/Reference/Instructions/switch">instructions switch</a> sont vos amies — elles prennent une seule valeur ou expression en entrée, puis examinent une palette de choix jusqu'à trouver celui qui correspond, et exécutent le code qui va avec. Voici un peu de pseudo-code, pour vous donner l'idée :</p> +Les [instructions switch](/fr/docs/Web/JavaScript/Reference/Instructions/switch) sont vos amies — elles prennent une seule valeur ou expression en entrée, puis examinent une palette de choix jusqu'à trouver celui qui correspond, et exécutent le code qui va avec. Voici un peu de pseudo-code, pour vous donner l'idée : -<pre class="brush: js"><strong>switch (expression) {</strong> - <strong>case</strong> choix1<strong>:</strong> +```js +switch (expression) { + case choix1: exécuter ce code - <strong>break;</strong> + break; - <strong>case</strong> choix2<strong>:</strong> + case choix2: exécuter ce code à la place - <strong>break;</strong> + break; - // incorporez autant de <strong>case</strong> que vous le souhaitez + // incorporez autant de case que vous le souhaitez - <strong>default:</strong> + default: sinon, exécutez juste ce code -<strong>}</strong></pre> - -<p>Ici nous avons</p> - -<ol> - <li>Le mot‑clé <code>switch</code> suivi de parenthèses.</li> - <li>Une expression ou une valeur mise entre les parenthèses.</li> - <li>Le mot‑clé <code>case</code> suivi d'une expression ou d'une valeur, et de deux‑points.</li> - <li>Le code exécuté si l'expression/valeur de <code>case</code> correspond à celles de <code>switch</code>.</li> - <li>Une déclaration <code>break</code>, suivie d'un point‑virgule. Si le choix précédent correspond à l'expression/valeur, le navigateur va stopper l'exécution du bloc de code ici et continuer après l'instruction <strong>switch</strong>.</li> - <li>Vous pouvez rajouter autant de <strong>cas</strong> que vous le souhaitez. (points 3–5)</li> - <li>Le mot‑clé <code>default</code>, suivi d'une même structure de code qu'aux points 3-5, sauf que <code>default</code> n'a pas de choix après lui et n'a donc pas besoin de l'instruction <code>break</code> puisqu'il n'y a plus rien à exécuter après ce bloc. C'est l'option <code>default</code> qui sera exécutée si aucun choix ne correspond.</li> -</ol> - -<div class="note"> -<p><strong>Note :</strong> Vous n'avez pas à inclure la section <code>default</code> — elle peut être omise en toute sécurité s'il n'y a aucune chance que l'expression finisse par égaler une valeur inconnue. À contrario, vous devez l'inclure s'il est possible qu'il y ait des cas inconnus.</p> -</div> +} +``` + +Ici nous avons -<h3 id="Un_exemple_de_switch">Un exemple de switch</h3> +1. Le mot‑clé `switch` suivi de parenthèses. +2. Une expression ou une valeur mise entre les parenthèses. +3. Le mot‑clé `case` suivi d'une expression ou d'une valeur, et de deux‑points. +4. Le code exécuté si l'expression/valeur de `case` correspond à celles de `switch`. +5. Une déclaration `break`, suivie d'un point‑virgule. Si le choix précédent correspond à l'expression/valeur, le navigateur va stopper l'exécution du bloc de code ici et continuer après l'instruction **switch**. +6. Vous pouvez rajouter autant de **cas** que vous le souhaitez. (points 3–5) +7. Le mot‑clé `default`, suivi d'une même structure de code qu'aux points 3-5, sauf que `default` n'a pas de choix après lui et n'a donc pas besoin de l'instruction `break` puisqu'il n'y a plus rien à exécuter après ce bloc. C'est l'option `default` qui sera exécutée si aucun choix ne correspond. -<p>Voyons un exemple concret — nous allons réécrire notre application de prévision météo en utilisant une instruction <code>switch</code> à la place :</p> +> **Note :** Vous n'avez pas à inclure la section `default` — elle peut être omise en toute sécurité s'il n'y a aucune chance que l'expression finisse par égaler une valeur inconnue. À contrario, vous devez l'inclure s'il est possible qu'il y ait des cas inconnus. -<pre class="brush: html"><label for="weather">Select the weather type today: </label> -<select id="weather"> - <option value="">--Make a choice--</option> - <option value="sunny">Sunny</option> - <option value="rainy">Rainy</option> - <option value="snowing">Snowing</option> - <option value="overcast">Overcast</option> -</select> +### Un exemple de switch -<p></p></pre> +Voyons un exemple concret — nous allons réécrire notre application de prévision météo en utilisant une instruction `switch` à la place : -<pre class="brush: js">const select = document.querySelector('select'); +```html +<label for="weather">Select the weather type today: </label> +<select id="weather"> + <option value="">--Make a choice--</option> + <option value="sunny">Sunny</option> + <option value="rainy">Rainy</option> + <option value="snowing">Snowing</option> + <option value="overcast">Overcast</option> +</select> + +<p></p> +``` + +```js +const select = document.querySelector('select'); const para = document.querySelector('p'); select.addEventListener('change', setWeather); @@ -335,39 +355,43 @@ function setWeather() { default: para.textContent = ''; } -}</pre> +} +``` -<p>{{ EmbedLiveSample('Un_exemple_de_switch', '100%', 100) }}</p> +{{ EmbedLiveSample('Un_exemple_de_switch', '100%', 100) }} -<div class="note"> -<p><strong>Note :</strong> Vous trouverez également cet <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-switch.html">exemple sur GitHub</a> (voyez‑le en <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-switch.html">cours d'exécution </a>ici aussi.)</p> -</div> +> **Note :** Vous trouverez également cet [exemple sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-switch.html) (voyez‑le en [cours d'exécution ](http://mdn.github.io/learning-area/javascript/building-blocks/simple-switch.html)ici aussi.) -<h2 id="Opérateur_ternaire">Opérateur ternaire</h2> +## Opérateur ternaire -<p>Voici une dernière syntaxe que nous souhaitons vous présenter avant de nous amuser avec quelques exemples. L'<a href="/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/L_op%C3%A9rateur_conditionnel">opérateur ternaire ou conditionnel</a> est un petit morceau de code qui teste une condition et renvoie une valeur ou expression si elle est <code>true</code> et une autre si elle est <code>false</code> — elle est utile dans certains cas, et occupe moins de place qu'un bloc <code>if...else</code> si votre choix est limité à deux possibilités à choisir via une condition <code>true</code>/<code>false</code>. Voici le pseudo‑code correspondant :</p> +Voici une dernière syntaxe que nous souhaitons vous présenter avant de nous amuser avec quelques exemples. L'[opérateur ternaire ou conditionnel](/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/L_op%C3%A9rateur_conditionnel) est un petit morceau de code qui teste une condition et renvoie une valeur ou expression si elle est `true` et une autre si elle est `false` — elle est utile dans certains cas, et occupe moins de place qu'un bloc `if...else` si votre choix est limité à deux possibilités à choisir via une condition `true`/`false`. Voici le pseudo‑code correspondant : -<pre>( condition ) ? exécuter ce code : exécuter celui‑ci à la place</pre> + ( condition ) ? exécuter ce code : exécuter celui‑ci à la place -<p>Regardons cet exemple simple :</p> +Regardons cet exemple simple : -<pre class="brush: js">let formuleDePolitesse = ( est_anniversaire ) ? 'Bon anniversaire Mme Smith — nous vous souhaitons une belle journée !' : 'Bonjour Mme Smith.';</pre> +```js +let formuleDePolitesse = ( est_anniversaire ) ? 'Bon anniversaire Mme Smith — nous vous souhaitons une belle journée !' : 'Bonjour Mme Smith.'; +``` -<p>Ici, nous avons une variable nommée <code>est_anniversaire</code> — si elle est <code>true</code>, nous adressons à notre hôte un message de « Bon anniversaire » ; si ce n'est pas le cas, c'est-à-dire si <code>est_anniversaire</code> renvoie <code>false</code>, nous disons simplement « Bonjour ».</p> +Ici, nous avons une variable nommée `est_anniversaire` — si elle est `true`, nous adressons à notre hôte un message de « Bon anniversaire » ; si ce n'est pas le cas, c'est-à-dire si `est_anniversaire` renvoie `false`, nous disons simplement « Bonjour ». -<h3 id="Exemple_opérateur_ternaire">Exemple opérateur ternaire</h3> +### Exemple opérateur ternaire -<p>L'opérateur ternaire ne sert pas qu'à définir des valeurs de variables ; vous pouvez aussi exécuter des fonctions, ou des lignes de code — ce que vous voulez. Voici un exemple concret de choix de thème où le style du site est déterminé grâce à un opérateur ternaire.</p> +L'opérateur ternaire ne sert pas qu'à définir des valeurs de variables ; vous pouvez aussi exécuter des fonctions, ou des lignes de code — ce que vous voulez. Voici un exemple concret de choix de thème où le style du site est déterminé grâce à un opérateur ternaire. -<pre class="brush: html"><label for="theme">Select theme: </label> -<select id="theme"> - <option value="white">White</option> - <option value="black">Black</option> -</select> +```html +<label for="theme">Select theme: </label> +<select id="theme"> + <option value="white">White</option> + <option value="black">Black</option> +</select> -<h1>This is my website</h1></pre> +<h1>This is my website</h1> +``` -<pre class="brush: js">const select = document.querySelector('select'); +```js +const select = document.querySelector('select'); const html = document.querySelector('html'); document.body.style.padding = '10px'; @@ -379,69 +403,62 @@ function update(bgColor, textColor) { select.onchange = function() { ( select.value === 'black' ) ? update('black','white') : update('white','black'); } -</pre> +``` -<p>{{ EmbedLiveSample('Exemple_opérateur_ternaire', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> +{{ EmbedLiveSample('Exemple_opérateur_ternaire', '100%', 300, "", "", "hide-codepen-jsfiddle") }} -<p>Nous mettons un élément {{htmlelement('select')}} pour choisir un thème (noir ou blanc), plus un simple élément {{htmlelement('h1')}} pour afficher un titre de site web. Nous avons aussi une fonction <code>update()</code>, qui prend deux couleurs en paramètre (entrées). La couleur de fond du site est déterminée par la couleur indiquée dans le premier paramètre fourni, et la couleur du texte par le deuxième.</p> +Nous mettons un élément {{htmlelement('select')}} pour choisir un thème (noir ou blanc), plus un simple élément {{htmlelement('h1')}} pour afficher un titre de site web. Nous avons aussi une fonction `update()`, qui prend deux couleurs en paramètre (entrées). La couleur de fond du site est déterminée par la couleur indiquée dans le premier paramètre fourni, et la couleur du texte par le deuxième. -<p>Nous avons également mis un écouteur d'événement <a href="/fr/docs/Web/API/GlobalEventHandlers/onchange">onchange</a> qui sert à exécuter une fonction contenant un opérateur ternaire. Il débute par un test de condition — <code>select.value === 'black'</code>. Si le test renvoie <code>true</code>, nous exécutons la fonction <code>update()</code> avec les paramètres blanc et noir : cela signifie que le fond sera noir et le texte blanc. S'il renvoie <code>false</code>, nous exécutons <code>update()</code> avec les paramètres noir et blanc, les couleurs du site seront inversées.</p> +Nous avons également mis un écouteur d'événement [onchange](/fr/docs/Web/API/GlobalEventHandlers/onchange) qui sert à exécuter une fonction contenant un opérateur ternaire. Il débute par un test de condition — `select.value === 'black'`. Si le test renvoie `true`, nous exécutons la fonction `update()` avec les paramètres blanc et noir : cela signifie que le fond sera noir et le texte blanc. S'il renvoie `false`, nous exécutons `update()` avec les paramètres noir et blanc, les couleurs du site seront inversées. -<div class="note"> -<p><strong>Note :</strong> Vous trouverez également cet <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-ternary.html">exemple sur GitHub</a> (voyez‑le en <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-ternary.html">cours d'exécution </a>ici aussi.)</p> -</div> +> **Note :** Vous trouverez également cet [exemple sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-ternary.html) (voyez‑le en [cours d'exécution ](http://mdn.github.io/learning-area/javascript/building-blocks/simple-ternary.html)ici aussi.) -<h2 id="Apprentissage_actif_un_calendrier_simple">Apprentissage actif : un calendrier simple</h2> +## Apprentissage actif : un calendrier simple -<p>Dans cet exemple nous allons vous aider à finaliser une application de calendrier simple. Dans le code, vous avez :</p> +Dans cet exemple nous allons vous aider à finaliser une application de calendrier simple. Dans le code, vous avez : -<ul> - <li>Un élément {{htmlelement("select")}} permettant à l'utilisateur de choisir un mois.</li> - <li>Un pilote d'événement <code>onchange</code> pour détecter si la valeur choisie dans le menu <code><select></code> a été modifiée.</li> - <li>Une fonction <code>createCalendar()</code> qui trace le calendrier et affiche le mois voulu dans l'élément {{htmlelement("h1")}}.</li> -</ul> +- Un élément {{htmlelement("select")}} permettant à l'utilisateur de choisir un mois. +- Un pilote d'événement `onchange` pour détecter si la valeur choisie dans le menu `<select>` a été modifiée. +- Une fonction `createCalendar()` qui trace le calendrier et affiche le mois voulu dans l'élément {{htmlelement("h1")}}. -<p>Vous aurez besoin d'écrire une instruction conditionnelle dans la fonction <code>onchange</code>, juste au dessous du commentaire <code>// AJOUTER LA CONDITION ICI</code>. Elle doit :</p> +Vous aurez besoin d'écrire une instruction conditionnelle dans la fonction `onchange`, juste au dessous du commentaire `// AJOUTER LA CONDITION ICI`. Elle doit : -<ol> - <li>Noter le mois choisi (enregistré dans la variable <code>choice</code>. Ce doit être la valeur de l'élément <code><select></code> après un changement, "Janvier" par exemple).</li> - <li>Faire en sorte que la variable nommée <code>days</code> soit égale au nombre de jours du mois sélectionné. Pour ce faire, examinez le nombre de jours dans chaque mois de l'année. Vous pouvez ignorer les années bissextiles pour les besoins de cet exemple.</li> -</ol> +1. Noter le mois choisi (enregistré dans la variable `choice`. Ce doit être la valeur de l'élément `<select>` après un changement, "Janvier" par exemple). +2. Faire en sorte que la variable nommée `days` soit égale au nombre de jours du mois sélectionné. Pour ce faire, examinez le nombre de jours dans chaque mois de l'année. Vous pouvez ignorer les années bissextiles pour les besoins de cet exemple. -<p>Conseils :</p> +Conseils : -<ul> - <li>Utilisez un OR logique pour grouper plusieurs mois ensemble dans une même condition, beaucoup d'entre eux ont le même nombre de jours.</li> - <li>Voyez quel est le nombre de jours le plus courant et utilisez le comme valeur par défaut.</li> -</ul> +- Utilisez un OR logique pour grouper plusieurs mois ensemble dans une même condition, beaucoup d'entre eux ont le même nombre de jours. +- Voyez quel est le nombre de jours le plus courant et utilisez le comme valeur par défaut. -<p>Si vous faites une erreur, vous pouvez toujours réinitialiser l'exemple avec le bouton "Réinitialiser". Si vous êtes vraiment bloqué, pressez "Voir la solution".</p> +Si vous faites une erreur, vous pouvez toujours réinitialiser l'exemple avec le bouton "Réinitialiser". Si vous êtes vraiment bloqué, pressez "Voir la solution". -<pre class="brush: html hidden"><div class="output" style="height: 500px;overflow: auto;"> - <label for="month">Choisissez un mois : </label> - <select id="month"> - <option value="Janvier">Janvier</option> - <option value="Février">Février</option> - <option value="Mars">Mars</option> - <option value="Avril">Avril</option> - <option value="Mai">Mai</option> - <option value="Juin">Juin</option> - <option value="Juillet">Juillet</option> - <option value="Août">Août</option> - <option value="Septembre">Septembre</option> - <option value="Octobre">Octobre</option> - <option value="Novembre">Novembre</option> - <option value="Decembre">Décembre</option> - </select> +```html hidden +<div class="output" style="height: 500px;overflow: auto;"> + <label for="month">Choisissez un mois : </label> + <select id="month"> + <option value="Janvier">Janvier</option> + <option value="Février">Février</option> + <option value="Mars">Mars</option> + <option value="Avril">Avril</option> + <option value="Mai">Mai</option> + <option value="Juin">Juin</option> + <option value="Juillet">Juillet</option> + <option value="Août">Août</option> + <option value="Septembre">Septembre</option> + <option value="Octobre">Octobre</option> + <option value="Novembre">Novembre</option> + <option value="Decembre">Décembre</option> + </select> - <h1></h1> + <h1></h1> - <ul></ul> -</div> + <ul></ul> +</div> -<hr> +<hr> -<textarea id="code" class="playable-code" style="height: 500px;"> +<textarea id="code" class="playable-code" style="height: 500px;"> var select = document.querySelector('select'); var list = document.querySelector('ul'); var h1 = document.querySelector('h1'); @@ -457,7 +474,7 @@ select.onchange = function() { function createCalendar(days, choice) { list.innerHTML = ''; h1.textContent = choice; - for (var i = 1; i <= days; i++) { + for (var i = 1; i <= days; i++) { const listItem = document.createElement('li'); listItem.textContent = i; list.appendChild(listItem); @@ -465,15 +482,16 @@ function createCalendar(days, choice) { } createCalendar(31,'Janvier'); -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Réinitialiser"> - <input id="solution" type="button" value="Voir la solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Réinitialiser"> + <input id="solution" type="button" value="Voir la solution"> +</div> +``` -<pre class="brush: css hidden">.output * { +```css hidden +.output * { box-sizing: border-box; } @@ -491,9 +509,10 @@ createCalendar(31,'Janvier'); background-color: #4A2DB6; color: white; } -</pre> +``` -<pre class="brush: js hidden">const textarea = document.getElementById('code'); +```js hidden +const textarea = document.getElementById('code'); const reset = document.getElementById('reset'); const solution = document.getElementById('solution'); let code = textarea.value; @@ -512,42 +531,41 @@ solution.addEventListener('click', function() { updateCode(); }); -var jsSolution = 'var select = document.querySelector(\'select\');\nvar list = document.querySelector(\'ul\');\nvar h1 = document.querySelector(\'h1\');\n\nselect.onchange = function() {\n var choice = select.value;\n var days = 31;\n if(choice === \'February\') {\n days = 28;\n } else if(choice === \'April\' || choice === \'June\' || choice === \'September\'|| choice === \'November\') {\n days = 30;\n }\n\n createCalendar(days, choice);\n}\n\nfunction createCalendar(days, choice) {\n list.innerHTML = \'\';\n h1.textContent = choice;\n for(var i = 1; i <= days; i++) {\n var listItem = document.createElement(\'li\');\n listItem.textContent = i;\n list.appendChild(listItem);\n }\n }\n\ncreateCalendar(31,\'January\');'; +var jsSolution = 'var select = document.querySelector(\'select\');\nvar list = document.querySelector(\'ul\');\nvar h1 = document.querySelector(\'h1\');\n\nselect.onchange = function() {\n var choice = select.value;\n var days = 31;\n if(choice === \'February\') {\n days = 28;\n } else if(choice === \'April\' || choice === \'June\' || choice === \'September\'|| choice === \'November\') {\n days = 30;\n }\n\n createCalendar(days, choice);\n}\n\nfunction createCalendar(days, choice) {\n list.innerHTML = \'\';\n h1.textContent = choice;\n for(var i = 1; i <= days; i++) {\n var listItem = document.createElement(\'li\');\n listItem.textContent = i;\n list.appendChild(listItem);\n }\n }\n\ncreateCalendar(31,\'January\');'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Apprentissage_actif_un_calendrier_simple', '100%', 1110, "", "", "hide-codepen-jsfiddle") }}</p> +{{ EmbedLiveSample('Apprentissage_actif_un_calendrier_simple', '100%', 1110, "", "", "hide-codepen-jsfiddle") }} -<h2 id="Activité_plus_de_choix_de_couleurs">Activité : plus de choix de couleurs</h2> +## Activité : plus de choix de couleurs -<p>Nous allons reprendre l'exemple de l'opérateur ternaire vu plus haut et transformer cet opérateur ternaire en une directive <code>switch</code> qui nous permettra une plus grande variété de choix pour le site web tout simple. Voyez l'élément {{htmlelement("select")}} — cette fois, il n'y a pas deux options de thème, mais cinq. Il vous faut ajouter une directive <code>switch</code> au dessous du commentaire <code>// AJOUT D'UNE DIRECTIVE SWITCH</code> :</p> +Nous allons reprendre l'exemple de l'opérateur ternaire vu plus haut et transformer cet opérateur ternaire en une directive `switch` qui nous permettra une plus grande variété de choix pour le site web tout simple. Voyez l'élément {{htmlelement("select")}} — cette fois, il n'y a pas deux options de thème, mais cinq. Il vous faut ajouter une directive `switch` au dessous du commentaire `// AJOUT D'UNE DIRECTIVE SWITCH` : -<ul> - <li>Elle doit accepter la variable <code>choice</code> comme expression d'entrée.</li> - <li>Pour chaque cas, le choix doit être égal à une des valeurs possibles pouvant être choisies, c'est-à-dire blanc, noir, mauve, jaune ou psychédélique.</li> - <li>Chaque cas exécutera la fonction <code>update()</code> à laquelle deux valeurs de couleurs seront passées, la première pour le fond, la seconde pour le texte. Souvenez vous que les valeurs de couleurs sont des chaînes ; elle doivent donc être mises entre guillemets.</li> -</ul> +- Elle doit accepter la variable `choice` comme expression d'entrée. +- Pour chaque cas, le choix doit être égal à une des valeurs possibles pouvant être choisies, c'est-à-dire blanc, noir, mauve, jaune ou psychédélique. +- Chaque cas exécutera la fonction `update()` à laquelle deux valeurs de couleurs seront passées, la première pour le fond, la seconde pour le texte. Souvenez vous que les valeurs de couleurs sont des chaînes ; elle doivent donc être mises entre guillemets. -<p>Si vous faites une erreur, vous pouvez toujours réinitialiser l'exemple avec le bouton « Réinitialiser ». Si vous êtes vraiment bloqué, pressez « Voir la solution ».</p> +Si vous faites une erreur, vous pouvez toujours réinitialiser l'exemple avec le bouton « Réinitialiser ». Si vous êtes vraiment bloqué, pressez « Voir la solution ». -<pre class="brush: html hidden"><div class="output" style="height: 300px;"> - <label for="theme">Choisissez un thème : </label> - <select id="theme"> - <option value="white">Blanc</option> - <option value="black">Noir</option> - <option value="purple">Mauve</option> - <option value="yellow">Jaune</option> - <option value="psychedelic">Psychédélique</option> - </select> +```html hidden +<div class="output" style="height: 300px;"> + <label for="theme">Choisissez un thème : </label> + <select id="theme"> + <option value="white">Blanc</option> + <option value="black">Noir</option> + <option value="purple">Mauve</option> + <option value="yellow">Jaune</option> + <option value="psychedelic">Psychédélique</option> + </select> - <h1>Voici mon site Web</h1> -</div> + <h1>Voici mon site Web</h1> +</div> -<hr> +<hr> -<textarea id="code" class="playable-code" style="height: 450px;"> +<textarea id="code" class="playable-code" style="height: 450px;"> const select = document.querySelector('select'); const html = document.querySelector('.output'); @@ -560,15 +578,16 @@ select.onchange = function() { function update(bgColor, textColor) { html.style.backgroundColor = bgColor; html.style.color = textColor; -}</textarea> +}</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Réinitialiser"> - <input id="solution" type="button" value="Voir la solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Réinitialiser"> + <input id="solution" type="button" value="Voir la solution"> +</div> +``` -<pre class="brush: js hidden">const textarea = document.getElementById('code'); +```js hidden +const textarea = document.getElementById('code'); const reset = document.getElementById('reset'); const solution = document.getElementById('solution'); let code = textarea.value; @@ -591,33 +610,29 @@ const jsSolution = 'const select = document.querySelector(\'select\');\nlet html textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Activité_plus_de_choix_de_couleurs', '100%', 850) }}</p> +{{ EmbedLiveSample('Activité_plus_de_choix_de_couleurs', '100%', 850) }} -<h2 id="Conclusion">Conclusion</h2> +## Conclusion -<p>C'est tout ce qu'il est nécessaire de connaître à propos des structures conditionnelles en JavaScript pour le moment ! Je pense que vous avez assurément compris ces concepts et travaillé les exemples aisément ; s'il y a quelque chose que vous n'avez pas compris, relisez cet article à nouveau, ou bien <a href="/fr/Apprendre#Nous_contacter">contactez‑nous</a> pour une aide.</p> +C'est tout ce qu'il est nécessaire de connaître à propos des structures conditionnelles en JavaScript pour le moment ! Je pense que vous avez assurément compris ces concepts et travaillé les exemples aisément ; s'il y a quelque chose que vous n'avez pas compris, relisez cet article à nouveau, ou bien [contactez‑nous](/fr/Apprendre#Nous_contacter) pour une aide. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Math#Opérateurs_de_comparaison">Opérateurs de comparaison</a></li> - <li><a href="/fr/docs/Web/JavaScript/Guide/Contrôle_du_flux_Gestion_des_erreurs#Les_instructions_conditionnelles">Les instructions conditionnelles</a></li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">Référence if...else</a></li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/L_op%C3%A9rateur_conditionnel">Référence opérateur conditionnel (ternaire)</a></li> -</ul> +- [Opérateurs de comparaison](/fr/docs/Learn/JavaScript/First_steps/Math#Opérateurs_de_comparaison) +- [Les instructions conditionnelles](/fr/docs/Web/JavaScript/Guide/Contrôle_du_flux_Gestion_des_erreurs#Les_instructions_conditionnelles) +- [Référence if...else](/fr/docs/Web/JavaScript/Reference/Instructions/if...else) +- [Référence opérateur conditionnel (ternaire)](/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/L_op%C3%A9rateur_conditionnel) -<p>{{NextMenu("Apprendre/JavaScript/Building_blocks/Looping_code", "Apprendre/JavaScript/Building_blocks")}}</p> +{{NextMenu("Apprendre/JavaScript/Building_blocks/Looping_code", "Apprendre/JavaScript/Building_blocks")}} -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/conditionals">Prendre des décisions dans du code — conditions</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Looping_code">Les boucles dans le code</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Fonctions">Fonctions — blocs de code réutilisables</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Construire vos propres fonctions</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Return_values">Valeurs de retour des fonctions</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">Introduction aux événements</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Image_gallery">Gallerie d'images</a></li> -</ul> +- [Prendre des décisions dans du code — conditions](/fr/Apprendre/JavaScript/Building_blocks/conditionals) +- [Les boucles dans le code](/fr/Apprendre/JavaScript/Building_blocks/Looping_code) +- [Fonctions — blocs de code réutilisables](/fr/Apprendre/JavaScript/Building_blocks/Fonctions) +- [Construire vos propres fonctions](/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function) +- [Valeurs de retour des fonctions](/fr/Apprendre/JavaScript/Building_blocks/Return_values) +- [Introduction aux événements](/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements) +- [Gallerie d'images](/fr/Apprendre/JavaScript/Building_blocks/Image_gallery) diff --git a/files/fr/learn/javascript/building_blocks/events/index.md b/files/fr/learn/javascript/building_blocks/events/index.md index b8bd4ba3d6..0f5ea11526 100644 --- a/files/fr/learn/javascript/building_blocks/events/index.md +++ b/files/fr/learn/javascript/building_blocks/events/index.md @@ -4,62 +4,71 @@ slug: Learn/JavaScript/Building_blocks/Events translation_of: Learn/JavaScript/Building_blocks/Events original_slug: Apprendre/JavaScript/Building_blocks/Evènements --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}</div> - -<p>Les événements sont des actions ou des occurrences qui se produisent dans le système que vous programmez et dont le système vous informe afin que vous puissiez y répondre d'une manière ou d'une autre si vous le souhaitez. Par exemple, si l'utilisateur clique sur un bouton d'une page Web, vous pouvez répondre à cette action en affichant une boîte d'information. Dans cet article, nous allons discuter de quelques concepts importants concernant les événements, et regarder comment ils fonctionnent dans les navigateurs. Ce ne sera pas une étude exhaustive; mais seulement ce que vous devez savoir à ce stade.</p> +Les événements sont des actions ou des occurrences qui se produisent dans le système que vous programmez et dont le système vous informe afin que vous puissiez y répondre d'une manière ou d'une autre si vous le souhaitez. Par exemple, si l'utilisateur clique sur un bouton d'une page Web, vous pouvez répondre à cette action en affichant une boîte d'information. Dans cet article, nous allons discuter de quelques concepts importants concernant les événements, et regarder comment ils fonctionnent dans les navigateurs. Ce ne sera pas une étude exhaustive; mais seulement ce que vous devez savoir à ce stade. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis:</th> - <td>Connaissances de base en informatique, une compréhension de base de HTML et CSS, <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript</a>.</td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Comprendre la théorie fondamentale des événements, comment ils fonctionnent dans les navigateurs et comment les événements peuvent différer dans différents environnements de programmation.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td> + Connaissances de base en informatique, une compréhension de base de HTML + et CSS, + <a href="/fr/docs/Learn/JavaScript/First_steps" + >Premiers pas en JavaScript</a + >. + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td> + Comprendre la théorie fondamentale des événements, comment ils + fonctionnent dans les navigateurs et comment les événements peuvent + différer dans différents environnements de programmation. + </td> + </tr> + </tbody> </table> -<h2 id="Une_série_d'événements_heureux">Une série d'événements heureux</h2> +## Une série d'événements heureux -<p>Comme mentionné ci-dessus, les événements sont des actions ou des occurrences qui se produisent dans le système que vous programmez — le système déclenche un signal quelconque lorsqu'un événement se produit, et fournit également un mécanisme par lequel une action est exécutée automatiquement (p.ex. un code en cours d'exécution) lorsque l'événement se produit. Par exemple, dans un aéroport, lorsque la piste est libre pour qu'un avion décolle, un signal est communiqué au pilote et, par conséquent, il commence à piloter l'avion.</p> +Comme mentionné ci-dessus, les événements sont des actions ou des occurrences qui se produisent dans le système que vous programmez — le système déclenche un signal quelconque lorsqu'un événement se produit, et fournit également un mécanisme par lequel une action est exécutée automatiquement (p.ex. un code en cours d'exécution) lorsque l'événement se produit. Par exemple, dans un aéroport, lorsque la piste est libre pour qu'un avion décolle, un signal est communiqué au pilote et, par conséquent, il commence à piloter l'avion. -<p><img alt="" src="MDN-mozilla-events-runway.png"></p> + -<p>Dans le cas du Web, les événements sont déclenchés à l'intérieur de la fenêtre du navigateur et tendent à être rattachés à un élément spécifique qui s'y trouve - il peut s'agir d'un élément unique, d'un ensemble d'éléments, du document HTML chargé dans l'onglet en cours ou toute la fenêtre du navigateur. Il y a beaucoup de types différents d'événements qui peuvent se produire, par exemple :</p> +Dans le cas du Web, les événements sont déclenchés à l'intérieur de la fenêtre du navigateur et tendent à être rattachés à un élément spécifique qui s'y trouve - il peut s'agir d'un élément unique, d'un ensemble d'éléments, du document HTML chargé dans l'onglet en cours ou toute la fenêtre du navigateur. Il y a beaucoup de types différents d'événements qui peuvent se produire, par exemple : -<ul> - <li>L'utilisateur clique avec la souris sur un certain élément ou en place le curseur sur un certain élément.</li> - <li>L'utilisateur appuie sur une touche du clavier. </li> - <li>L'utilisateur redimensionne ou ferme la fenêtre du navigateur. </li> - <li>Une page web finissant de se charger. </li> - <li>Un formulaire en cours de soumission </li> - <li>Une vidéo en cours de lecture, en pause ou en fin de lecture. </li> - <li>Une erreur qui survient.</li> -</ul> +- L'utilisateur clique avec la souris sur un certain élément ou en place le curseur sur un certain élément. +- L'utilisateur appuie sur une touche du clavier. +- L'utilisateur redimensionne ou ferme la fenêtre du navigateur. +- Une page web finissant de se charger. +- Un formulaire en cours de soumission +- Une vidéo en cours de lecture, en pause ou en fin de lecture. +- Une erreur qui survient. -<p>Vous vous en rendrez compte (notamment en jetant un coup d'œil à la section MDN <a href="/fr/docs/Web/Events">Référence des événements</a> ), il y a <strong>beaucoup</strong> d'événements auxquels vous pouvez répondre.<br> - <br> - Chaque événement disponible a un <strong>gestionnaire d'événement</strong>, qui est un bloc de code (généralement une fonction JavaScript définie par l'utilisateur) qui sera exécuté lorsque l'événement se déclenchera. Lorsqu'un tel bloc de code est défini pour être exécuté en réponse à un déclenchement d'événement, nous disons que nous <strong>enregistrons un gestionnaire d'événements</strong>. Notez que les gestionnaires d'événements sont parfois appelés <strong>écouteurs d'événements</strong> - ils sont à peu près interchangeables pour ce qui nous concerne, même si à la rigueur, ils fonctionnent ensemble. L'écouteur écoute l'événement qui se produit et le gestionnaire est le code qui est exécuté en réponse à ce qui se passe.</p> +Vous vous en rendrez compte (notamment en jetant un coup d'œil à la section MDN [Référence des événements](/fr/docs/Web/Events) ), il y a **beaucoup** d'événements auxquels vous pouvez répondre. -<div class="note"> -<p><strong>Note :</strong> il est important de noter que les événements web ne font pas partie du langage du noyau JavaScript — ils sont définis comme faisant partie des APIs JavaScript intégrées du navigateur</p> -</div> +Chaque événement disponible a un **gestionnaire d'événement**, qui est un bloc de code (généralement une fonction JavaScript définie par l'utilisateur) qui sera exécuté lorsque l'événement se déclenchera. Lorsqu'un tel bloc de code est défini pour être exécuté en réponse à un déclenchement d'événement, nous disons que nous **enregistrons un gestionnaire d'événements**. Notez que les gestionnaires d'événements sont parfois appelés **écouteurs d'événements** - ils sont à peu près interchangeables pour ce qui nous concerne, même si à la rigueur, ils fonctionnent ensemble. L'écouteur écoute l'événement qui se produit et le gestionnaire est le code qui est exécuté en réponse à ce qui se passe. + +> **Note :** il est important de noter que les événements web ne font pas partie du langage du noyau JavaScript — ils sont définis comme faisant partie des APIs JavaScript intégrées du navigateur -<h3 id="Un_exemple_simple">Un exemple simple</h3> +### Un exemple simple -<p>Regardons un exemple simple pour expliquer ce que nous entendons ici. Vous avez déjà utilisé des événements et des gestionnaires d'événements dans de nombreux exemples de ce cours, mais récapitulons simplement pour consolider nos connaissances. Dans l'exemple suivant, nous avons un {{htmlelement ("bouton")}} unique, qui, lorsqu'il est pressé, fera passer l'arrière-plan à une couleur aléatoire:</p> +Regardons un exemple simple pour expliquer ce que nous entendons ici. Vous avez déjà utilisé des événements et des gestionnaires d'événements dans de nombreux exemples de ce cours, mais récapitulons simplement pour consolider nos connaissances. Dans l'exemple suivant, nous avons un {{htmlelement ("bouton")}} unique, qui, lorsqu'il est pressé, fera passer l'arrière-plan à une couleur aléatoire: -<pre class="brush: html"><button>Change color</button></pre> +```html +<button>Change color</button> +``` -<pre class="brush: css hidden">button { margin: 10px };</pre> +```css hidden +button { margin: 10px }; +``` -<p>Le JavaScript ressemblera à ça :</p> +Le JavaScript ressemblera à ça : -<pre class="brush: js">var btn = document.querySelector('button'); +```js +var btn = document.querySelector('button'); function random(number) { return Math.floor(Math.random()*(number+1)); @@ -68,228 +77,242 @@ function random(number) { btn.onclick = function() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; -}</pre> +} +``` + -<p> </p> -<p>Dans ce code, nous stockons une référence au bouton dans une variable appelée btn, en utilisant la fonction {{domxref ("Document.querySelector ()")}}. Nous définissons également une fonction qui renvoie un nombre aléatoire. La troisième partie du code est le gestionnaire d'événement. La variable <code>btn</code> pointe sur un élément <code><button></code> , et ce type d'objet a un certain nombre d'événements qui peuvent être déclenchés, et par conséquent, des gestionnaires d'événements sont disponibles. Nous sommes à l'écoute du déclenchement de l'événement click, en définissant la propriété <code>onclick</code> du gestionnaire d'événements comme une fonction anonyme contenant du code qui génère une couleur RVB aléatoire et lui affecte la couleur d'arrière-plan <code><body></code> .<br> - <br> - Ce code sera maintenant exécuté chaque fois que l'événement "click" se déclenchera sur l'élément <code><button></code>, c'est-à-dire chaque fois qu'un utilisateur cliquera dessus.</p> +Dans ce code, nous stockons une référence au bouton dans une variable appelée btn, en utilisant la fonction {{domxref ("Document.querySelector ()")}}. Nous définissons également une fonction qui renvoie un nombre aléatoire. La troisième partie du code est le gestionnaire d'événement. La variable `btn` pointe sur un élément `<button>` , et ce type d'objet a un certain nombre d'événements qui peuvent être déclenchés, et par conséquent, des gestionnaires d'événements sont disponibles. Nous sommes à l'écoute du déclenchement de l'événement click, en définissant la propriété `onclick` du gestionnaire d'événements comme une fonction anonyme contenant du code qui génère une couleur RVB aléatoire et lui affecte la couleur d'arrière-plan `<body>` . -<p>Vous pourrez voir cet exemple s'afficher sur toute la page en cliquant sur <a href="https://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventhandlerattributes.html">ce lien.</a></p> +Ce code sera maintenant exécuté chaque fois que l'événement "click" se déclenchera sur l'élément `<button>`, c'est-à-dire chaque fois qu'un utilisateur cliquera dessus. -<p> </p> +Vous pourrez voir cet exemple s'afficher sur toute la page en cliquant sur [ce lien.](https://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventhandlerattributes.html) -<h3 id="Ce_ne_sont_pas_que_des_pages_web">Ce ne sont pas que des pages web</h3> -<p>Une autre chose qui mérite d'être mentionnée à ce stade est que les événements ne sont pas particuliers à JavaScript - la plupart des langages de programmation ont un certain type de modèle d'événement, et la façon dont cela fonctionne diffère souvent de celle de JavaScript. En fait, le modèle d'événement en JavaScript pour les pages Web diffère du modèle d'événement pour JavaScript tel qu'il est utilisé dans d'autres environnements.</p> -<p>Par exemple, <a href="/fr/docs/Learn/Server-side/Express_Nodejs">Node.js</a> est un runtime JavaScript très populaire qui permet aux développeurs d'utiliser JavaScript pour créer des applications réseau et serveur. Le modèle <a href="https://nodejs.org/docs/latest-v5.x/api/events.html">Node.js event model</a> s'appuie sur des écouteurs pour écouter les événements et des émetteurs pour générer des événements périodiquement — bien qu'il ne le semble pas à première vue, le code est très différent, en particulier lorsqu'il utilise des fonctions comme <code>on()</code> pour enregistrer un écouteur d'événement, et <code>once()</code> pour enregistrer un écouteur d'événement qui s'efface après sa première exécution. le document <a href="https://nodejs.org/docs/latest-v8.x/api/http.html#http_event_connect">HTTP connect event docs</a> propose un bon exemple d'utilisation.</p> +### Ce ne sont pas que des pages web -<p>Comme autre exemple, vous pouvez désormais utiliser JavaScript pour créer des extensions inter-navigateurs — comme améliorations de la fonctionnalité du navigateur — à l'aide d'une technologie appelée <a href="/fr/Add-ons/WebExtensions">WebExtensions</a>. Le modèle d'événement est similaire au modèle d'événements Web, mais un peu différent — les écouteurs d'événements sont sensibles à la casse (p.ex.<code>onMessage</code> plutôt que <code>onmessage</code>), et doivent êtres combinés à la fonction <code>addListener</code>. Jetez un oeil à la page <a href="/fr/Add-ons/WebExtensions/API/runtime/onMessage">runtime.onMessage page</a> pour voir un exemple.</p> +Une autre chose qui mérite d'être mentionnée à ce stade est que les événements ne sont pas particuliers à JavaScript - la plupart des langages de programmation ont un certain type de modèle d'événement, et la façon dont cela fonctionne diffère souvent de celle de JavaScript. En fait, le modèle d'événement en JavaScript pour les pages Web diffère du modèle d'événement pour JavaScript tel qu'il est utilisé dans d'autres environnements. -<p>Vous n'avez pas besoin de comprendre quoi que ce soit à propos d'autres environnements de ce type à ce stade de votre apprentissage; nous voulions juste préciser que les événements peuvent différer selon les environnements de programmation.</p> +Par exemple, [Node.js](/fr/docs/Learn/Server-side/Express_Nodejs) est un runtime JavaScript très populaire qui permet aux développeurs d'utiliser JavaScript pour créer des applications réseau et serveur. Le modèle [Node.js event model](https://nodejs.org/docs/latest-v5.x/api/events.html) s'appuie sur des écouteurs pour écouter les événements et des émetteurs pour générer des événements périodiquement — bien qu'il ne le semble pas à première vue, le code est très différent, en particulier lorsqu'il utilise des fonctions comme `on()` pour enregistrer un écouteur d'événement, et `once()` pour enregistrer un écouteur d'événement qui s'efface après sa première exécution. le document [HTTP connect event docs](https://nodejs.org/docs/latest-v8.x/api/http.html#http_event_connect) propose un bon exemple d'utilisation. -<h2 id="De_quelle_manière_utiliser_les_événements_Web">De quelle manière utiliser les événements Web ?</h2> +Comme autre exemple, vous pouvez désormais utiliser JavaScript pour créer des extensions inter-navigateurs — comme améliorations de la fonctionnalité du navigateur — à l'aide d'une technologie appelée [WebExtensions](/fr/Add-ons/WebExtensions). Le modèle d'événement est similaire au modèle d'événements Web, mais un peu différent — les écouteurs d'événements sont sensibles à la casse (p.ex.`onMessage` plutôt que `onmessage`), et doivent êtres combinés à la fonction `addListener`. Jetez un oeil à la page [runtime.onMessage page](/fr/Add-ons/WebExtensions/API/runtime/onMessage) pour voir un exemple. -<p>Il existe plusieurs façons d'ajouter un code d'écouteur d'événement aux pages Web afin qu'il soit exécuté lorsque l'événement associé se déclenche. Dans cette section, nous allons passer en revue les différents mécanismes et discuter de ceux que vous devriez utiliser.</p> +Vous n'avez pas besoin de comprendre quoi que ce soit à propos d'autres environnements de ce type à ce stade de votre apprentissage; nous voulions juste préciser que les événements peuvent différer selon les environnements de programmation. -<h3 id="Les_propriétés_du_gestionnaire_d'événement">Les propriétés du gestionnaire d'événement</h3> +## De quelle manière utiliser les événements Web ? -<p>Voici les propriétés qui existent pour contenir le code du gestionnaire d'événement que nous avons vu le plus fréquemment pendant le cours. Revenons à l'exemple ci-dessus :</p> +Il existe plusieurs façons d'ajouter un code d'écouteur d'événement aux pages Web afin qu'il soit exécuté lorsque l'événement associé se déclenche. Dans cette section, nous allons passer en revue les différents mécanismes et discuter de ceux que vous devriez utiliser. -<pre class="brush: js">var btn = document.querySelector('button'); +### Les propriétés du gestionnaire d'événement + +Voici les propriétés qui existent pour contenir le code du gestionnaire d'événement que nous avons vu le plus fréquemment pendant le cours. Revenons à l'exemple ci-dessus : + +```js +var btn = document.querySelector('button'); btn.onclick = function() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; -}</pre> +} +``` -<p>La propriété <code><a href="/fr/docs/Web/API/GlobalEventHandlers/onclick">onclick</a></code> est la propriété du gestionnaire d'événement utilisée dans cette situation. C'est essentiellement une propriété comme les autres disponibles sur le bouton (p.ex. <code><a href="/fr/docs/Web/API/Node/textContent">btn.textContent</a></code>, ou <code><a href="/fr/docs/Web/API/HTMLElement/style">btn.style</a></code>), mais d'un type spécial — lorsque vous la définissez comme étant égale à du code, ce code est exécuté lorsque l'événement se déclenche sur le bouton.</p> +La propriété [`onclick`](/fr/docs/Web/API/GlobalEventHandlers/onclick) est la propriété du gestionnaire d'événement utilisée dans cette situation. C'est essentiellement une propriété comme les autres disponibles sur le bouton (p.ex. [`btn.textContent`](/fr/docs/Web/API/Node/textContent), ou [`btn.style`](/fr/docs/Web/API/HTMLElement/style)), mais d'un type spécial — lorsque vous la définissez comme étant égale à du code, ce code est exécuté lorsque l'événement se déclenche sur le bouton. -<p>Vous pouvez également définir la propriété du gestionnaire d'événement comme étant égale au nom d'une fonction définie (comme nous l'avons vu dans <a href="/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Construire votre propre fonction</a>). Le code suivant fonctionnera tout pareil:</p> +Vous pouvez également définir la propriété du gestionnaire d'événement comme étant égale au nom d'une fonction définie (comme nous l'avons vu dans [Construire votre propre fonction](/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function)). Le code suivant fonctionnera tout pareil: -<pre class="brush: js">var btn = document.querySelector('button'); +```js +var btn = document.querySelector('button'); function bgChange() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; } -btn.onclick = bgChange;</pre> +btn.onclick = bgChange; +``` -<p>De nombreuses propriétés de gestionnaire d'événement sont disponibles. Faisons une expérience.</p> +De nombreuses propriétés de gestionnaire d'événement sont disponibles. Faisons une expérience. -<p>Tout d'abord, faites une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventhandlerproperty.html">random-color-eventhandlerproperty.html</a>, et ouvrez-le dans votre navigateur. C'est juste une copie de l'exemple simple de couleur aléatoire avec lequel nous avons déjà joué dans cet article. Maintenant, changez <code>btn.onclick</code> pour lui attribuer, tour à tour, les différentes valeurs qui suivent, et observez le résultat:</p> +Tout d'abord, faites une copie locale de [random-color-eventhandlerproperty.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventhandlerproperty.html), et ouvrez-le dans votre navigateur. C'est juste une copie de l'exemple simple de couleur aléatoire avec lequel nous avons déjà joué dans cet article. Maintenant, changez `btn.onclick` pour lui attribuer, tour à tour, les différentes valeurs qui suivent, et observez le résultat: -<ul> - <li><code><a href="/fr/docs/Web/API/GlobalEventHandlers/onfocus">btn.onfocus</a></code> et <code><a href="/fr/docs/Web/API/GlobalEventHandlers/onblur">btn.onblur</a></code> — La couleur change lorsque le bouton est net ou grisé (essayez d'appuyer sur la touche Tab pour l'activer et l'éteindre à nouveau). Ceux-ci sont souvent utilisés pour afficher des informations sur la façon de remplir les champs de formulaire lorsqu'ils sont sélectionnés, ou afficher un message d'erreur si un champ de formulaire vient d'être rempli avec une valeur incorrecte.</li> - <li><code><a href="/fr/docs/Web/API/GlobalEventHandlers/ondblclick">btn.ondblclick</a></code> — La couleur change seulement si l'élément est double-cliqué.</li> - <li><code><a href="/fr/docs/Web/API/GlobalEventHandlers/onkeypress">window.onkeypress</a></code>, <code><a href="/fr/docs/Web/API/GlobalEventHandlers/onkeydown">window.onkeydown</a></code>, <code><a href="/fr/docs/Web/API/GlobalEventHandlers/onkeyup">window.onkeyup</a></code> — La couleur change si l'on appuie sur une touche du clavier. <code>keypress</code> se réfère à un appui normal sur la touche (bouton appuyé puis relâché), alors que <code>keydown</code> et <code>keyup</code> se réfèrent respectivement à l'appui et au relâchement sur la touche. Notez que cela ne fonctionne pas si vous essayez d'enregistrer ce gestionnaire d'événement sur le bouton lui-même - nous avons dû l'enregistrer sur l'objet <a href="/fr/docs/Web/API/Window">window</a>, qui représente la fenêtre entière du navigateur.</li> - <li><code><a href="/fr/docs/Web/API/GlobalEventHandlers/onmouseover">btn.onmouseover</a></code> et <code><a href="/fr/docs/Web/API/GlobalEventHandlers/onmouseout">btn.onmouseout</a></code> — La couleur changera respectivement lorsque le pointeur de la souris survolera le bouton, ou lorsque le curseur arrêtera le survol du bouton pour s'éloigner de ce dernier.</li> -</ul> +- [`btn.onfocus`](/fr/docs/Web/API/GlobalEventHandlers/onfocus) et [`btn.onblur`](/fr/docs/Web/API/GlobalEventHandlers/onblur) — La couleur change lorsque le bouton est net ou grisé (essayez d'appuyer sur la touche Tab pour l'activer et l'éteindre à nouveau). Ceux-ci sont souvent utilisés pour afficher des informations sur la façon de remplir les champs de formulaire lorsqu'ils sont sélectionnés, ou afficher un message d'erreur si un champ de formulaire vient d'être rempli avec une valeur incorrecte. +- [`btn.ondblclick`](/fr/docs/Web/API/GlobalEventHandlers/ondblclick) — La couleur change seulement si l'élément est double-cliqué. +- [`window.onkeypress`](/fr/docs/Web/API/GlobalEventHandlers/onkeypress), [`window.onkeydown`](/fr/docs/Web/API/GlobalEventHandlers/onkeydown), [`window.onkeyup`](/fr/docs/Web/API/GlobalEventHandlers/onkeyup) — La couleur change si l'on appuie sur une touche du clavier. `keypress` se réfère à un appui normal sur la touche (bouton appuyé puis relâché), alors que `keydown` et `keyup` se réfèrent respectivement à l'appui et au relâchement sur la touche. Notez que cela ne fonctionne pas si vous essayez d'enregistrer ce gestionnaire d'événement sur le bouton lui-même - nous avons dû l'enregistrer sur l'objet [window](/fr/docs/Web/API/Window), qui représente la fenêtre entière du navigateur. +- [`btn.onmouseover`](/fr/docs/Web/API/GlobalEventHandlers/onmouseover) et [`btn.onmouseout`](/fr/docs/Web/API/GlobalEventHandlers/onmouseout) — La couleur changera respectivement lorsque le pointeur de la souris survolera le bouton, ou lorsque le curseur arrêtera le survol du bouton pour s'éloigner de ce dernier. -<p>Certains événements sont très généraux et disponibles presque partout (par exemple un gestionnaire <code>onclick</code> peut être enregistré sur presque n'importe quel élément), alors que certains sont plus spécifiques et seulement utiles dans certaines situations (par exemple, il est logique d'utiliser <a href="/fr/docs/Web/API/GlobalEventHandlers/GlobalEventHandlers.onplay">onplay</a> seulement sur des éléments spécifiques, comme des {{htmlelement("video")}}).</p> +Certains événements sont très généraux et disponibles presque partout (par exemple un gestionnaire `onclick` peut être enregistré sur presque n'importe quel élément), alors que certains sont plus spécifiques et seulement utiles dans certaines situations (par exemple, il est logique d'utiliser [onplay](/fr/docs/Web/API/GlobalEventHandlers/GlobalEventHandlers.onplay) seulement sur des éléments spécifiques, comme des {{htmlelement("video")}}). -<h3 id="Les_gestionnaires_d'événements_en_ligne_ne_les_utilisez_pas_!">Les gestionnaires d'événements en ligne : ne les utilisez pas !</h3> +### Les gestionnaires d'événements en ligne : ne les utilisez pas ! -<p>Vous pourriez également voir un motif comme celui-ci dans votre code:</p> +Vous pourriez également voir un motif comme celui-ci dans votre code: -<pre class="brush: html"><button onclick="bgChange()">Press me</button> -</pre> +```html +<button onclick="bgChange()">Press me</button> +``` -<pre class="brush: js">function bgChange() { +```js +function bgChange() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; -}</pre> +} +``` -<div class="note"> -<p><strong>Note :</strong> Vous trouverez le <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventhandlerattributes.html">code source complet </a>de cet exemple sur GitHub (également <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventhandlerattributes.html">le voir s'exécuter</a>).</p> -</div> +> **Note :** Vous trouverez le [code source complet ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventhandlerattributes.html)de cet exemple sur GitHub (également [le voir s'exécuter](http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventhandlerattributes.html)). + +La première méthode d'enregistrement des gestionnaires d'événements trouvés sur le Web impliquait des **attributs HTML du gestionnaire d'événement** (c'est-à-dire **les gestionnaires d'événements en ligne**) comme celui présenté ci-dessus — la valeur de l'attribut est littéralement le code JavaScript que vous souhaitez exécuter lorsque l'événement survient. L'exemple ci-dessus appelle une fonction définie dans un élément {{htmlelement("script")}} sur la même page, mais vous pouvez également insérer du JavaScript directement dans l'attribut comme par exemple : -<p>La première méthode d'enregistrement des gestionnaires d'événements trouvés sur le Web impliquait des <strong>attributs HTML du gestionnaire d'événement</strong> (c'est-à-dire <strong>les gestionnaires d'événements en ligne</strong>) comme celui présenté ci-dessus — la valeur de l'attribut est littéralement le code JavaScript que vous souhaitez exécuter lorsque l'événement survient. L'exemple ci-dessus appelle une fonction définie dans un élément {{htmlelement("script")}} sur la même page, mais vous pouvez également insérer du JavaScript directement dans l'attribut comme par exemple :</p> +```html +<button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button> +``` -<pre class="brush: html"><button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button></pre> +Vous trouverez des équivalents d'attributs HTML pour la plupart des propriétés du gestionnaire d'événement; cependant, vous ne devriez pas les utiliser — ils sont considérés comme une mauvaise pratique. Il peut sembler facile d'utiliser un attribut de gestionnaire d'événement si vous voulez avancer rapidement, mais ils deviennent rapidement ingérables et inefficaces. -<p>Vous trouverez des équivalents d'attributs HTML pour la plupart des propriétés du gestionnaire d'événement; cependant, vous ne devriez pas les utiliser — ils sont considérés comme une mauvaise pratique. Il peut sembler facile d'utiliser un attribut de gestionnaire d'événement si vous voulez avancer rapidement, mais ils deviennent rapidement ingérables et inefficaces.<br> - <br> - Pour commencer, ce n'est pas une bonne idée de mélanger votre HTML et votre JavaScript, car il deviennent difficile à analyser — garder votre JavaScript au même endroit est préférable; s'il se trouve dans un fichier séparé, vous pourrez l'appliquer à plusieurs documents HTML.</p> +Pour commencer, ce n'est pas une bonne idée de mélanger votre HTML et votre JavaScript, car il deviennent difficile à analyser — garder votre JavaScript au même endroit est préférable; s'il se trouve dans un fichier séparé, vous pourrez l'appliquer à plusieurs documents HTML. -<p>Même dans un fichier unique, les gestionnaires d'événement en ligne ne sont pas une bonne idée. Un bouton ça va, mais que faire si vous avez 100 boutons ? Vous devez ajouter 100 attributs au fichier; la maintenance se transformerait très vite en un cauchemar. Avec JavaScript, vous pouvez facilement ajouter une fonction de gestionnaire d'événement à tous les boutons de la page, peu importe leur nombre, en utilisant quelque chose comme ceci :</p> +Même dans un fichier unique, les gestionnaires d'événement en ligne ne sont pas une bonne idée. Un bouton ça va, mais que faire si vous avez 100 boutons ? Vous devez ajouter 100 attributs au fichier; la maintenance se transformerait très vite en un cauchemar. Avec JavaScript, vous pouvez facilement ajouter une fonction de gestionnaire d'événement à tous les boutons de la page, peu importe leur nombre, en utilisant quelque chose comme ceci : -<pre class="brush: js">var buttons = document.querySelectorAll('button'); +```js +var buttons = document.querySelectorAll('button'); -for (var i = 0; i < buttons.length; i++) { +for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = bgChange; -}</pre> +} +``` -<div class="note"> -<p><strong>Note :</strong> Séparer votre logique de programmation de votre contenu rend également votre site plus convivial pour les moteurs de recherche.</p> -</div> +> **Note :** Séparer votre logique de programmation de votre contenu rend également votre site plus convivial pour les moteurs de recherche. -<h3 id="addEventListener()_et_removeEventListener()">addEventListener() et removeEventListener()</h3> +### addEventListener() et removeEventListener() -<p>Le dernier type de mécanisme d'événement est défini dans le <a href="https://www.w3.org/TR/DOM-Level-2-Events/">Document Object Model (DOM) Level 2 Events</a> , qui fournit aux navigateurs une nouvelle fonction: <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>. Cela fonctionne de la même manière que les propriétés du gestionnaire d'événement, mais la syntaxe est évidemment différente. Nous pourrions réécrire notre exemple de couleur aléatoire comme ceci:</p> +Le dernier type de mécanisme d'événement est défini dans le [Document Object Model (DOM) Level 2 Events](https://www.w3.org/TR/DOM-Level-2-Events/) , qui fournit aux navigateurs une nouvelle fonction: [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener). Cela fonctionne de la même manière que les propriétés du gestionnaire d'événement, mais la syntaxe est évidemment différente. Nous pourrions réécrire notre exemple de couleur aléatoire comme ceci: -<pre class="brush: js">var btn = document.querySelector('button'); +```js +var btn = document.querySelector('button'); function bgChange() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; } -btn.addEventListener('click', bgChange);</pre> +btn.addEventListener('click', bgChange); +``` -<div class="note"> -<p><strong>Note :</strong> Vous trouverez le <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-addeventlistener.html">code source complet </a>de cet exemple sur GitHub (également <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-addeventlistener.html">le voir s'exécuter</a>).</p> -</div> +> **Note :** Vous trouverez le [code source complet ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-addeventlistener.html)de cet exemple sur GitHub (également [le voir s'exécuter](http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-addeventlistener.html)). -<p>Dans la fonction <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> , nous spécifions deux paramètres - le nom de l'événement pour lequel nous voulons enregistrer ce gestionnaire, et le code qui comprend la fonction du gestionnaire que nous voulons exécuter en réponse. Notez qu'il est parfaitement approprié de placer tout le code dans la fonction <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>, dans une fonction anonyme, comme ceci:</p> +Dans la fonction [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener) , nous spécifions deux paramètres - le nom de l'événement pour lequel nous voulons enregistrer ce gestionnaire, et le code qui comprend la fonction du gestionnaire que nous voulons exécuter en réponse. Notez qu'il est parfaitement approprié de placer tout le code dans la fonction [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener), dans une fonction anonyme, comme ceci: -<pre class="brush: js">btn.addEventListener('click', function() { +```js +btn.addEventListener('click', function() { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; -});</pre> +}); +``` + +Ce mécanisme a certains avantages par rapport aux mécanismes plus anciens discutés précédemment. Pour commencer, il existe une fonction réciproque, [`removeEventListener()`](/fr/docs/Web/API/EventTarget/removeEventListener), qui supprime un écouteur ajouté précédemment. Par exemple, cela supprimerait l'écouteur du premier bloc de code de cette section: + +```js +btn.removeEventListener('click', bgChange); +``` + +Ceci n'a pas beaucoup de sens pour les programmes simples et de petite taille, mais pour les programmes plus grands et plus complexes, cela peut améliorer l'efficacité, de nettoyer les anciens gestionnaires d'événements inutilisés. De plus, par exemple, cela vous permet d'avoir un même bouton qui effectue différentes actions dans des circonstances différentes - tout ce que vous avez à faire est d'ajouter / supprimer des gestionnaires d'événements convenablement. + +D'autre part, vous pouvez également enregistrer plusieurs gestionnaires pour le même écouteur. Les deux gestionnaires suivants ne seraient pas appliqués: + +```js +myElement.onclick = functionA; +myElement.onclick = functionB; +``` -<p>Ce mécanisme a certains avantages par rapport aux mécanismes plus anciens discutés précédemment. Pour commencer, il existe une fonction réciproque, <code><a href="/fr/docs/Web/API/EventTarget/removeEventListener">removeEventListener()</a></code>, qui supprime un écouteur ajouté précédemment. Par exemple, cela supprimerait l'écouteur du premier bloc de code de cette section:</p> +Comme la deuxième ligne remplacerait la valeur de `onclick` définie par le premier. Cependant, ceci fonctionnerait: -<pre class="brush: js">btn.removeEventListener('click', bgChange);</pre> +```js +myElement.addEventListener('click', functionA); +myElement.addEventListener('click', functionB); +``` -<p>Ceci n'a pas beaucoup de sens pour les programmes simples et de petite taille, mais pour les programmes plus grands et plus complexes, cela peut améliorer l'efficacité, de nettoyer les anciens gestionnaires d'événements inutilisés. De plus, par exemple, cela vous permet d'avoir un même bouton qui effectue différentes actions dans des circonstances différentes - tout ce que vous avez à faire est d'ajouter / supprimer des gestionnaires d'événements convenablement.<br> - <br> - D'autre part, vous pouvez également enregistrer plusieurs gestionnaires pour le même écouteur. Les deux gestionnaires suivants ne seraient pas appliqués:</p> +Les deux fonctions seraient maintenant exécutées lorsque l'élément est cliqué. -<pre class="brush: js">myElement.onclick = functionA; -myElement.onclick = functionB;</pre> +En outre, il existe un certain nombre d'autres fonctionnalités et options puissantes disponibles avec ce mécanisme d'événement. Celles-ci sont un peu hors de propos pour cet article, mais si vous voulez en savoir plus sur elles, jetez un oeil aux pages de référence de [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener) et [`removeEventListener()`](/fr/docs/Web/API/EventTarget/removeEventListener). -<p>Comme la deuxième ligne remplacerait la valeur de <code>onclick</code> définie par le premier. Cependant, ceci fonctionnerait:</p> +### Quel mécanisme devrais-je utiliser ? -<pre class="brush: js">myElement.addEventListener('click', functionA); -myElement.addEventListener('click', functionB);</pre> +Parmi les trois mécanismes, vous ne devriez certainement pas utiliser les attributs du gestionnaire d'événement HTML - ceux-ci sont obsolètes et constituent une mauvaise pratique, comme mentionné ci-dessus. -<p>Les deux fonctions seraient maintenant exécutées lorsque l'élément est cliqué.<br> - <br> - En outre, il existe un certain nombre d'autres fonctionnalités et options puissantes disponibles avec ce mécanisme d'événement. Celles-ci sont un peu hors de propos pour cet article, mais si vous voulez en savoir plus sur elles, jetez un oeil aux pages de référence de <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> et <code><a href="/fr/docs/Web/API/EventTarget/removeEventListener">removeEventListener()</a></code>.</p> +Les deux autres sont relativement interchangeables, au moins pour des utilisations simples: -<h3 id="Quel_mécanisme_devrais-je_utiliser">Quel mécanisme devrais-je utiliser ?</h3> -<p>Parmi les trois mécanismes, vous ne devriez certainement pas utiliser les attributs du gestionnaire d'événement HTML - ceux-ci sont obsolètes et constituent une mauvaise pratique, comme mentionné ci-dessus.<br> - <br> - Les deux autres sont relativement interchangeables, au moins pour des utilisations simples:<br> - </p> -<ul> - <li> Les propriétés du gestionnaire d'événement ont moins de puissance et d'options, mais une meilleure compatibilité entre les navigateurs (prise en charge depuis Internet Explorer 8). Vous devriez probablement commencer par ceux-ci pendant votre apprentissage.</li> - <li> Les événements du DOM Niveau 2 (<code>addEventListener()</code>, etc.) sont plus puissants, mais peuvent aussi devenir plus complexes et moins bien supportés (supportés depuis Internet Explorer 9). Vous devriez également vous entraîner avec, et tenter de les utiliser si possible.</li> -</ul> +- Les propriétés du gestionnaire d'événement ont moins de puissance et d'options, mais une meilleure compatibilité entre les navigateurs (prise en charge depuis Internet Explorer 8). Vous devriez probablement commencer par ceux-ci pendant votre apprentissage. +- Les événements du DOM Niveau 2 (`addEventListener()`, etc.) sont plus puissants, mais peuvent aussi devenir plus complexes et moins bien supportés (supportés depuis Internet Explorer 9). Vous devriez également vous entraîner avec, et tenter de les utiliser si possible. -<p>Les principaux avantages du troisième mécanisme : vous pouvez supprimer le code du gestionnaire d'événement si nécessaire en utilisant <code>removeEventListener()</code>, et vous pouvez ajouter plusieurs écouteurs du même type aux éléments si nécessaire. Par exemple, vous pouvez appeler <code>addEventListener('click', function() { ... })</code> sur un élément plusieurs fois, avec différentes fonctions spécifiées dans le deuxième argument. Cela est impossible avec les propriétés du gestionnaire d'événement car toute tentative ultérieure de définition d'une propriété remplacera les propriétés précédentes, par exemple:</p> +Les principaux avantages du troisième mécanisme : vous pouvez supprimer le code du gestionnaire d'événement si nécessaire en utilisant `removeEventListener()`, et vous pouvez ajouter plusieurs écouteurs du même type aux éléments si nécessaire. Par exemple, vous pouvez appeler `addEventListener('click', function() { ... })` sur un élément plusieurs fois, avec différentes fonctions spécifiées dans le deuxième argument. Cela est impossible avec les propriétés du gestionnaire d'événement car toute tentative ultérieure de définition d'une propriété remplacera les propriétés précédentes, par exemple: -<pre class="brush: js">element.onclick = function1; +```js +element.onclick = function1; element.onclick = function2; -etc.</pre> +etc. +``` -<div class="note"> -<p><strong>Note:</strong> Si vous êtes appelé à prendre en charge des navigateurs plus anciens qu'Internet Explorer 8 dans votre travail, vous risquez de rencontrer des difficultés, car ces anciens navigateurs utilisent des modèles d'événements différents des nouveaux navigateurs. Mais n'ayez crainte, la plupart des bibliothèques JavaScript (par exemple <code>jQuery</code>) ont des fonctions intégrées qui permettent d'éliminer les différences entre navigateurs. Ne vous en faites pas trop à ce stade de votre parcours d'apprentissage.</p> -</div> +> **Note :** Si vous êtes appelé à prendre en charge des navigateurs plus anciens qu'Internet Explorer 8 dans votre travail, vous risquez de rencontrer des difficultés, car ces anciens navigateurs utilisent des modèles d'événements différents des nouveaux navigateurs. Mais n'ayez crainte, la plupart des bibliothèques JavaScript (par exemple `jQuery`) ont des fonctions intégrées qui permettent d'éliminer les différences entre navigateurs. Ne vous en faites pas trop à ce stade de votre parcours d'apprentissage. -<h2 id="D'autres_concepts_liés_aux_événements">D'autres concepts liés aux événements</h2> +## D'autres concepts liés aux événements -<p>Dans cette section, nous aborderons brièvement quelques concepts avancés relatifs aux événements. Il n'est pas important de les comprendre entièrement à ce stade, mais cela pourra servir à expliquer certains modèles de code que vous rencontrerez probablement de temps en temps.</p> +Dans cette section, nous aborderons brièvement quelques concepts avancés relatifs aux événements. Il n'est pas important de les comprendre entièrement à ce stade, mais cela pourra servir à expliquer certains modèles de code que vous rencontrerez probablement de temps en temps. -<h3 id="L'objet_événement">L'objet événement</h3> +### L'objet événement -<p>Parfois, dans une fonction de gestionnaire d'événement, vous pouvez voir un paramètre spécifié avec un nom tel que <code>event</code>, <code>evt</code>, ou simplement <code>e</code> . C'est ce qu'on appelle l'objet événement, qui est automatiquement transmis aux gestionnaires d'événements pour fournir des fonctionnalités et des informations supplémentaires. Par exemple, réécrivons légèrement notre exemple de couleur aléatoire:</p> +Parfois, dans une fonction de gestionnaire d'événement, vous pouvez voir un paramètre spécifié avec un nom tel que `event`, `evt`, ou simplement `e` . C'est ce qu'on appelle l'objet événement, qui est automatiquement transmis aux gestionnaires d'événements pour fournir des fonctionnalités et des informations supplémentaires. Par exemple, réécrivons légèrement notre exemple de couleur aléatoire: -<pre class="brush: js">function bgChange(e) { +```js +function bgChange(e) { var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; e.target.style.backgroundColor = rndCol; console.log(e); } -btn.addEventListener('click', bgChange);</pre> +btn.addEventListener('click', bgChange); +``` -<div class="note"> -<p><strong>Note :</strong> Vous trouverez le <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventobject.html">code source complet </a>de cet exemple sur GitHub (également <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventobject.html">le voir s'exécuter</a>).</p> -</div> +> **Note :** Vous trouverez le [code source complet ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventobject.html)de cet exemple sur GitHub (également [le voir s'exécuter](http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventobject.html)). -<p>Ici, vous pouvez voir que nous incluons un objet événement, <strong>e</strong>, dans la fonction, et dans la fonction définissant un style de couleur d'arrière-plan sur <code>e.target</code> - qui est le bouton lui-même. La propriété <code>target</code> de l'objet événement est toujours une référence à l'élément sur lequel l'événement vient de se produire. Donc, dans cet exemple, nous définissons une couleur d'arrière-plan aléatoire sur le bouton, pas sur la page.</p> +Ici, vous pouvez voir que nous incluons un objet événement, **e**, dans la fonction, et dans la fonction définissant un style de couleur d'arrière-plan sur `e.target` - qui est le bouton lui-même. La propriété `target` de l'objet événement est toujours une référence à l'élément sur lequel l'événement vient de se produire. Donc, dans cet exemple, nous définissons une couleur d'arrière-plan aléatoire sur le bouton, pas sur la page. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez utiliser n'importe quel nom pour l'objet d'événement - il vous suffit de choisir un nom que vous pouvez ensuite utiliser pour le référencer dans la fonction du gestionnaire d'événements. <code>e</code>/<code>evt</code>/<code>event</code> sont les plus couramment utilisés par les développeurs car ils sont courts et faciles à retenir. C'est toujours bon de s'en tenir à une norme.</p> -</div> +> **Note :** Vous pouvez utiliser n'importe quel nom pour l'objet d'événement - il vous suffit de choisir un nom que vous pouvez ensuite utiliser pour le référencer dans la fonction du gestionnaire d'événements. `e`/`evt`/`event` sont les plus couramment utilisés par les développeurs car ils sont courts et faciles à retenir. C'est toujours bon de s'en tenir à une norme. -<p><code>e.target</code>est incroyablement utile lorsque vous voulez définir le même gestionnaire d'événements sur plusieurs éléments et affecter une action à chacun d'entre eux quand un événement se produit sur eux. Vous pourriez, par exemple, avoir un ensemble de 16 tuiles qui disparaissent quand on clique dessus. Il est utile de toujours pouvoir affecter une action à <code>e.target</code>, plutôt que de devoir la sélectionner de manière plus difficile. Dans l'exemple suivant (voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/useful-eventtarget.html">useful-eventtarget.html</a> pour le code source ; et ici pour le voir <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/useful-eventtarget.html">s'exécuter</a>), nous avons créé 16 éléments {{htmlelement("div")}} avec JavaScript. Quand nous les sélectionnons tous en utilisant {{domxref("document.querySelectorAll()")}}, puis que nous faisons une boucle sur chacun d'eux, en ajoutant un gestionnaire <code>onclick</code> à chacun de sorte qu'une couleur aléatoire est appliquée lorsque l'élément est cliqué:</p> +`e.target`est incroyablement utile lorsque vous voulez définir le même gestionnaire d'événements sur plusieurs éléments et affecter une action à chacun d'entre eux quand un événement se produit sur eux. Vous pourriez, par exemple, avoir un ensemble de 16 tuiles qui disparaissent quand on clique dessus. Il est utile de toujours pouvoir affecter une action à `e.target`, plutôt que de devoir la sélectionner de manière plus difficile. Dans l'exemple suivant (voir [useful-eventtarget.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/useful-eventtarget.html) pour le code source ; et ici pour le voir [s'exécuter](http://mdn.github.io/learning-area/javascript/building-blocks/events/useful-eventtarget.html)), nous avons créé 16 éléments {{htmlelement("div")}} avec JavaScript. Quand nous les sélectionnons tous en utilisant {{domxref("document.querySelectorAll()")}}, puis que nous faisons une boucle sur chacun d'eux, en ajoutant un gestionnaire `onclick` à chacun de sorte qu'une couleur aléatoire est appliquée lorsque l'élément est cliqué: -<pre class="brush: js">var divs = document.querySelectorAll('div'); +```js +var divs = document.querySelectorAll('div'); -for (var i = 0; i < divs.length; i++) { +for (var i = 0; i < divs.length; i++) { divs[i].onclick = function(e) { e.target.style.backgroundColor = bgChange(); } -}</pre> +} +``` -<h4>Résultat</h4> +#### Résultat -<p>Le résultat est le suivant (essayez de cliquer dessus - amusez-vous):</p> +Le résultat est le suivant (essayez de cliquer dessus - amusez-vous): -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Useful event target example</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Useful event target example</title> + <style> div { background-color: red; height: 100px; width: 25%; float: left; } - </style> - </head> - <body> - <script> - for (var i = 1; i <= 16; i++) { + </style> + </head> + <body> + <script> + for (var i = 1; i <= 16; i++) { var myDiv = document.createElement('div'); document.body.appendChild(myDiv); } @@ -305,50 +328,55 @@ for (var i = 0; i < divs.length; i++) { var divs = document.querySelectorAll('div'); - for (var i = 0; i < divs.length; i++) { + for (var i = 0; i < divs.length; i++) { divs[i].onclick = function(e) { e.target.style.backgroundColor = bgChange(); } } - </script> - </body> -</html></pre> - -<p>{{ EmbedLiveSample('Résultat', '100%', 400, "", "", "hide-codepen-jsfiddle") }}</p> - -<p>La plupart des gestionnaires d'événements que vous rencontrerez ne disposent que d'un ensemble standard de propriétés et de fonctions (méthodes) disponibles sur l'objet événement (voir la liste complète sur {{domxref("Event")}} ). Cependant, certains gestionnaires plus avancés ajoutent des propriétés spécialisées contenant des données supplémentaires dont ils ont besoin pour fonctionner. Le <a href="/fr/docs/Web/API/MediaRecorder_API">Media Recorder API</a>, par exemple, a un événement <code>dataavailable</code> , qui se déclenche quand un fichier audio ou vidéo a été enregistré et est disponible pour être utilisé (par exemple, pour l'enregistrer ou le lire). L'objet événement du gestionnaire <a href="/fr/docs/Web/API/MediaRecorder/ondataavailable">ondataavailable</a> correspondant dispose d'une propriété <code>data</code> contenant les données audio ou vidéo enregistrées pour vous permettre d'y accéder et de l'utiliser.</p> - -<h3 id="Éviter_le_comportement_par_défaut">Éviter le comportement par défaut</h3> - -<p>Parfois, vous rencontrerez une situation où vous voudrez arrêter un événement qui adopte son comportement par défaut. L'exemple le plus courant est celui d'un formulaire Web, par exemple un formulaire d'inscription personnalisé. Lorsque vous remplissez les détails et appuyez sur le bouton "Soumettre", le comportement naturel consiste à soumettre les données à une page spécifiée sur le serveur pour traitement, et le navigateur redirige vers une page de "message de réussite" quelconque (ou la même page, si une autre n'est pas spécifiée.).<br> - <br> - Le problème survient lorsque l'utilisateur n'a pas soumis les données correctement. En tant que développeur, vous devez arrêter la soumission au serveur et lui envoyer un message d'erreur indiquant ce qui ne va pas et ce qui doit être fait pour corriger les erreurs. Certains navigateurs prennent en charge les fonctions de validation automatique des données de formulaire, mais comme beaucoup ne le font pas, il est conseillé de ne pas vous y fier et d'implémenter vos propres contrôles de validation. Regardons un exemple simple.<br> - <br> - Tout d'abord, un simple formulaire HTML qui vous oblige à entrer votre nom et votre prénom:</p> - -<pre class="brush: html"><form> - <div> - <label for="fname">First name: </label> - <input id="fname" type="text"> - </div> - <div> - <label for="lname">Last name: </label> - <input id="lname" type="text"> - </div> - <div> - <input id="submit" type="submit"> - </div> -</form> -<p></p></pre> - -<pre class="brush: css hidden">div { + </script> + </body> +</html> +``` + +{{ EmbedLiveSample('Résultat', '100%', 400, "", "", "hide-codepen-jsfiddle") }} + +La plupart des gestionnaires d'événements que vous rencontrerez ne disposent que d'un ensemble standard de propriétés et de fonctions (méthodes) disponibles sur l'objet événement (voir la liste complète sur {{domxref("Event")}} ). Cependant, certains gestionnaires plus avancés ajoutent des propriétés spécialisées contenant des données supplémentaires dont ils ont besoin pour fonctionner. Le [Media Recorder API](/fr/docs/Web/API/MediaRecorder_API), par exemple, a un événement `dataavailable` , qui se déclenche quand un fichier audio ou vidéo a été enregistré et est disponible pour être utilisé (par exemple, pour l'enregistrer ou le lire). L'objet événement du gestionnaire [ondataavailable](/fr/docs/Web/API/MediaRecorder/ondataavailable) correspondant dispose d'une propriété `data` contenant les données audio ou vidéo enregistrées pour vous permettre d'y accéder et de l'utiliser. + +### Éviter le comportement par défaut + +Parfois, vous rencontrerez une situation où vous voudrez arrêter un événement qui adopte son comportement par défaut. L'exemple le plus courant est celui d'un formulaire Web, par exemple un formulaire d'inscription personnalisé. Lorsque vous remplissez les détails et appuyez sur le bouton "Soumettre", le comportement naturel consiste à soumettre les données à une page spécifiée sur le serveur pour traitement, et le navigateur redirige vers une page de "message de réussite" quelconque (ou la même page, si une autre n'est pas spécifiée.). + +Le problème survient lorsque l'utilisateur n'a pas soumis les données correctement. En tant que développeur, vous devez arrêter la soumission au serveur et lui envoyer un message d'erreur indiquant ce qui ne va pas et ce qui doit être fait pour corriger les erreurs. Certains navigateurs prennent en charge les fonctions de validation automatique des données de formulaire, mais comme beaucoup ne le font pas, il est conseillé de ne pas vous y fier et d'implémenter vos propres contrôles de validation. Regardons un exemple simple. + +Tout d'abord, un simple formulaire HTML qui vous oblige à entrer votre nom et votre prénom: + +```html +<form> + <div> + <label for="fname">First name: </label> + <input id="fname" type="text"> + </div> + <div> + <label for="lname">Last name: </label> + <input id="lname" type="text"> + </div> + <div> + <input id="submit" type="submit"> + </div> +</form> +<p></p> +``` + +```css hidden +div { margin-bottom: 10px; } -</pre> +``` -<p>Maintenant un peu de JavaScript - ici nous implémentons une vérification très simple dans un gestionnaire d'événement <a href="/fr/docs/Web/API/GlobalEventHandlers/onsubmit">onsubmit</a> (l'événement submit est renvoyé sur un formulaire quand il est soumis) qui vérifie si les champs de texte sont vides. Si c'est le cas, nous appelons la fonction <code><a href="/fr/docs/Web/API/Event/preventDefault">preventDefault()</a></code> sur l'objet événement - ce qui stoppe la soumission du formulaire - puis nous affichons un message d'erreur dans le paragraphe sous notre formulaire pour indiquer à l'utilisateur ce qui ne va pas :</p> +Maintenant un peu de JavaScript - ici nous implémentons une vérification très simple dans un gestionnaire d'événement [onsubmit](/fr/docs/Web/API/GlobalEventHandlers/onsubmit) (l'événement submit est renvoyé sur un formulaire quand il est soumis) qui vérifie si les champs de texte sont vides. Si c'est le cas, nous appelons la fonction [`preventDefault()`](/fr/docs/Web/API/Event/preventDefault) sur l'objet événement - ce qui stoppe la soumission du formulaire - puis nous affichons un message d'erreur dans le paragraphe sous notre formulaire pour indiquer à l'utilisateur ce qui ne va pas : -<pre class="brush: js">var form = document.querySelector('form'); +```js +var form = document.querySelector('form'); var fname = document.getElementById('fname'); var lname = document.getElementById('lname'); var submit = document.getElementById('submit'); @@ -359,26 +387,26 @@ form.onsubmit = function(e) { e.preventDefault(); para.textContent = 'You need to fill in both names!'; } -}</pre> +} +``` -<p>Évidemment, cette validation est assez faible - cela n'empêcherait pas l'utilisateur de valider le formulaire avec des espaces ou des nombres entrés dans les champs, par exemple - mais cela est acceptable. Le résultat est le suivant :</p> +Évidemment, cette validation est assez faible - cela n'empêcherait pas l'utilisateur de valider le formulaire avec des espaces ou des nombres entrés dans les champs, par exemple - mais cela est acceptable. Le résultat est le suivant : -<p>{{ EmbedLiveSample('Éviter_le_comportement_par_défaut', '100%', 140, "", "", "hide-codepen-jsfiddle") }}</p> +{{ EmbedLiveSample('Éviter_le_comportement_par_défaut', '100%', 140, "", "", "hide-codepen-jsfiddle") }} -<div class="note"> -<p><strong>Note :</strong> pour le code source, voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/preventdefault-validation.html">preventdefault-validation.html</a> (et le voir s'exécuter <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/preventdefault-validation.html">ici</a>.)</p> -</div> +> **Note :** pour le code source, voir [preventdefault-validation.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/preventdefault-validation.html) (et le voir s'exécuter [ici](http://mdn.github.io/learning-area/javascript/building-blocks/events/preventdefault-validation.html).) -<h3 id="Le_bouillonnement_et_la_capture">Le bouillonnement et la capture</h3> +### Le bouillonnement et la capture -<p>Le dernier sujet à aborder ici est quelque chose que vous ne rencontrerez pas souvent, mais cela peut être une vraie difficulté si vous ne le comprenez pas. Le bouillonnement et la capture d'événements sont deux mécanismes qui décrivent ce qui se passe lorsque deux gestionnaires du même type d'événement sont activés sur un même élément. Regardons un exemple pour faciliter cela - ouvrez l'exemple <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box.html">show-video-box.html</a> dans un nouvel onglet (et le <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box.html">code source </a>dans un autre). C'est également disponible en live ci-dessous.</p> +Le dernier sujet à aborder ici est quelque chose que vous ne rencontrerez pas souvent, mais cela peut être une vraie difficulté si vous ne le comprenez pas. Le bouillonnement et la capture d'événements sont deux mécanismes qui décrivent ce qui se passe lorsque deux gestionnaires du même type d'événement sont activés sur un même élément. Regardons un exemple pour faciliter cela - ouvrez l'exemple [show-video-box.html](http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box.html) dans un nouvel onglet (et le [code source ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box.html)dans un autre). C'est également disponible en live ci-dessous. -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Show video box example</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Show video box example</title> + <style> div { position: absolute; top: 50%; @@ -404,20 +432,20 @@ form.onsubmit = function(e) { margin: 40px auto; } - </style> - </head> - <body> - <button>Display video</button> + </style> + </head> + <body> + <button>Display video</button> - <div class="hidden"> - <video> - <source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.mp4" type="video/mp4"> - <source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.webm" type="video/webm"> - <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> - </video> - </div> + <div class="hidden"> + <video> + <source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.mp4" type="video/mp4"> + <source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.webm" type="video/webm"> + <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> + </video> + </div> - <script> + <script> var btn = document.querySelector('button'); var videoBox = document.querySelector('div'); @@ -441,128 +469,121 @@ form.onsubmit = function(e) { video.play(); }); - </script> - </body> -</html></pre> + </script> + </body> +</html> +``` -<p>{{ EmbedLiveSample('Le_bouillonnement_et_la_capture', '100%', 500, "", "", "hide-codepen-jsfiddle") }}</p> +{{ EmbedLiveSample('Le_bouillonnement_et_la_capture', '100%', 500, "", "", "hide-codepen-jsfiddle") }} -<p>Ceci est un exemple assez simple qui montre et cache une balise {{htmlelement("div")}} avec une balise {{htmlelement("video")}} à l'intérieur:</p> +Ceci est un exemple assez simple qui montre et cache une balise {{htmlelement("div")}} avec une balise {{htmlelement("video")}} à l'intérieur: -<pre class="brush: html"><button>Display video</button> +```html +<button>Display video</button> -<div class="hidden"> - <video> - <source src="rabbit320.mp4" type="video/mp4"> - <source src="rabbit320.webm" type="video/webm"> - <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> - </video> -</div></pre> +<div class="hidden"> + <video> + <source src="rabbit320.mp4" type="video/mp4"> + <source src="rabbit320.webm" type="video/webm"> + <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> + </video> +</div> +``` -<p>Quand le {{htmlelement("button")}} est cliqué, la vidéo est affichée, en changeant l'attribut de classe sur la balise <code><div></code> de <code>hidden</code> à <code>showing</code> ( le CSS de l'exemple contient ces deux classes, qui positionnent respectivement la boîte hors de l'écran et sur l'écran.) :</p> +Quand le {{htmlelement("button")}} est cliqué, la vidéo est affichée, en changeant l'attribut de classe sur la balise `<div>` de `hidden` à `showing` ( le CSS de l'exemple contient ces deux classes, qui positionnent respectivement la boîte hors de l'écran et sur l'écran.) : -<pre class="brush: js">btn.onclick = function() { +```js +btn.onclick = function() { videoBox.setAttribute('class', 'showing'); -}</pre> +} +``` -<p>Nous ajoutons ensuite quelques gestionnaires d'événements <code>onclick</code> supplémentaires - le premier à <code><div></code> et le second à <code><video></code>. L'idée est que lorsque l'on clique sur la zone du <code><div></code> en dehors de la vidéo, la boîte doit être masquée à nouveau; Lorsque la vidéo elle-même est cliquée, la vidéo devrait commencer à jouer. </p> +Nous ajoutons ensuite quelques gestionnaires d'événements `onclick` supplémentaires - le premier à `<div>` et le second à `<video>`. L'idée est que lorsque l'on clique sur la zone du `<div>` en dehors de la vidéo, la boîte doit être masquée à nouveau; Lorsque la vidéo elle-même est cliquée, la vidéo devrait commencer à jouer. -<pre>videoBox.onclick = function() { - videoBox.setAttribute('class', 'hidden'); -}; + videoBox.onclick = function() { + videoBox.setAttribute('class', 'hidden'); + }; -video.onclick = function() { - video.play(); -};</pre> + video.onclick = function() { + video.play(); + }; + +Mais il y a un problème - actuellement, lorsque vous cliquez sur la vidéo, elle commence à jouer, mais cela entraîne le fait que `<div>` est également caché en même temps. C'est parce que la vidéo est dans le `<div>` - elle en fait partie - alors que cliquer sur la vidéo lance les _deux_ gestionnaires d'événements ci-dessus. + +#### Explication du bouillonnement et de la capture -<p>Mais il y a un problème - actuellement, lorsque vous cliquez sur la vidéo, elle commence à jouer, mais cela entraîne le fait que <code><div></code> est également caché en même temps. C'est parce que la vidéo est dans le <code><div></code> - elle en fait partie - alors que cliquer sur la vidéo lance les <em>deux</em> gestionnaires d'événements ci-dessus.</p> +Quand un événement se déclenche sur un élément qui a des éléments parents (p.ex. l'élément {{htmlelement("video")}} dans notre cas), les navigateurs modernes utilisent deux phases différentes: la phase de **capture** et la phase de **bouillonnement**. -<h4 id="Explication_du_bouillonnement_et_de_la_capture">Explication du bouillonnement et de la capture</h4> +Dans la phase de capture: -<p>Quand un événement se déclenche sur un élément qui a des éléments parents (p.ex. l'élément {{htmlelement("video")}} dans notre cas), les navigateurs modernes utilisent deux phases différentes: la phase de <strong>capture</strong> et la phase de <strong>bouillonnement</strong>.<br> - <br> - Dans la phase de capture:</p> +- Le navigateur vérifie si l'ancêtre le plus éloigné de l'élément ({{htmlelement("html")}}) dispose d'un gestionnaire d'événement `onclick` enregistré pendant la phase de capture et le lance si c'est le cas. +- Ensuite, il passe à l'élément suivant à l'intérieur de `<html>` et fait la même chose, puis la suivante, et ainsi de suite jusqu'à ce qu'il atteigne l'élément sur lequel on a cliqué. -<ul> - <li>Le navigateur vérifie si l'ancêtre le plus éloigné de l'élément ({{htmlelement("html")}}) dispose d'un gestionnaire d'événement <code>onclick</code> enregistré pendant la phase de capture et le lance si c'est le cas.</li> - <li>Ensuite, il passe à l'élément suivant à l'intérieur de <code><html></code> et fait la même chose, puis la suivante, et ainsi de suite jusqu'à ce qu'il atteigne l'élément sur lequel on a cliqué.</li> -</ul> +Dans la phase de bouillonnement, l'opposé exact se produit: -<p>Dans la phase de bouillonnement, l'opposé exact se produit:<br> - <br> - Le navigateur vérifie si l'élément qui a été cliqué a un gestionnaire d'événement <code>onclick</code> enregistré dans la phase de bouillonnement et l'exécute si c'est le cas.<br> - Ensuite, il passe à l'élément ancêtre immédiat et fait la même chose, puis le suivant, et ainsi de suite jusqu'à ce qu'il atteigne l'élément <code><html></code>.</p> +Le navigateur vérifie si l'élément qui a été cliqué a un gestionnaire d'événement `onclick` enregistré dans la phase de bouillonnement et l'exécute si c'est le cas. + Ensuite, il passe à l'élément ancêtre immédiat et fait la même chose, puis le suivant, et ainsi de suite jusqu'à ce qu'il atteigne l'élément `<html>`. -<p><a href="https://mdn.mozillademos.org/files/16064/bubbling-capturing.png"><img alt="" src="bubbling-capturing.png"></a></p> +[](https://mdn.mozillademos.org/files/16064/bubbling-capturing.png) -<p>(Cliquez sur l'image pour l'agrandir et la voir traduite en français.)</p> +(Cliquez sur l'image pour l'agrandir et la voir traduite en français.) -<p>Dans les navigateurs modernes, par défaut, tous les gestionnaires d'événements sont enregistrés dans la phase de bouillonnement. Ainsi, dans notre exemple actuel, lorsque vous cliquez sur la vidéo, l'événement click fait un bouillonnement de l'élément <code><video></code> vers l'élément <code><html></code>. Comme ceci :</p> +Dans les navigateurs modernes, par défaut, tous les gestionnaires d'événements sont enregistrés dans la phase de bouillonnement. Ainsi, dans notre exemple actuel, lorsque vous cliquez sur la vidéo, l'événement click fait un bouillonnement de l'élément `<video>` vers l'élément `<html>`. Comme ceci : -<ul> - <li>Il trouve d'abord le gestionnaire <code>video.onclick...</code> et le lance, de manière à ce que la vidéo soit jouée en premier.</li> - <li>Ensuite il trouve le gestionnaire <code>videoBox.onclick...</code> et le lance, de sorte que la vidéo est cachée.</li> -</ul> +- Il trouve d'abord le gestionnaire `video.onclick...` et le lance, de manière à ce que la vidéo soit jouée en premier. +- Ensuite il trouve le gestionnaire `videoBox.onclick...` et le lance, de sorte que la vidéo est cachée. -<h4 id="Régler_le_problème_avec_stopPropagation()">Régler le problème avec stopPropagation()</h4> +#### Régler le problème avec stopPropagation() -<p>C'est un comportement ennuyeux, mais il y a un moyen de l'éviter ! L'objet événement standard dispose d'une fonction appelée <code><a href="/fr/docs/Web/API/Event/stopPropagation">stopPropagation()</a></code>, qui, lorsqu'il est invoqué sur l'objet événement d'un gestionnaire, fait en sorte que le gestionnaire soit exécuté, mais l'événement ne remonte pas plus haut dans la chaîne, et donc plus aucun autre gestionnaire ne sera exécuté.<br> - <br> - Nous pouvons donc résoudre notre problème actuel en changeant la fonction du deuxième gestionnaire dans le bloc de code précédent comme ceci:</p> +C'est un comportement ennuyeux, mais il y a un moyen de l'éviter ! L'objet événement standard dispose d'une fonction appelée [`stopPropagation()`](/fr/docs/Web/API/Event/stopPropagation), qui, lorsqu'il est invoqué sur l'objet événement d'un gestionnaire, fait en sorte que le gestionnaire soit exécuté, mais l'événement ne remonte pas plus haut dans la chaîne, et donc plus aucun autre gestionnaire ne sera exécuté. -<pre class="brush: js">video.onclick = function(e) { +Nous pouvons donc résoudre notre problème actuel en changeant la fonction du deuxième gestionnaire dans le bloc de code précédent comme ceci: + +```js +video.onclick = function(e) { e.stopPropagation(); video.play(); -};</pre> +}; +``` -<p>Vous pouvez faire une copie locale du <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box.html">code source show-video-box.html </a> et le modifier vous-même ou regarder le résultat ici : <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box-fixed.html">show-video-box-fixed.html</a> (ou voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box-fixed.html">code source</a>).</p> +Vous pouvez faire une copie locale du [code source show-video-box.html ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box.html)et le modifier vous-même ou regarder le résultat ici : [show-video-box-fixed.html](http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box-fixed.html) (ou voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box-fixed.html)). -<div class="note"> -<p><strong>Note :</strong> Pourquoi s'embêter à capturer et bouillonner ? Eh bien, aux heures sombres où les navigateurs étaien peu compatibles entre eux qu'ils ne le sont aujourd'hui, Netscape n'utilisait que la capture d'événements, et Internet Explorer n'utilisait que les bouillonnements. Quand le W3C a décidé d'essayer de normaliser le comportement et de parvenir à un consensus, ils en sont arrivés à ce système qui inclue les deux, qui est celui implémenté dans les navigateurs modernes.</p> -</div> +> **Note :** Pourquoi s'embêter à capturer et bouillonner ? Eh bien, aux heures sombres où les navigateurs étaien peu compatibles entre eux qu'ils ne le sont aujourd'hui, Netscape n'utilisait que la capture d'événements, et Internet Explorer n'utilisait que les bouillonnements. Quand le W3C a décidé d'essayer de normaliser le comportement et de parvenir à un consensus, ils en sont arrivés à ce système qui inclue les deux, qui est celui implémenté dans les navigateurs modernes. -<div class="note"> -<p><strong>Note :</strong> Comme mentionné ci-dessus, par défaut, tous les gestionnaires d'événements sont enregistrés dans la phase de bouillonnement, ce qui est plus logique la plupart du temps. Si vous voulez vraiment enregistrer un événement dans la phase de capture, vous pouvez le faire en enregistrant votre gestionnaire avec <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>, et en positionnant la troisième propriété, qui est optionnelle, sur<code>true</code>.</p> -</div> +> **Note :** Comme mentionné ci-dessus, par défaut, tous les gestionnaires d'événements sont enregistrés dans la phase de bouillonnement, ce qui est plus logique la plupart du temps. Si vous voulez vraiment enregistrer un événement dans la phase de capture, vous pouvez le faire en enregistrant votre gestionnaire avec [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener), et en positionnant la troisième propriété, qui est optionnelle, sur`true`. + +#### Délégation d'événement + +Le bouillonnement nous permet également de tirer parti de la délégation d'événements - ce concept repose sur le fait que si vous voulez exécuter du code lorsque vous cliquez sur l'un des nombreux éléments enfants, vous pouvez définir l'écouteur d'événement sur leur parent et ainsi leur répercuter les événement, plutôt que de devoir définir l'écouteur d'événement sur chaque enfant individuellement. -<h4 id="Délégation_d'événement">Délégation d'événement</h4> +Un bon exemple est une série d'éléments de liste - si vous voulez que chacun d'eux fasse apparaître un message lorsque vous cliquez dessus, vous pouvez définir l'écouteur d'événement `click` sur la balise parente `<ul>`, et il apparaîtra sur les éléments de la liste. -<p>Le bouillonnement nous permet également de tirer parti de la délégation d'événements - ce concept repose sur le fait que si vous voulez exécuter du code lorsque vous cliquez sur l'un des nombreux éléments enfants, vous pouvez définir l'écouteur d'événement sur leur parent et ainsi leur répercuter les événement, plutôt que de devoir définir l'écouteur d'événement sur chaque enfant individuellement.<br> - <br> - Un bon exemple est une série d'éléments de liste - si vous voulez que chacun d'eux fasse apparaître un message lorsque vous cliquez dessus, vous pouvez définir l'écouteur d'événement <code>click</code> sur la balise parente <code><ul></code>, et il apparaîtra sur les éléments de la liste.</p> +Ce concept est expliqué plus loin sur le blog de David Walsh, avec de multiples exemples - voir [How JavaScript Event Delegation Works](https://davidwalsh.name/event-delegate). -<p>Ce concept est expliqué plus loin sur le blog de David Walsh, avec de multiples exemples - voir <a href="https://davidwalsh.name/event-delegate">How JavaScript Event Delegation Works</a>.</p> +## Conclusion -<h2 id="Conclusion">Conclusion</h2> +Vous devriez maintenant maîtriser tout ce que vous devez savoir sur les événements Web à ce stade de votre apprentissage. Comme mentionné ci-dessus, les événements ne font pas vraiment partie du langage du noyau JavaScript principal - ils sont définis dans les API Web du navigateur. -<p>Vous devriez maintenant maîtriser tout ce que vous devez savoir sur les événements Web à ce stade de votre apprentissage. Comme mentionné ci-dessus, les événements ne font pas vraiment partie du langage du noyau JavaScript principal - ils sont définis dans les API Web du navigateur.<br> - <br> - En outre, il est important de comprendre que les différents contextes dans lesquels JavaScript est utilisé tendent à avoir des modèles d'événements différents - des API Web à d'autres domaines tels que WebExtensions du navigateur et Node.js (JavaScript côté serveur). Nous ne nous attendons pas à ce que vous compreniez tous ces domaines maintenant, mais cela aide certainement à comprendre les bases des événements à mesure que vous avancez dans l'apprentissage du développement Web.</p> +En outre, il est important de comprendre que les différents contextes dans lesquels JavaScript est utilisé tendent à avoir des modèles d'événements différents - des API Web à d'autres domaines tels que WebExtensions du navigateur et Node.js (JavaScript côté serveur). Nous ne nous attendons pas à ce que vous compreniez tous ces domaines maintenant, mais cela aide certainement à comprendre les bases des événements à mesure que vous avancez dans l'apprentissage du développement Web. -<p>S'il y a quelque chose que vous n'avez pas compris, n'hésitez pas à relire l'article, ou <a href="/fr/Learn#Contact_us">contactez-nous </a>pour demander de l'aide.</p> +S'il y a quelque chose que vous n'avez pas compris, n'hésitez pas à relire l'article, ou [contactez-nous ](/fr/Learn#Contact_us)pour demander de l'aide. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="http://www.quirksmode.org/js/events_order.html">Event order</a> (discussion sur la capture et le bouillonnement) — une pièce superbement détaillée de Peter-Paul Koch.</li> - <li><a href="http://www.quirksmode.org/js/events_access.html">Event accessing</a> (discussion sur l'objet événement) — une autre pièce superbement détaillée de Peter-Paul Koch.</li> - <li><a href="/fr/docs/Web/Events">Event reference</a></li> -</ul> +- [Event order](http://www.quirksmode.org/js/events_order.html) (discussion sur la capture et le bouillonnement) — une pièce superbement détaillée de Peter-Paul Koch. +- [Event accessing](http://www.quirksmode.org/js/events_access.html) (discussion sur l'objet événement) — une autre pièce superbement détaillée de Peter-Paul Koch. +- [Event reference](/fr/docs/Web/Events) -<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}} -<p> </p> -<h2 id="Dans_ce_module">Dans ce module</h2> -<ul> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/conditionals">Prendre des décisions dans le code - les conditions</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Looping_code">Les boucles dans le code</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Fonctions">les fonctions - des blocs de code réutilisables</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Construisez votre propre fonction</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Return_values">les valeurs de retour des fonction</a><a href="/fr/docs/Learn/JavaScript/Building_blocks/Return_values">s</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">Introduction aux événement</a><a href="/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">s</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Image_gallery">Galerie d'images</a></li> -</ul> +## Dans ce module -<p> </p> +- [Prendre des décisions dans le code - les conditions](/fr/Apprendre/JavaScript/Building_blocks/conditionals) +- [Les boucles dans le code](/fr/Apprendre/JavaScript/Building_blocks/Looping_code) +- [les fonctions - des blocs de code réutilisables](/fr/Apprendre/JavaScript/Building_blocks/Fonctions) +- [Construisez votre propre fonction](/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function) +- [les valeurs de retour des fonction](/fr/Apprendre/JavaScript/Building_blocks/Return_values)[s](/fr/docs/Learn/JavaScript/Building_blocks/Return_values) +- [Introduction aux événement](/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements)[s](/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements) +- [Galerie d'images](/fr/docs/Apprendre/JavaScript/Building_blocks/Image_gallery) diff --git a/files/fr/learn/javascript/building_blocks/functions/index.md b/files/fr/learn/javascript/building_blocks/functions/index.md index eb804d4dcf..afd792fac3 100644 --- a/files/fr/learn/javascript/building_blocks/functions/index.md +++ b/files/fr/learn/javascript/building_blocks/functions/index.md @@ -4,324 +4,387 @@ slug: Learn/JavaScript/Building_blocks/Functions translation_of: Learn/JavaScript/Building_blocks/Functions original_slug: Apprendre/JavaScript/Building_blocks/Fonctions --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}</div> - -<p>Les <strong>fonctions</strong> sont un autre concept essentiel de la programmation, qui permettent de stocker dans un bloc défini une partie de code qui effectue une seule tâche afin de l'appeler plus tard lorsque nous en avons besoin en utilisant une seule commande courte — au lieu de ré-écrire l'intégralité de ce code à chaque fois. Dans cet article nous explorons les concepts fondamentaux inhérents aux fonctions tels que la syntaxe de base, comment les définir et les invoquer, leur portée et leurs paramètres.</p> +Les **fonctions** sont un autre concept essentiel de la programmation, qui permettent de stocker dans un bloc défini une partie de code qui effectue une seule tâche afin de l'appeler plus tard lorsque nous en avons besoin en utilisant une seule commande courte — au lieu de ré-écrire l'intégralité de ce code à chaque fois. Dans cet article nous explorons les concepts fondamentaux inhérents aux fonctions tels que la syntaxe de base, comment les définir et les invoquer, leur portée et leurs paramètres. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prerequis:</th> - <td>Culture informatique basique, compréhension basique du HTML et du CSS, <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript...</a></td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Comprendre les concepts fondamentaux des fonctions JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prerequis:</th> + <td> + Culture informatique basique, compréhension basique du HTML et du CSS, + <a href="/fr/docs/Learn/JavaScript/First_steps" + >Premiers pas en JavaScript...</a + > + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td>Comprendre les concepts fondamentaux des fonctions JavaScript.</td> + </tr> + </tbody> </table> -<h2 id="Où_trouve-ton_des_fonctions">Où trouve-t'on des fonctions ?</h2> +## Où trouve-t'on des fonctions ? -<p>En JavaScript, vous trouverez des fonctions partout. En fait, nous avons utilisé des fonctions depuis le début du cours ; nous n'en avons simplement pas beaucoup parlé. Toutefois, il est maintenant temps de parler des fonctions de manière explicite et d'explorer réellement leur syntaxe.</p> +En JavaScript, vous trouverez des fonctions partout. En fait, nous avons utilisé des fonctions depuis le début du cours ; nous n'en avons simplement pas beaucoup parlé. Toutefois, il est maintenant temps de parler des fonctions de manière explicite et d'explorer réellement leur syntaxe. -<p>Presque à chaque fois que vous utilisez une structure de JavaScript qui utilise une paire de parenthèses — <code>()</code> — et que vous n'utilisez <strong>pas</strong> une structure usuelle et intégrée du langage telle que les boucles <a href="/fr/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop">for</a>, <a href="/fr/Learn/JavaScript/Building_blocks/Looping_code#while_and_do_..._while">while </a>ou<a href="/fr/Learn/JavaScript/Building_blocks/Looping_code#while_and_do_..._while"> do...while </a>, ou une déclaration <a href="/fr/Learn/JavaScript/Building_blocks/conditionals#if_..._else_statements">if...else </a>, vous utilisez une fonction.</p> +Presque à chaque fois que vous utilisez une structure de JavaScript qui utilise une paire de parenthèses — `()` — et que vous n'utilisez **pas** une structure usuelle et intégrée du langage telle que les boucles [for](/fr/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop), [while ](/fr/Learn/JavaScript/Building_blocks/Looping_code#while_and_do_..._while)ou[ do...while ](/fr/Learn/JavaScript/Building_blocks/Looping_code#while_and_do_..._while), ou une déclaration [if...else ](/fr/Learn/JavaScript/Building_blocks/conditionals#if_..._else_statements), vous utilisez une fonction. -<h2 id="Les_fonctions_intégrées_du_navigateur">Les fonctions intégrées du navigateur</h2> +## Les fonctions intégrées du navigateur -<p>Nous avons beaucoup utilisé les fonctions intégrées du navigateur dans ce cours. Comme par exemple à chaque fois que nous avons manipulé une chaîne de caractères :</p> +Nous avons beaucoup utilisé les fonctions intégrées du navigateur dans ce cours. Comme par exemple à chaque fois que nous avons manipulé une chaîne de caractères : -<pre class="brush: js">var myText = 'I am a string'; +```js +var myText = 'I am a string'; var newString = myText.replace('string', 'sausage'); console.log(newString); // La fonction replace () sélectionne une chaîne, // remplace une sous-chaîne par une autre, et renvoie -// la nouvelle chaîne avec les modifications effectuées.</pre> +// la nouvelle chaîne avec les modifications effectuées. +``` -<p>Ou à chaque fois que nous avons manipulé un tableau :</p> +Ou à chaque fois que nous avons manipulé un tableau : -<pre class="brush: js">var myArray = ['I', 'love', 'chocolate', 'frogs']; +```js +var myArray = ['I', 'love', 'chocolate', 'frogs']; var madeAString = myArray.join(' '); console.log(madeAString); // La fonction join() sélectionne un tableau, rassemble // tous les éléments du tableau dans une chaîne, -// et renvoie cette nouvelle chaîne.</pre> +// et renvoie cette nouvelle chaîne. +``` -<p>Ou à chaque fois que nous avons généré un nombre aléatoire :</p> +Ou à chaque fois que nous avons généré un nombre aléatoire : -<pre class="brush: js">var myNumber = Math.random(); +```js +var myNumber = Math.random(); // la fonction random() génère un nombre aléatoire // entre 0 et 1, et renvoie -// ce nombre</pre> +// ce nombre +``` -<p>... nous avons utilisé une fonction !</p> +... nous avons utilisé une fonction ! -<div class="note"> -<p><strong>Note :</strong> N'hésitez pas à copier ces lignes dans la console JavaScript de votre navigateur afin de vous familiariser à nouveau avec leur fonctionnalité si vous en ressentez le besoin.</p> -</div> +> **Note :** N'hésitez pas à copier ces lignes dans la console JavaScript de votre navigateur afin de vous familiariser à nouveau avec leur fonctionnalité si vous en ressentez le besoin. -<p>Le langage Javascript a de nombreuses fonctions intégrées pour vous permettre de faire des choses utiles sans devoir écrire tout le code vous-même. En fait, certains codes que vous appelez quand<strong> invoquez</strong> (un mot sophistiqué pour dire lancer ou exécuter) une fonction intégrée du navigateur ne pourraient pas être écrits en JavaScript — la plupart de ces fonctions appellent des parties de code interne du navigateur qui est très majoritairement écrit en langages de bas niveau comme le C++, et non pas en langage web comme JavaScript.</p> +Le langage Javascript a de nombreuses fonctions intégrées pour vous permettre de faire des choses utiles sans devoir écrire tout le code vous-même. En fait, certains codes que vous appelez quand **invoquez** (un mot sophistiqué pour dire lancer ou exécuter) une fonction intégrée du navigateur ne pourraient pas être écrits en JavaScript — la plupart de ces fonctions appellent des parties de code interne du navigateur qui est très majoritairement écrit en langages de bas niveau comme le C++, et non pas en langage web comme JavaScript. -<p>Gardez à l'esprit que certaines fonctions intégrées du navigateur ne font pas partie du noyau du langage JavaScript — certaines font partie des APIs du navigateur qui sont construites à partir du langage par défaut pour apporter encore plus de fonctionnalités ( consultez cette <a href="/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript">section antérieure de notre cours</a> pour une description plus détaillée ). Nous aborderons l'utilisation des APIs du navigateur plus en détail dans un module ultérieur.</p> +Gardez à l'esprit que certaines fonctions intégrées du navigateur ne font pas partie du noyau du langage JavaScript — certaines font partie des APIs du navigateur qui sont construites à partir du langage par défaut pour apporter encore plus de fonctionnalités ( consultez cette [section antérieure de notre cours](/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript) pour une description plus détaillée ). Nous aborderons l'utilisation des APIs du navigateur plus en détail dans un module ultérieur. -<h2 id="Fonctions_versus_méthodes">Fonctions versus méthodes</h2> +## Fonctions versus méthodes -<p>Une chose que nous devons éclaircir avant d'aller plus loin — d'un point de vue technique les fonctions intégrées du navigateur ne sont pas des fonctions mais des <strong>méthodes</strong>. Cela peut vous effrayer ou vous désorienter mais n'ayez crainte — les mots fonction et méthode sont largement interchangeables, du moins pour ce qui nous concerne, à ce niveau de votre apprentissage.</p> +Une chose que nous devons éclaircir avant d'aller plus loin — d'un point de vue technique les fonctions intégrées du navigateur ne sont pas des fonctions mais des **méthodes**. Cela peut vous effrayer ou vous désorienter mais n'ayez crainte — les mots fonction et méthode sont largement interchangeables, du moins pour ce qui nous concerne, à ce niveau de votre apprentissage. -<p>La distinction réside dans le fait que les méthodes sont des fonctions définies à l'intérieur d'objets. Les fonctions intégrées au navigateur (méthodes) et les variables (que l'on appelle <strong>propriétés</strong>) sont stockées dans des objets structurés, pour rendre le code plus efficace et facile à manier.</p> +La distinction réside dans le fait que les méthodes sont des fonctions définies à l'intérieur d'objets. Les fonctions intégrées au navigateur (méthodes) et les variables (que l'on appelle **propriétés**) sont stockées dans des objets structurés, pour rendre le code plus efficace et facile à manier. -<p>Vous n'aurez pas besoin d'apprendre les rouages des objets structurés du JavaScript pour le moment — vous pouvez attendre un module ultérieur qui vous en apprendra tous les rouages internes et comment les créer par vous même. Pour le moment, nous souhaitons simplement éviter toute confusion possible entre méthode et fonction — car vous êtes susceptibles de rencontrer les deux termes si vous en recherchez les ressources disponibles sur le Web. </p> +Vous n'aurez pas besoin d'apprendre les rouages des objets structurés du JavaScript pour le moment — vous pouvez attendre un module ultérieur qui vous en apprendra tous les rouages internes et comment les créer par vous même. Pour le moment, nous souhaitons simplement éviter toute confusion possible entre méthode et fonction — car vous êtes susceptibles de rencontrer les deux termes si vous en recherchez les ressources disponibles sur le Web. -<h2 id="Fonctions_personnalisées">Fonctions personnalisées</h2> +## Fonctions personnalisées -<p>Nous avons également rencontré beaucoup de fonctions personnalisées dans le cours jusqu'ici — fonctions définies dans votre code, et non pas dans le navigateur. À chaque fois que vous voyez un nom personnalisé suivi de parenthèses, vous utilisez une fonction personnalisée. Dans notre exemple <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/random-canvas-circles.html">random-canvas-circles.html </a>tiré de l'article <a href="/fr/Apprendre/JavaScript/Building_blocks/Looping_code">les boucles dans le code </a>(voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html">code source </a>complet), nous avons inclus une fonction personnalisée <code>draw()</code>qui ressemblait à ça :</p> +Nous avons également rencontré beaucoup de fonctions personnalisées dans le cours jusqu'ici — fonctions définies dans votre code, et non pas dans le navigateur. À chaque fois que vous voyez un nom personnalisé suivi de parenthèses, vous utilisez une fonction personnalisée. Dans notre exemple [random-canvas-circles.html ](http://mdn.github.io/learning-area/javascript/building-blocks/loops/random-canvas-circles.html)tiré de l'article [les boucles dans le code ](/fr/Apprendre/JavaScript/Building_blocks/Looping_code)(voir aussi le [code source ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html)complet), nous avons inclus une fonction personnalisée `draw()`qui ressemblait à ça : -<pre class="brush: js">function draw() { +```js +function draw() { ctx.clearRect(0,0,WIDTH,HEIGHT); - for (var i = 0; i < 100; i++) { + for (var i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = 'rgba(255,0,0,0.5)'; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); ctx.fill(); } -}</pre> +} +``` -<p>Cette fonction dessine 100 cercles aléatoires dans un élément {{htmlelement("canvas")}}. À chaque fois que nous voulons faire cela, il suffit d'invoquer la fonction comme suit :</p> +Cette fonction dessine 100 cercles aléatoires dans un élément {{htmlelement("canvas")}}. À chaque fois que nous voulons faire cela, il suffit d'invoquer la fonction comme suit : -<pre class="brush: js">draw();</pre> +```js +draw(); +``` -<p>au lieu de devoir ré-écrire tout le code à chaque fois que nous voulons la répéter. De plus, les fonctions peuvent contenir tous les codes qu'il vous plaira — vous pouvez même appeler d'autres fonctions à l'intérieur d'une fonction. Par exemple, la fonction ci-dessus appelle la fonction <code>random()</code> trois fois, comme définie par le code suivant :</p> +au lieu de devoir ré-écrire tout le code à chaque fois que nous voulons la répéter. De plus, les fonctions peuvent contenir tous les codes qu'il vous plaira — vous pouvez même appeler d'autres fonctions à l'intérieur d'une fonction. Par exemple, la fonction ci-dessus appelle la fonction `random()` trois fois, comme définie par le code suivant : -<pre class="brush: js">function random(number) { +```js +function random(number) { return Math.floor(Math.random()*number); -}</pre> +} +``` -<p>Nous avions besoin de cette fonction car la fonction intégrée du navigateur <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a> génère uniquement un nombre décimal aléatoire compris entre 0 et 1 alors que nous voulions un nombre entier compris entre 0 et un nombre défini.</p> +Nous avions besoin de cette fonction car la fonction intégrée du navigateur [Math.random()](/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/random) génère uniquement un nombre décimal aléatoire compris entre 0 et 1 alors que nous voulions un nombre entier compris entre 0 et un nombre défini. -<h2 id="Invoquer_des_fonctions">Invoquer des fonctions</h2> +## Invoquer des fonctions -<p>Vous êtes probablement au clair avec cela maintenant, mais juste au cas où... pour utiliser une fonction après qu'elle ait été définie, vous devez la lancer - ou l'invoquer. Pour ce faire, vous devez inclure le nom de la fonction quelque part dans le code suivi par des parenthèses.</p> +Vous êtes probablement au clair avec cela maintenant, mais juste au cas où... pour utiliser une fonction après qu'elle ait été définie, vous devez la lancer - ou l'invoquer. Pour ce faire, vous devez inclure le nom de la fonction quelque part dans le code suivi par des parenthèses. -<pre class="brush: js">function myFunction() { +```js +function myFunction() { alert('hello'); } myFunction() -// appelle la fonction une fois</pre> +// appelle la fonction une fois +``` -<h2 id="Fonctions_anonymes">Fonctions anonymes</h2> +## Fonctions anonymes -<p>Vous pouvez rencontrer des fonctions définies et invoquées de manière légèrement différentes. Nous venons juste de créer une fonction comme celle-ci :</p> +Vous pouvez rencontrer des fonctions définies et invoquées de manière légèrement différentes. Nous venons juste de créer une fonction comme celle-ci : -<pre class="brush: js">function myFunction() { +```js +function myFunction() { alert('hello'); -}</pre> +} +``` -<p>Mais vous pouvez également créer une fonction qui n'a pas de nom :</p> +Mais vous pouvez également créer une fonction qui n'a pas de nom : -<pre class="brush: js">function() { +```js +function() { alert('hello'); -}</pre> +} +``` -<p>Ceci est une <strong>fonction anonyme </strong>— elle n'a pas de nom ! De plus, elle ne produira pas d'effet par elle-même. Les fonctions anonymes sont généralement utilisées en association avec un gestionnaire d'évènement, comme dans l'exemple suivant qui lance le code inscrit dans la fonction lorsque le bouton associé est cliqué :</p> +Ceci est une **fonction anonyme** — elle n'a pas de nom ! De plus, elle ne produira pas d'effet par elle-même. Les fonctions anonymes sont généralement utilisées en association avec un gestionnaire d'évènement, comme dans l'exemple suivant qui lance le code inscrit dans la fonction lorsque le bouton associé est cliqué : -<pre class="brush: js">var myButton = document.querySelector('button'); +```js +var myButton = document.querySelector('button'); myButton.onclick = function() { alert('hello'); -}</pre> +} +``` -<p>Cet exemple ci-dessus nécessite qu'il y ait un élément HTML {{htmlelement("button")}} disponible sur la page afin qu'il puisse être cliqué. Vous avez déjà rencontré ce type de structure plusieurs fois dans ce cours et vous en apprendrez plus à son sujet lorsque vous en étudierez l'utilisation dans l'article suivant.</p> +Cet exemple ci-dessus nécessite qu'il y ait un élément HTML {{htmlelement("button")}} disponible sur la page afin qu'il puisse être cliqué. Vous avez déjà rencontré ce type de structure plusieurs fois dans ce cours et vous en apprendrez plus à son sujet lorsque vous en étudierez l'utilisation dans l'article suivant. -<p>Vous pouvez également assigner une fonction anonyme en tant que valeur d'une variable, comme par exemple :</p> +Vous pouvez également assigner une fonction anonyme en tant que valeur d'une variable, comme par exemple : -<pre class="brush: js">var myGreeting = function() { +```js +var myGreeting = function() { alert('hello'); -}</pre> +} +``` -<p>Cette fonction peut désormais être invoquée en utilisant :</p> +Cette fonction peut désormais être invoquée en utilisant : -<pre class="brush: js">myGreeting();</pre> +```js +myGreeting(); +``` -<p>Cela a pour effet d'attribuer un nom à la fonction ; vous pouvez également utiliser la fonction anonyme en tant que valeur de variables multiples, comme par exemple :</p> +Cela a pour effet d'attribuer un nom à la fonction ; vous pouvez également utiliser la fonction anonyme en tant que valeur de variables multiples, comme par exemple : -<pre class="brush: js">var anotherGreeting = function() { +```js +var anotherGreeting = function() { alert('hello'); -}</pre> +} +``` -<p>Cette fonction peut désormais être invoquée en utilisant au choix :</p> +Cette fonction peut désormais être invoquée en utilisant au choix : -<pre class="brush: js">myGreeting(); -anotherGreeting();</pre> +```js +myGreeting(); +anotherGreeting(); +``` -<p>Cela peut toutefois générer de la confusion, donc ne le faites pas ! Lorsque l'on crée des fonctions, il vaut mieux se contenter de cette forme :</p> +Cela peut toutefois générer de la confusion, donc ne le faites pas ! Lorsque l'on crée des fonctions, il vaut mieux se contenter de cette forme : -<pre class="brush: js">function myGreeting() { +```js +function myGreeting() { alert('hello'); -}</pre> +} +``` -<p>Vous utiliserez principalement des fonctions anonymes simplement pour lancer une partie de code en réponse à un évènement — comme lorsqu'un bouton est cliqué — en utilisant un gestionnaire d'évènement. Cela devrait ressembler à ça :</p> +Vous utiliserez principalement des fonctions anonymes simplement pour lancer une partie de code en réponse à un évènement — comme lorsqu'un bouton est cliqué — en utilisant un gestionnaire d'évènement. Cela devrait ressembler à ça : -<pre class="brush: js">myButton.onclick = function() { +```js +myButton.onclick = function() { alert('hello'); // Je peux mettre ici autant // de code que je le souhaite -}</pre> +} +``` -<h2 id="Paramètres_des_fonctions">Paramètres des fonctions</h2> +## Paramètres des fonctions -<p>Certaines fonctions nécessitent que l'on définisse des <strong>paramètres</strong> lorsqu'on les appelle — ce sont des valeurs qui doivent êtres inclues dans les parenthèses de la fonction pour que celle-ci fonctionne correctement.</p> +Certaines fonctions nécessitent que l'on définisse des **paramètres** lorsqu'on les appelle — ce sont des valeurs qui doivent êtres inclues dans les parenthèses de la fonction pour que celle-ci fonctionne correctement. -<div class="note"> -<p><strong>Note :</strong> Les paramètres sont parfois appelés arguments, propriétés ou encore attributs.</p> -</div> +> **Note :** Les paramètres sont parfois appelés arguments, propriétés ou encore attributs. -<p>Par exemple, la fonction intégrée du navigateur <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a> ne nécessite pas de paramètres. lorsqu'elle est appelée, elle renvoie toujours un nombre aléatoire compris entre 0 et 1 : </p> +Par exemple, la fonction intégrée du navigateur [Math.random()](/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/random) ne nécessite pas de paramètres. lorsqu'elle est appelée, elle renvoie toujours un nombre aléatoire compris entre 0 et 1 : -<pre class="brush: js">var myNumber = Math.random();</pre> +```js +var myNumber = Math.random(); +``` -<p>La fonction de chaîne intégrée du navigateur <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a> nécessite toutefois deux paramètres — la sous-chaîne qu'elle doit remplacer à l'intérieur de la chaîne, et la sous-chaîne par laquelle elle doit la remplacer :</p> +La fonction de chaîne intégrée du navigateur [replace()](/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace) nécessite toutefois deux paramètres — la sous-chaîne qu'elle doit remplacer à l'intérieur de la chaîne, et la sous-chaîne par laquelle elle doit la remplacer : -<pre class="brush: js">var myText = 'I am a string'; -var newString = myText.replace('string', 'sausage');</pre> +```js +var myText = 'I am a string'; +var newString = myText.replace('string', 'sausage'); +``` -<div class="note"> -<p><strong>Note :</strong> Quand vous devez définir plusieurs paramètres, ils doivent être séparés par des virgules.</p> -</div> +> **Note :** Quand vous devez définir plusieurs paramètres, ils doivent être séparés par des virgules. -<p>Il est également à noter que parfois les paramètres sont optionnels — vous n'avez pas à les spécifier. Si vous ne le faites pas, la fonction va généralement adopter un comportement par défaut. Par exemple, la fonction de tableau <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/join">join()</a> a des paramètres optionnels :</p> +Il est également à noter que parfois les paramètres sont optionnels — vous n'avez pas à les spécifier. Si vous ne le faites pas, la fonction va généralement adopter un comportement par défaut. Par exemple, la fonction de tableau [join()](/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/join) a des paramètres optionnels : -<pre class="brush: js">var myArray = ['I', 'love', 'chocolate', 'frogs']; +```js +var myArray = ['I', 'love', 'chocolate', 'frogs']; var madeAString = myArray.join(' '); // renvoie 'I love chocolate frogs' var madeAString = myArray.join(); -// renvoie 'I,love,chocolate,frogs'</pre> +// renvoie 'I,love,chocolate,frogs' +``` -<p>Si aucun paramètre n'est inclus pour spécifier un caractère de jointure / délimitation, une virgule est utilisée par défaut.</p> +Si aucun paramètre n'est inclus pour spécifier un caractère de jointure / délimitation, une virgule est utilisée par défaut. -<h2 id="La_portée_des_fonctions_et_les_conflits.">La portée des fonctions et les conflits.</h2> +## La portée des fonctions et les conflits. -<p>Parlons un peu de la {{glossary("portée")}} — un concept très important lorsque l'on a affaire à des fonctions. Lorsque vous créez une fonction, les variables et les autres choses qui sont définies à l'intérieur de la fonction ont leur propre <strong>portée</strong>, ce qui signifie qu'elles sont enfermées dans leur propre compartiment séparé et qu'elles ne peuvent pas être affectées par d'autres fonctions ou par le code en dehors de la fonction.</p> +Parlons un peu de la {{glossary("portée")}} — un concept très important lorsque l'on a affaire à des fonctions. Lorsque vous créez une fonction, les variables et les autres choses qui sont définies à l'intérieur de la fonction ont leur propre **portée**, ce qui signifie qu'elles sont enfermées dans leur propre compartiment séparé et qu'elles ne peuvent pas être affectées par d'autres fonctions ou par le code en dehors de la fonction. -<p>Le plus haut niveau en dehors de toutes vos fonctions est appelé la <strong>portée globale</strong>. Les valeurs définies dans la portée globale sont accessibles à partir de n'importe qu'elle partie du code.</p> +Le plus haut niveau en dehors de toutes vos fonctions est appelé la **portée globale**. Les valeurs définies dans la portée globale sont accessibles à partir de n'importe qu'elle partie du code. -<p>Le JavaScript est construit de cette façon pour plusieurs raisons — mais principalement à cause de la sécurité et de l'organisation. Parfois, vous ne voulez pas que vos variables soient accessibles depuis toutes les autres parties du code — des script externes appelés depuis l'extérieur de la fonction pourraient interférer avec votre code et causer des problèmes parce qu'ils utilisent les mêmes noms de variables que d'autres parties du code, provoquant des conflits. Cela peut être fait de manière malveillante ou simplement par accident.</p> +Le JavaScript est construit de cette façon pour plusieurs raisons — mais principalement à cause de la sécurité et de l'organisation. Parfois, vous ne voulez pas que vos variables soient accessibles depuis toutes les autres parties du code — des script externes appelés depuis l'extérieur de la fonction pourraient interférer avec votre code et causer des problèmes parce qu'ils utilisent les mêmes noms de variables que d'autres parties du code, provoquant des conflits. Cela peut être fait de manière malveillante ou simplement par accident. -<p>Par exemple, disons que vous avez un fichier HTML qui appelle deux fichiers JavaScript externes, et que les deux ont une variable et une fonction définie qui utilisent le même nom :</p> +Par exemple, disons que vous avez un fichier HTML qui appelle deux fichiers JavaScript externes, et que les deux ont une variable et une fonction définie qui utilisent le même nom : -<pre class="brush: html"><!-- Excerpt from my HTML --> -<script src="first.js"></script> -<script src="second.js"></script> -<script> +```html +<!-- Excerpt from my HTML --> +<script src="first.js"></script> +<script src="second.js"></script> +<script> greeting(); -</script></pre> +</script> +``` -<pre class="brush: js">// first.js +```js +// first.js var name = 'Chris'; function greeting() { alert('Hello ' + name + ': welcome to our company.'); -}</pre> +} +``` -<pre class="brush: js">// second.js +```js +// second.js var name = 'Zaptec'; function greeting() { alert('Our company is called ' + name + '.'); -}</pre> +} +``` -<p>Les deux fonctions que vous voulez appeler s'appellent <code>greeting()</code>, mais vous ne pouvez accéder qu'à la fonction <code>greeting()</code> du second fichier <code>second.js</code> — car celui-ci est appliqué au code HTML plus tard dans le code source, de sorte que sa variable et sa fonction écrasent celles du premier fichier <code>first.js</code>.</p> +Les deux fonctions que vous voulez appeler s'appellent `greeting()`, mais vous ne pouvez accéder qu'à la fonction `greeting()` du second fichier `second.js` — car celui-ci est appliqué au code HTML plus tard dans le code source, de sorte que sa variable et sa fonction écrasent celles du premier fichier `first.js`. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez voir cet exemple <a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/conflict.html">s'exécuter sur GitHub</a> (voir aussi le <a href="https://github.com/mdn/learning-area/tree/master/javascript/building-blocks/functions">code source</a>).</p> -</div> +> **Note :** Vous pouvez voir cet exemple [s'exécuter sur GitHub](http://mdn.github.io/learning-area/javascript/building-blocks/functions/conflict.html) (voir aussi le [code source](https://github.com/mdn/learning-area/tree/master/javascript/building-blocks/functions)). -<p>En conservant des parties de votre code enfermées dans des fonctions, vous évitez de tels problèmes. Cette procédure est considérée comme une bonne pratique.</p> +En conservant des parties de votre code enfermées dans des fonctions, vous évitez de tels problèmes. Cette procédure est considérée comme une bonne pratique. -<p>C'est un peu comme au zoo. Les lions, zèbres, tigres et pingouins sont enfermés dans leurs propres enclos, et n'ont accès qu'aux éléments se trouvant à l'intérieur de leur enclos — de la même manière que la portée des fonctions. S'il leur était possible de pénétrer dans les autres enclos, des problèmes se produiraient. Au mieux, des animaux différents seraient dans l'inconfort au sein d'un habitat étranger — un lion ou un tigre se sentirait très mal dans l'environnement humide et glacé des pingouins. Au pire, les lions et les tigres pourraient essayer de manger les pingouins !</p> +C'est un peu comme au zoo. Les lions, zèbres, tigres et pingouins sont enfermés dans leurs propres enclos, et n'ont accès qu'aux éléments se trouvant à l'intérieur de leur enclos — de la même manière que la portée des fonctions. S'il leur était possible de pénétrer dans les autres enclos, des problèmes se produiraient. Au mieux, des animaux différents seraient dans l'inconfort au sein d'un habitat étranger — un lion ou un tigre se sentirait très mal dans l'environnement humide et glacé des pingouins. Au pire, les lions et les tigres pourraient essayer de manger les pingouins ! -<p><img alt="" src="MDN-mozilla-zoo.png"></p> + -<p>Le gardien du zoo est comme la portée globale — il ou elle a les clefs pour accéder à chaque enclos, pour l'approvisionner en nourriture, soigner les animaux malades, ...etc.</p> +Le gardien du zoo est comme la portée globale — il ou elle a les clefs pour accéder à chaque enclos, pour l'approvisionner en nourriture, soigner les animaux malades, ...etc. -<h3 id="Apprentissage_actif_Jouer_avec_la_portée">Apprentissage actif : Jouer avec la portée</h3> +### Apprentissage actif : Jouer avec la portée -<p>Jetons un coup d'oeil à un exemple réel pour démontrer les effets de la portée.</p> +Jetons un coup d'oeil à un exemple réel pour démontrer les effets de la portée. -<ol> - <li>Tout d'abord, faisons un copie locale de notre exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-scope.html">function-scope.html</a>. Celui-ci contient deux fonctions appelées <code>a()</code> et <code>b()</code>, et trois variables — <code>x</code>, <code>y</code>, and <code>z</code> — deux d'entre elles sont définies à l'intérieur de la fonction, et l'autre dans la portée globale. Il contient également une troisième fonction appelée <code>output()</code>, qui prend un seul paramètre et le renvoie dans un paragraphe de la page.</li> - <li>Ouvrez l'exemple ci-dessus dans un navigateur et dans un éditeur de texte.</li> - <li>Ouvrez la console JavaScript dans les outils de développement de votre navigateur et entrez la commande suivante : - <pre class="brush: js">output(x);</pre> - Vous devriez voir la valeur de la variable <code>x</code> renvoyée à l'écran.</li> - <li>Maintenant essayez d'entrer les commandes suivantes : - <pre class="brush: js">output(y); -output(z);</pre> +1. Tout d'abord, faisons un copie locale de notre exemple [function-scope.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-scope.html). Celui-ci contient deux fonctions appelées `a()` et `b()`, et trois variables — `x`, `y`, and `z` — deux d'entre elles sont définies à l'intérieur de la fonction, et l'autre dans la portée globale. Il contient également une troisième fonction appelée `output()`, qui prend un seul paramètre et le renvoie dans un paragraphe de la page. +2. Ouvrez l'exemple ci-dessus dans un navigateur et dans un éditeur de texte. +3. Ouvrez la console JavaScript dans les outils de développement de votre navigateur et entrez la commande suivante : - <p>Toutes les deux devraient vous renvoyer un message d'erreur du type : "<a href="/fr/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: y is not defined</a>". Pourquoi ? À cause de la portée de la fonction — <code>y</code> and <code>z</code> sont enfermées dans les fonctions <code>a()</code> et <code>b()</code>, donc <code>output()</code> ne peut pas les atteindre lorsqu'elles sont appelées depuis la portée globale.</p> - </li> - <li> - <p>Néanmoins, que se passe-t-il losqu'elles sont appelées de l'intérieur d'une autre fonction ? Essayer d'éditer <code>a()</code> et <code>b()</code> pour qu'elles aient la forme suivante :</p> + ```js + output(x); + ``` - <pre class="brush: js">function a() { - var y = 2; - output(y); -} + Vous devriez voir la valeur de la variable `x` renvoyée à l'écran. -function b() { - var z = 3; - output(z); -}</pre> - Sauvegardez le code et rechargez-le dans votre navigateur, puis essayez d'appeler les fonctions <code>a()</code> et <code>b()</code> depuis la console JavaScript : - - <pre class="brush: js">a(); -b();</pre> - Vous devriez voir les valeurs <code>y</code> and <code>z</code> renvoyées sur la page. Cela fonctionne très bien car la fonction <code>output()</code> est applée à l'intérieur des autres fonctions — dans la portée dans laquelle les variables qu'elle renvoie sont définies. La fonction <code>output()</code> est elle-même disponible n'importe où dans le code, car elle est définie dans la portée globale.</li> - <li>Maintenant essayer de mettre à jour le code comme ceci : - <pre class="brush: js">function a() { - var y = 2; - output(x); -} +4. Maintenant essayez d'entrer les commandes suivantes : -function b() { - var z = 3; - output(x); -}</pre> - Sauvegardez et rechargez à nouveau dans la console JavaScript :</li> - <li> - <pre class="brush: js">a(); -b();</pre> - Les deux fonctions <code>a()</code> et <code>b()</code> appelées devraient renvoyer la valeur x — 1. Cela fonctionne très bien car même si la fonction <code>output()</code> n'est pas dans la même portée que celle dans laquelle <code>x</code> est définie, <code>x</code> est une variable globale et donc elle est disponible dans n'importe quelle partie du code.</li> - <li>Pour finir, essayez de mettre à jour le code comme ceci : - <pre class="brush: js">function a() { - var y = 2; - output(z); -} + ```js + output(y); + output(z); + ``` + + Toutes les deux devraient vous renvoyer un message d'erreur du type : "[ReferenceError: y is not defined](/fr/docs/Web/JavaScript/Reference/Errors/Not_defined)". Pourquoi ? À cause de la portée de la fonction — `y` and `z` sont enfermées dans les fonctions `a()` et `b()`, donc `output()` ne peut pas les atteindre lorsqu'elles sont appelées depuis la portée globale. -function b() { - var z = 3; - output(y); -}</pre> - </li> - <li>Sauvegardez et rechargez à nouveau dans la console JavaScript : - <pre class="brush: js">a(); -b();</pre> - Cette fois l'appel de <code>a()</code> et <code>b()</code> renverra l'erreur "<a href="/fr/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: z is not defined</a>" — parce que l'appel de la fonction <code>output()</code> et des variables qu'elle essaie d'afficher ne sont pas définis dans les mêmes portées — les variables sont en effet invisibles pour cet appel de fonction.</li> -</ol> +5. Néanmoins, que se passe-t-il losqu'elles sont appelées de l'intérieur d'une autre fonction ? Essayer d'éditer `a()` et `b()` pour qu'elles aient la forme suivante : -<div class="note"> -<p><strong>Note :</strong> Ces règles de portée ne s'appliquent pas aux boucles (ex. <code>for() { ... }</code>) ni aux instructions conditionnelles (ex. <code>if() { ... }</code>) — elles semblent très similaires, mais ce n'est pas la même chose ! Prenez garde de ne pas les confondre.</p> -</div> + ```js + function a() { + var y = 2; + output(y); + } -<div class="note"> -<p><strong>Note :</strong> Le message d'erreur <a href="/fr/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: "x" is not defined</a> est l'un des plus courant que vous pourrez rencontrer. S'il s'affiche et que vous êtes sûr d'avoir défini la variable en question, vérifiez quelle est sa portée.</p> -</div> + function b() { + var z = 3; + output(z); + } + ``` -<h3 id="Des_fonctions_à_lintérieur_de_fonctions">Des fonctions à l'intérieur de fonctions</h3> + Sauvegardez le code et rechargez-le dans votre navigateur, puis essayez d'appeler les fonctions `a()` et `b()` depuis la console JavaScript : -<p>Gardez à l'esprit que vous pouvez appeler une fonction de n'importe où, même à l'intérieur d'une autre fonction. Ceci est souvent utilisé comme un moyen de garder le code bien organisé — si vous avez une grande fonction complexe, elle est plus facile à comprendre si vous la divisez en plusieurs sous-fonctions :</p> + ```js + a(); + b(); + ``` -<pre class="brush: js">function myBigFunction() { + Vous devriez voir les valeurs `y` and `z` renvoyées sur la page. Cela fonctionne très bien car la fonction `output()` est applée à l'intérieur des autres fonctions — dans la portée dans laquelle les variables qu'elle renvoie sont définies. La fonction `output()` est elle-même disponible n'importe où dans le code, car elle est définie dans la portée globale. + +6. Maintenant essayer de mettre à jour le code comme ceci : + + ```js + function a() { + var y = 2; + output(x); + } + + function b() { + var z = 3; + output(x); + } + ``` + + Sauvegardez et rechargez à nouveau dans la console JavaScript : + +7. ```js + a(); + b(); + ``` + + Les deux fonctions `a()` et `b()` appelées devraient renvoyer la valeur x — 1. Cela fonctionne très bien car même si la fonction `output()` n'est pas dans la même portée que celle dans laquelle `x` est définie, `x` est une variable globale et donc elle est disponible dans n'importe quelle partie du code. + +8. Pour finir, essayez de mettre à jour le code comme ceci : + + ```js + function a() { + var y = 2; + output(z); + } + + function b() { + var z = 3; + output(y); + } + ``` + +9. Sauvegardez et rechargez à nouveau dans la console JavaScript : + + ```js + a(); + b(); + ``` + + Cette fois l'appel de `a()` et `b()` renverra l'erreur "[ReferenceError: z is not defined](/fr/docs/Web/JavaScript/Reference/Errors/Not_defined)" — parce que l'appel de la fonction `output()` et des variables qu'elle essaie d'afficher ne sont pas définis dans les mêmes portées — les variables sont en effet invisibles pour cet appel de fonction. + +> **Note :** Ces règles de portée ne s'appliquent pas aux boucles (ex. `for() { ... }`) ni aux instructions conditionnelles (ex. `if() { ... }`) — elles semblent très similaires, mais ce n'est pas la même chose ! Prenez garde de ne pas les confondre. + +> **Note :** Le message d'erreur [ReferenceError: "x" is not defined](/fr/docs/Web/JavaScript/Reference/Errors/Not_defined) est l'un des plus courant que vous pourrez rencontrer. S'il s'affiche et que vous êtes sûr d'avoir défini la variable en question, vérifiez quelle est sa portée. + +### Des fonctions à l'intérieur de fonctions + +Gardez à l'esprit que vous pouvez appeler une fonction de n'importe où, même à l'intérieur d'une autre fonction. Ceci est souvent utilisé comme un moyen de garder le code bien organisé — si vous avez une grande fonction complexe, elle est plus facile à comprendre si vous la divisez en plusieurs sous-fonctions : + +```js +function myBigFunction() { var myValue; subFunction1(); @@ -340,11 +403,12 @@ function subFunction2() { function subFunction3() { console.log(myValue); } -</pre> +``` -<p>Assurez-vous simplement que les valeurs utilisées dans la fonction ont une portée correcte. L'exemple ci-dessus entraînerait une erreur <code>ReferenceError: myValue is not defined</code>, car bien que la valeur <code>myValue</code> est définie dans la même portée que les appels de fonction, elle n'est pas définie dans les définitions de fonctions - le code réel qui est exécuté lorsque les fonctions sont appelées. Pour que cela fonctionne, vous devez passer la valeur dans la fonction en tant que paramètre, comme ceci :</p> +Assurez-vous simplement que les valeurs utilisées dans la fonction ont une portée correcte. L'exemple ci-dessus entraînerait une erreur `ReferenceError: myValue is not defined`, car bien que la valeur `myValue` est définie dans la même portée que les appels de fonction, elle n'est pas définie dans les définitions de fonctions - le code réel qui est exécuté lorsque les fonctions sont appelées. Pour que cela fonctionne, vous devez passer la valeur dans la fonction en tant que paramètre, comme ceci : -<pre class="brush: js">function myBigFunction() { +```js +function myBigFunction() { var myValue = 1; subFunction1(myValue); @@ -362,32 +426,28 @@ function subFunction2(value) { function subFunction3(value) { console.log(value); -}</pre> +} +``` -<h2 id="Conclusion">Conclusion</h2> +## Conclusion -<p>Cet article a exploré les concepts fondamentaux inhérents aux fonctions, ouvrant la voie au suivant dans lequel nous passerons à la pratique et vous guiderons à travers les étapes pour construire votre propre fonction personnalisée.</p> +Cet article a exploré les concepts fondamentaux inhérents aux fonctions, ouvrant la voie au suivant dans lequel nous passerons à la pratique et vous guiderons à travers les étapes pour construire votre propre fonction personnalisée. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/JavaScript/Guide/Fonctions">Fonctions</a> — aborde certaines fonctionnalités avancées non incluses ici.</li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Fonctions/Valeurs_par_d%C3%A9faut_des_arguments">Valeur par défaut des arguments</a>, <a href="/fr/docs/Web/JavaScript/Reference/Fonctions/Fonctions_fl%C3%A9ch%C3%A9es">Fonctions fléchées</a> — références avancées</li> -</ul> +- [Fonctions](/fr/docs/Web/JavaScript/Guide/Fonctions) — aborde certaines fonctionnalités avancées non incluses ici. +- [Valeur par défaut des arguments](/fr/docs/Web/JavaScript/Reference/Fonctions/Valeurs_par_d%C3%A9faut_des_arguments), [Fonctions fléchées](/fr/docs/Web/JavaScript/Reference/Fonctions/Fonctions_fl%C3%A9ch%C3%A9es) — références avancées -<ul> -</ul> +<!----> -<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}} -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/conditionals">Prendre des décisions dans le code — conditions</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Looping_code">Les boucles dans le code</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Fonctions">Fonctions — des blocs de code réutilisables</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Construire votre propre fonction</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Return_values">Valeurs de retour des fonctions</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">Introduction aux évènements</a></li> - <li><a href="/fr/Apprendre/JavaScript/Building_blocks/Image_gallery">Galerie d'images</a></li> -</ul> +- [Prendre des décisions dans le code — conditions](/fr/Apprendre/JavaScript/Building_blocks/conditionals) +- [Les boucles dans le code](/fr/Apprendre/JavaScript/Building_blocks/Looping_code) +- [Fonctions — des blocs de code réutilisables](/fr/Apprendre/JavaScript/Building_blocks/Fonctions) +- [Construire votre propre fonction](/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function) +- [Valeurs de retour des fonctions](/fr/Apprendre/JavaScript/Building_blocks/Return_values) +- [Introduction aux évènements](/fr/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements) +- [Galerie d'images](/fr/Apprendre/JavaScript/Building_blocks/Image_gallery) diff --git a/files/fr/learn/javascript/building_blocks/image_gallery/index.md b/files/fr/learn/javascript/building_blocks/image_gallery/index.md index bc09ea1194..78d6530000 100644 --- a/files/fr/learn/javascript/building_blocks/image_gallery/index.md +++ b/files/fr/learn/javascript/building_blocks/image_gallery/index.md @@ -15,148 +15,135 @@ tags: translation_of: Learn/JavaScript/Building_blocks/Image_gallery original_slug: Apprendre/JavaScript/Building_blocks/Image_gallery --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}} -<div>{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</div> - -<p>Maintenant que nous avons examiné les blocs fondamentaux de construction de JavaScript, nous allons tester vos connaissances sur les boucles, les fonctions, les conditions et les événements en vous aidant à créer un élément assez commun que vous verrez sur de nombreux sites web. Une galerie JavaScript animée.</p> +Maintenant que nous avons examiné les blocs fondamentaux de construction de JavaScript, nous allons tester vos connaissances sur les boucles, les fonctions, les conditions et les événements en vous aidant à créer un élément assez commun que vous verrez sur de nombreux sites web. Une galerie JavaScript animée. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Conditions préalables:</th> - <td>Avant de tenter cette évaluation, vous devriez avoir parcouru tous les articles de ce module. </td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Tester la compréhension des boucles, des fonctions, des conditions et des événements JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Conditions préalables:</th> + <td> + Avant de tenter cette évaluation, vous devriez avoir parcouru tous les + articles de ce module. + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td> + Tester la compréhension des boucles, des fonctions, des conditions et + des événements JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Point_de_départ">Point de départ</h2> - -<p>Pour réaliser cette évaluation, vous devez récupérer le fichier<a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/gallery/gallery-start.zip?raw=true"> ZIP</a> et le décompresser quelque par sur votre ordinateur.</p> +## Point de départ -<p>Vous pouvez également utiliser un site comme <a class="external external-icon" href="http://jsbin.com/">JSBin</a> ou <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> pour effectuer votre évalution. Vous pouvez copier le code HTML,CSS et JavaScript dans l'un de ces éditeurs en ligne. Si l'éditeur en ligne que vous utilisez ne dispose pas de panneaux JavaScript/CSS séparés, n'hésitez pas à utiliser les éléments <code><script></code>/<code><style></code> dans la page HTML.</p> +Pour réaliser cette évaluation, vous devez récupérer le fichier[ ZIP](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/gallery/gallery-start.zip?raw=true) et le décompresser quelque par sur votre ordinateur. -<div class="note"> -<p><strong>Note :</strong> Si vous êtes bloqué, demandez-nous de l'aide — voir la section {{anch("Évaluation ou aide supplémentaire")}} au bas de cette page.</p> -</div> +Vous pouvez également utiliser un site comme [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/) pour effectuer votre évalution. Vous pouvez copier le code HTML,CSS et JavaScript dans l'un de ces éditeurs en ligne. Si l'éditeur en ligne que vous utilisez ne dispose pas de panneaux JavaScript/CSS séparés, n'hésitez pas à utiliser les éléments `<script>`/`<style>` dans la page HTML. -<h2 id="Résumé_du_projet">Résumé du projet</h2> +> **Note :** Si vous êtes bloqué, demandez-nous de l'aide — voir la section {{anch("Évaluation ou aide supplémentaire")}} au bas de cette page. -<p>Vous avez reçu des fichiers HTML, CSS, des images et quelques lignes de code JavaScript; vous devez écrire le code JavaScript nécessaire pour en faire un programme fonctionnel. Le corps HTML ressemble à ceci:</p> +## Résumé du projet -<pre class="brush: html"><h1>Image gallery example</h1> +Vous avez reçu des fichiers HTML, CSS, des images et quelques lignes de code JavaScript; vous devez écrire le code JavaScript nécessaire pour en faire un programme fonctionnel. Le corps HTML ressemble à ceci: -<div class="full-img"> - <img class="displayed-img" src="images/pic1.jpg"> - <div class="overlay"></div> - <button class="dark">Darken</button> -</div> +```html +<h1>Image gallery example</h1> -<div class="thumb-bar"> +<div class="full-img"> + <img class="displayed-img" src="images/pic1.jpg"> + <div class="overlay"></div> + <button class="dark">Darken</button> +</div> -</div></pre> +<div class="thumb-bar"> -<p>L'exemple ressemble à ceci:</p> +</div> +``` -<p><img alt="" src="gallery.png"></p> +L'exemple ressemble à ceci: + -<p>Les parties les plus intéressantes du fichier CSS de l'exemple:</p> +Les parties les plus intéressantes du fichier CSS de l'exemple: -<ul> - <li>Positionnez les trois éléments en absolu à l’intérieur du <code>full-img <div></code>: le <code><img></code> dans lequel l’image est affichée grandeur nature, un <code><div></code> vide dimensionné à la même taille que le <code><img></code> et placé juste au-dessus (ceci est utilisé pour appliquer un effet assombrissant à l'image via une couleur d'arrière-plan semi-transparente), et un bouton <code><button></code>qui est utilisé pour contrôler l'effet d'assombrissement.</li> - <li>Réglez la largeur des images à l'intérieur de <code>thumb-bar <div></code>(appelées images miniatures) à 20% et faites un float à gauche pour qu'elles soient côte-à-côte sur une ligne.</li> -</ul> +- Positionnez les trois éléments en absolu à l’intérieur du `full-img <div>`: le `<img>` dans lequel l’image est affichée grandeur nature, un `<div>` vide dimensionné à la même taille que le `<img>` et placé juste au-dessus (ceci est utilisé pour appliquer un effet assombrissant à l'image via une couleur d'arrière-plan semi-transparente), et un bouton `<button>`qui est utilisé pour contrôler l'effet d'assombrissement. +- Réglez la largeur des images à l'intérieur de `thumb-bar <div>`(appelées images miniatures) à 20% et faites un float à gauche pour qu'elles soient côte-à-côte sur une ligne. -<p>Votre JavaScript doit:</p> +Votre JavaScript doit: -<ul> - <li>Itérer toutes les images dans une boucle, et pour chacune d'elle, insérer un élément <code><img></code> à l'intérieur de <code>thumb-bar <div></code> qui va incorporer cette image dans la page.</li> - <li>Associer un gestionnaire d'événement <code>onclick</code> à chaque <code><img></code> à l'intérieur de <code>thumb-bar <div></code> pour que, lorsqu'elles sont cliquées, l'image correspondante soit affichée dans l'élément <code>displayed-img <img></code>.</li> - <li>Associer un gestionnaire d'événement <code>onclick</code> au <code><button></code> pour que, lorsqu'il est cliqué, un effet assombrissant soit appliqué à l'image grandeur nature. Losrqu'il est cliqué à nouveau, l'effet doit disparaitre.</li> -</ul> +- Itérer toutes les images dans une boucle, et pour chacune d'elle, insérer un élément `<img>` à l'intérieur de `thumb-bar <div>` qui va incorporer cette image dans la page. +- Associer un gestionnaire d'événement `onclick` à chaque `<img>` à l'intérieur de `thumb-bar <div>` pour que, lorsqu'elles sont cliquées, l'image correspondante soit affichée dans l'élément `displayed-img <img>`. +- Associer un gestionnaire d'événement `onclick` au `<button>` pour que, lorsqu'il est cliqué, un effet assombrissant soit appliqué à l'image grandeur nature. Losrqu'il est cliqué à nouveau, l'effet doit disparaitre. -<p>Pour vous donner une idée, regardez l'<a href="http://mdn.github.io/learning-area/javascript/building-blocks/gallery/">exemple</a> (Ne regardez pas le code source!).</p> +Pour vous donner une idée, regardez l'[exemple](http://mdn.github.io/learning-area/javascript/building-blocks/gallery/) (Ne regardez pas le code source!). -<h2 id="Les_différentes_étapes">Les différentes étapes</h2> +## Les différentes étapes -<p>Les sections suivantes décrivent ce que vous avez à faire.</p> +Les sections suivantes décrivent ce que vous avez à faire. -<h3 id="Itération_sur_les_images">Itération sur les images</h3> +### Itération sur les images -<p>Nous vous avons fourni des lignes qui storent une référence à <code>thumb-bar <div></code> dans une variable nommée <code>thumbBar</code>, créent un nouvel élément <code><img></code>, définissent son attribut <code>src</code> à un emplacement de valueur <code>xxx</code>, et ajoutent ce nouvel élément <code><img></code> dans <code>thumbBar</code>.</p> +Nous vous avons fourni des lignes qui storent une référence à `thumb-bar <div>` dans une variable nommée `thumbBar`, créent un nouvel élément `<img>`, définissent son attribut `src` à un emplacement de valueur `xxx`, et ajoutent ce nouvel élément `<img>` dans `thumbBar`. -<p>Vous avez besoin de:</p> +Vous avez besoin de: -<ol> - <li>Ajouter votre code en-dessous du commentaire <em>Looping through images</em> à l'intérieur d'une boucle qui itère sur les 5 images — vous n'avez besoin que de 5 itérations, chacune représentant une image.</li> - <li>Remplacez, pour chaque itération, la valeur <code>xxx</code> de l'emplacement par une chaîne de caractères qui correspond au chemin de l'image considérée. Il faut définir la valeur de l'attribut <code>src</code> dans chaque cas. Gardez à l'esprit que, à chaque fois, l'image est dans le répertoire des images et que son nom est <code>pic1.jpg</code>, <code>pic2.jpg</code>, etc.</li> -</ol> +1. Ajouter votre code en-dessous du commentaire _Looping through images_ à l'intérieur d'une boucle qui itère sur les 5 images — vous n'avez besoin que de 5 itérations, chacune représentant une image. +2. Remplacez, pour chaque itération, la valeur `xxx` de l'emplacement par une chaîne de caractères qui correspond au chemin de l'image considérée. Il faut définir la valeur de l'attribut `src` dans chaque cas. Gardez à l'esprit que, à chaque fois, l'image est dans le répertoire des images et que son nom est `pic1.jpg`, `pic2.jpg`, etc. -<h3 id="Ajout_dun_gestionnaire_onclick_à_chaque_miniature">Ajout d'un gestionnaire onclick à chaque miniature</h3> +### Ajout d'un gestionnaire onclick à chaque miniature -<p>À chaque itération, vous devez ajouter un gestionnaire <code>onclick</code> au <code>newImage</code> courant. Il doit:</p> +À chaque itération, vous devez ajouter un gestionnaire `onclick` au `newImage` courant. Il doit: -<ol> - <li>Trouver la valeur de l'attribut <code>src</code> de l'image courante. Cela peut être fait avec la fonction <code><a href="/fr/docs/Web/API/Element/getAttribute">getAttribute()</a></code> sur <code><img></code>, en lui passant le paramètre <code>"src"</code> à chaque fois. Mais comment avoir l'image? Utiliser <code>newImage</code> ne marche pas du fait que la boucle est finie avant que le gestionnaire d'événement ne soit appelé; de cette manière, la valeur de <code>src</code> sera toujours celle du dernier <code><img></code>. Pour résoudre cela, gardez à l'esprit que, pour chaque gestionnaire d'événement, c'est <code><img></code> qui en est la cible. Pourquoi ne pas récupérer l'information de l'objet événement?</li> - <li>Exécuter une fonction, en lui passant en paramètre la fameuse valeur de <code>src</code>. Vous pouvez nommer la fonction à votre guise.</li> - <li>Cette fonction du gestionnaire d'événement doit définir la valeur de l'attribut <code>src</code> de <code>displayed-img <img></code> à la valeur du <code>src</code> passé en paramètre. Nous vous avons fourni une ligne qui stocke une référence de l'<code><img></code> concerné dans une variable nommée <code>displayedImg</code>. Notez que nous voulons une fonction nommée.</li> -</ol> +1. Trouver la valeur de l'attribut `src` de l'image courante. Cela peut être fait avec la fonction [`getAttribute()`](/fr/docs/Web/API/Element/getAttribute) sur `<img>`, en lui passant le paramètre `"src"` à chaque fois. Mais comment avoir l'image? Utiliser `newImage` ne marche pas du fait que la boucle est finie avant que le gestionnaire d'événement ne soit appelé; de cette manière, la valeur de `src` sera toujours celle du dernier `<img>`. Pour résoudre cela, gardez à l'esprit que, pour chaque gestionnaire d'événement, c'est `<img>` qui en est la cible. Pourquoi ne pas récupérer l'information de l'objet événement? +2. Exécuter une fonction, en lui passant en paramètre la fameuse valeur de `src`. Vous pouvez nommer la fonction à votre guise. +3. Cette fonction du gestionnaire d'événement doit définir la valeur de l'attribut `src` de `displayed-img <img>` à la valeur du `src` passé en paramètre. Nous vous avons fourni une ligne qui stocke une référence de l'`<img>` concerné dans une variable nommée `displayedImg`. Notez que nous voulons une fonction nommée. -<h3 id="Écrire_le_gestionnaire_du_bouton_dassombrissement">Écrire le gestionnaire du bouton d'assombrissement</h3> +### Écrire le gestionnaire du bouton d'assombrissement -<p>Il ne reste que notre <code><button></code> d'assombrissement — nous vous avons fourni une ligne qui stocke une référence au <code><button></code> dans une variable appelée <code>btn</code>. Vous devez ajouter un gestionnaire <code>onclick</code> qui:</p> +Il ne reste que notre `<button>` d'assombrissement — nous vous avons fourni une ligne qui stocke une référence au `<button>` dans une variable appelée `btn`. Vous devez ajouter un gestionnaire `onclick` qui: -<ol> - <li>Vérifie la classe appliquée à <code><button></code> — à nouveau, vous pouvez utiliser <code>getAttribute()</code>.</li> - <li>Si le nom de classe est <code>"dark"</code>, changer la classe du <code><button></code> pour <code>"light"</code> (avec <code><a href="/fr/docs/Web/API/Element/setAttribute">setAttribute()</a></code>), son contenu textuel par "Lighten", et le {{cssxref("background-color")}} du voile d'assombrissement <code><div></code> par <code>"rgba(0,0,0,0.5)"</code>.</li> - <li>Si le nom de classe n'est pas <code>"dark"</code>, changer la classe du <code><button></code> pour <code>"dark"</code>, son contenu textuel par "Darken", et le {{cssxref("background-color")}} du voile d'assombrissement <code><div></code> par <code>"rgba(0,0,0,0)"</code>.</li> -</ol> +1. Vérifie la classe appliquée à `<button>` — à nouveau, vous pouvez utiliser `getAttribute()`. +2. Si le nom de classe est `"dark"`, changer la classe du `<button>` pour `"light"` (avec [`setAttribute()`](/fr/docs/Web/API/Element/setAttribute)), son contenu textuel par "Lighten", et le {{cssxref("background-color")}} du voile d'assombrissement `<div>` par `"rgba(0,0,0,0.5)"`. +3. Si le nom de classe n'est pas `"dark"`, changer la classe du `<button>` pour `"dark"`, son contenu textuel par "Darken", et le {{cssxref("background-color")}} du voile d'assombrissement `<div>` par `"rgba(0,0,0,0)"`. -<p>Les lignes suivantes fournissent une base pour réaliser les changements décrits aux points 2 et 3.</p> +Les lignes suivantes fournissent une base pour réaliser les changements décrits aux points 2 et 3. -<pre class="brush: js">btn.setAttribute('class', xxx); +```js +btn.setAttribute('class', xxx); btn.textContent = xxx; -overlay.style.backgroundColor = xxx;</pre> +overlay.style.backgroundColor = xxx; +``` + +## Conseil -<h2 id="Conseil">Conseil</h2> +- Vous n'avez pas besoin d'éditer le code HTML ni le code CSS. -<ul> - <li>Vous n'avez pas besoin d'éditer le code HTML ni le code CSS.</li> -</ul> +## Évaluation ou aide supplémentaire -<h2 id="Évaluation_ou_aide_supplémentaire">Évaluation ou aide supplémentaire</h2> +Si vous souhaitez que votre travail soit évalué, ou si vous êtes bloqué et que vous voulez demander de l'aide : -<p>Si vous souhaitez que votre travail soit évalué, ou si vous êtes bloqué et que vous voulez demander de l'aide :</p> +1. Mettez votre travail dans un éditeur partageable en ligne tel que [CodePen](https://codepen.io/), [jsFiddle](https://jsfiddle.net/), ou [Glitch](https://glitch.com/). +2. Rédiger un sujet pour demander une évaluation et/ou une aide à le [forum Discourse du MDN](https://discourse.mozilla.org/c/mdn). Ajoutez la balise "learning" à votre message pour que nous puissions le trouver plus facilement. Votre message doit inclure : -<ol> - <li>Mettez votre travail dans un éditeur partageable en ligne tel que <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a>.</li> - <li>Rédiger un sujet pour demander une évaluation et/ou une aide à le <a href="https://discourse.mozilla.org/c/mdn">forum Discourse du MDN</a>. Ajoutez la balise "learning" à votre message pour que nous puissions le trouver plus facilement. Votre message doit inclure : - <ul> - <li>Un titre descriptif tel que "Évaluation demandée pour la galerie d'images".</li> - <li>Des détails sur ce que vous souhaitez que nous fassions — par exemple ce que vous avez déjà essayé, si vous êtes bloqué et avez besoin d'aide.</li> - <li>Un lien vers l'exemple que vous souhaitez faire évaluer ou pour lequel vous avez besoin d'aide, dans un éditeur en ligne. C'est une bonne pratique à adopter — il est très difficile d'aider une personne ayant un problème de codage si on ne peut pas voir son code.</li> - <li>Un lien vers la page de la tâche ou de l'évaluation proprement dite, afin que nous puissions trouver la question pour laquelle vous souhaitez de l'aide.</li> - </ul> - </li> -</ol> + - Un titre descriptif tel que "Évaluation demandée pour la galerie d'images". + - Des détails sur ce que vous souhaitez que nous fassions — par exemple ce que vous avez déjà essayé, si vous êtes bloqué et avez besoin d'aide. + - Un lien vers l'exemple que vous souhaitez faire évaluer ou pour lequel vous avez besoin d'aide, dans un éditeur en ligne. C'est une bonne pratique à adopter — il est très difficile d'aider une personne ayant un problème de codage si on ne peut pas voir son code. + - Un lien vers la page de la tâche ou de l'évaluation proprement dite, afin que nous puissions trouver la question pour laquelle vous souhaitez de l'aide. -<p>Si vous suivez cette évaluation dans le cadre d'un cours organisé, vous devriez pouvoir donner votre travail à votre professeur ou mentor pour la notation. Si vous apprenez en autodidacte, vous pouvez obtenir le guide de notation simplement en le demandant <a href="https://discourse.mozilla.org/t/image-gallery-assessment/24687">sur le fil de discussion de cet exercice</a>, ou sur <a href="irc://irc.mozilla.org/mdn">#mdn</a> du canal IRC de <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Faites d'abord l'exercice, vous ne gagnerez rien à tricher!</p> +Si vous suivez cette évaluation dans le cadre d'un cours organisé, vous devriez pouvoir donner votre travail à votre professeur ou mentor pour la notation. Si vous apprenez en autodidacte, vous pouvez obtenir le guide de notation simplement en le demandant [sur le fil de discussion de cet exercice](https://discourse.mozilla.org/t/image-gallery-assessment/24687), ou sur [#mdn](irc://irc.mozilla.org/mdn) du canal IRC de [Mozilla IRC](https://wiki.mozilla.org/IRC). Faites d'abord l'exercice, vous ne gagnerez rien à tricher! -<p>{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</p> +{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}} -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/conditionals">Prendre des décisions dans le code — conditions</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code">Les boucles dans le code</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Fonctions">Fonctions — des blocs de code réutilisables</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Construire vos propres fonctions</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Return_values">Valeurs de retour des fonctions</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">Introduction aux événements</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Image_gallery">Galerie d'images</a></li> -</ul> +- [Prendre des décisions dans le code — conditions](/fr/docs/Apprendre/JavaScript/Building_blocks/conditionals) +- [Les boucles dans le code](/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code) +- [Fonctions — des blocs de code réutilisables](/fr/docs/Apprendre/JavaScript/Building_blocks/Fonctions) +- [Construire vos propres fonctions](/fr/docs/Apprendre/JavaScript/Building_blocks/Build_your_own_function) +- [Valeurs de retour des fonctions](/fr/docs/Apprendre/JavaScript/Building_blocks/Return_values) +- [Introduction aux événements](/fr/docs/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements) +- [Galerie d'images](/fr/docs/Apprendre/JavaScript/Building_blocks/Image_gallery) diff --git a/files/fr/learn/javascript/building_blocks/index.md b/files/fr/learn/javascript/building_blocks/index.md index f93cdfbd85..bb9e1f50da 100644 --- a/files/fr/learn/javascript/building_blocks/index.md +++ b/files/fr/learn/javascript/building_blocks/index.md @@ -13,44 +13,36 @@ tags: translation_of: Learn/JavaScript/Building_blocks original_slug: Apprendre/JavaScript/Building_blocks --- -<div>{{JsSidebar}}</div> +{{JsSidebar}}{{PreviousNext("Learn/JavaScript/First_steps", "Learn/JavaScript/Objects")}} -<div>{{PreviousNext("Learn/JavaScript/First_steps", "Learn/JavaScript/Objects")}}</div> +Dans ce module nous allons continuer à voir l'ensemble des fonctionnalités clefs du JavaScript en nous concentrant plus particulièrement sur les structures les plus répandues telles que les conditions, les boucles, les fonctions et les événements. Nous avons déjà vu ces notions dans le cours mais sans nous y attarder, nous allons maintenant les étudier en détails. -<p>Dans ce module nous allons continuer à voir l'ensemble des fonctionnalités clefs du JavaScript en nous concentrant plus particulièrement sur les structures les plus répandues telles que les conditions, les boucles, les fonctions et les événements. Nous avons déjà vu ces notions dans le cours mais sans nous y attarder, nous allons maintenant les étudier en détails.</p> +## Prérequis -<h2 id="Prérequis">Prérequis</h2> +Avant de commencer ce module, vous devriez connaître les bases du [HTML ](/fr/Apprendre/HTML/Introduction_%C3%A0_HTML)et du [CSS ](/fr/Apprendre/CSS/Introduction_%C3%A0_CSS)et avoir suivi le module précédent, [JavaScript Premiers Pas.](/fr/docs/Learn/JavaScript/First_steps) -<p>Avant de commencer ce module, vous devriez connaître les bases du <a href="/fr/Apprendre/HTML/Introduction_%C3%A0_HTML">HTML </a>et du <a href="/fr/Apprendre/CSS/Introduction_%C3%A0_CSS">CSS </a>et avoir suivi le module précédent, <a href="/fr/docs/Learn/JavaScript/First_steps">JavaScript Premiers Pas.</a></p> +> **Note :** Si vous travaillez depuis un ordinateur, une tablette ou depuis un autre appareil sur lequel vous ne pouvez pas créer vos propres fichiers, ce n'est pas un problème, vous pourrez essayer la plupart des exemples en lignes grâce à des outils comme [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/) . -<div class="note"> -<p><strong>Note :</strong> Si vous travaillez depuis un ordinateur, une tablette ou depuis un autre appareil sur lequel vous ne pouvez pas créer vos propres fichiers, ce n'est pas un problème, vous pourrez essayer la plupart des exemples en lignes grâce à des outils comme <a class="external external-icon" href="http://jsbin.com/">JSBin</a> ou <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> .</p> -</div> +## Guides -<h2 id="Guides">Guides</h2> +- [Prendre des décisions dans votre code — les conditions](/fr/docs/Learn/JavaScript/Building_blocks/conditionals) + - : Quelque soit le langage de programmation, notre programme doit prendre des décisions et effectuer des actions différentes selon les valeurs traitées. Dans un jeu par exemple, si le nombre de vies du joueur est égal à 0, le jeu s'achève. Sur le même principe, une application météo affiche un fond d'aube si elle est lancée le matin, des étoiles et la Lune si, au contraire, elle est lancée la nuit. Dans cet article, nous allons voir comment les structures conditionnelles fonctionnent en JavaScript. +- [Les boucles](/fr/Apprendre/JavaScript/Building_blocks/Looping_code) + - : Parfois une action doit être réalisée plusieurs fois d'affilée. Par exemple, parcourir une liste de noms. En programmation, les boucles effectuent ce genre de tâches à merveille. Ici, nous allons examiner les structures de boucles en JavaScript. +- [Les fonctions — réutiliser des blocs de code](/fr/docs/Learn/JavaScript/Building_blocks/Functions) + - : Un autre concept essentiel en programmation est celui de **fonctions.** Les **fonctions** permettent de définir un morceau de code réalisant une tâche particulière qui pourra être appelé ultérieurement dans le reste du programme par une simple ligne, ce qui évite d'écrire plusieurs fois le même code. Dans cet article, nous allons voir les concepts qui se cachent derrière les fonctions tels que la syntaxe de base, la définition et l'appel d'une fonction, sa portée et ses paramètres. +- [Créez votre propre fonction](/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function) + - : L'essentiel sur la théorie des fonctions a été traité dans le chapitre précédent, cet article va vous permettre de mettre en pratique vos connaissances avec un exercice. Nous allons construire notre propre fonction et nous en profiterons pour expliquer quelques notions plus avancées, utiles pour travailler avec les fonctions. +- [Les valeurs de retour des fonctions](/fr/docs/Learn/JavaScript/Building_blocks/Return_values) + - : Il reste un dernier point à vous présenter avant de terminer cette partie sur les fonctions, il s'agit des valeurs retournées. Une fois leur exécution finie, les fonctions renvoient des valeurs, pour certaines d'entre-elles ce retour nous est utile. Il est important de bien comprendre ce que sont ces valeurs, comment les utiliser dans notre programme et comment faire en sorte que nos fonctions renvoient des valeurs qui nous soient utiles. +- [Introduction aux événements](/fr/docs/Learn/JavaScript/Building_blocks/Events) + - : Les événements sont des actions ou occurences qui surviennent au cours de l'exécution de votre programme, auxquels vous pouvez répondre de la manière que vous souhaitez. Par exemple, si l'utilisateur clique sur une page web, vous pourriez vouloir répondre à cette action en affichant un élément d'information. Dans ce dernier article, nous allons voir des concepts importants se rapportant aux événements et voir la manière dont ils fonctionnent au sein des navigateurs. -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/Building_blocks/conditionals">Prendre des décisions dans votre code — les conditions</a></dt> - <dd>Quelque soit le langage de programmation, notre programme doit prendre des décisions et effectuer des actions différentes selon les valeurs traitées. Dans un jeu par exemple, si le nombre de vies du joueur est égal à 0, le jeu s'achève. Sur le même principe, une application météo affiche un fond d'aube si elle est lancée le matin, des étoiles et la Lune si, au contraire, elle est lancée la nuit. Dans cet article, nous allons voir comment les structures conditionnelles fonctionnent en JavaScript.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Building_blocks/Looping_code">Les boucles</a></dt> - <dd>Parfois une action doit être réalisée plusieurs fois d'affilée. Par exemple, parcourir une liste de noms. En programmation, les boucles effectuent ce genre de tâches à merveille. Ici, nous allons examiner les structures de boucles en JavaScript.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions">Les fonctions — réutiliser des blocs de code</a></dt> - <dd>Un autre concept essentiel en programmation est celui de <strong>fonctions. </strong>Les<strong> fonctions</strong> permettent de définir un morceau de code réalisant une tâche particulière qui pourra être appelé ultérieurement dans le reste du programme par une simple ligne, ce qui évite d'écrire plusieurs fois le même code. Dans cet article, nous allons voir les concepts qui se cachent derrière les fonctions tels que la syntaxe de base, la définition et l'appel d'une fonction, sa portée et ses paramètres.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Créez votre propre fonction</a></dt> - <dd>L'essentiel sur la théorie des fonctions a été traité dans le chapitre précédent, cet article va vous permettre de mettre en pratique vos connaissances avec un exercice. Nous allons construire notre propre fonction et nous en profiterons pour expliquer quelques notions plus avancées, utiles pour travailler avec les fonctions.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Building_blocks/Return_values">Les valeurs de retour des fonctions</a></dt> - <dd>Il reste un dernier point à vous présenter avant de terminer cette partie sur les fonctions, il s'agit des valeurs retournées. Une fois leur exécution finie, les fonctions renvoient des valeurs, pour certaines d'entre-elles ce retour nous est utile. Il est important de bien comprendre ce que sont ces valeurs, comment les utiliser dans notre programme et comment faire en sorte que nos fonctions renvoient des valeurs qui nous soient utiles.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Building_blocks/Events">Introduction aux événements</a></dt> - <dd>Les événements sont des actions ou occurences qui surviennent au cours de l'exécution de votre programme, auxquels vous pouvez répondre de la manière que vous souhaitez. Par exemple, si l'utilisateur clique sur une page web, vous pourriez vouloir répondre à cette action en affichant un élément d'information. Dans ce dernier article, nous allons voir des concepts importants se rapportant aux événements et voir la manière dont ils fonctionnent au sein des navigateurs.</dd> -</dl> +## Auto-évaluation -<h2 id="Auto-évaluation">Auto-évaluation</h2> +L'auto-évaluation suivante teste votre compréhension des bases du JavaScript vues dans le guide ci-dessus. -<p>L'auto-évaluation suivante teste votre compréhension des bases du JavaScript vues dans le guide ci-dessus.</p> +- [Galerie de photos](/fr/docs/Learn/JavaScript/Building_blocks/Image_gallery) + - : Maintenant que vous avez fini ce chapitre sur la construction de blocs en JavaScript, vous allez pouvoir tester vos connaissances sur les boucles, les fonctions, les conditions et les événements en codant un élément que l'on retrouve sur de très nombreux sites web, une galerie de photos en JavaScript. -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/Building_blocks/Image_gallery">Galerie de photos</a></dt> - <dd>Maintenant que vous avez fini ce chapitre sur la construction de blocs en JavaScript, vous allez pouvoir tester vos connaissances sur les boucles, les fonctions, les conditions et les événements en codant un élément que l'on retrouve sur de très nombreux sites web, une galerie de photos en JavaScript.</dd> -</dl> - -<p>{{PreviousNext("Learn/JavaScript/First_steps", "Learn/JavaScript/Objects")}} </p> +{{PreviousNext("Learn/JavaScript/First_steps", "Learn/JavaScript/Objects")}} diff --git a/files/fr/learn/javascript/building_blocks/looping_code/index.md b/files/fr/learn/javascript/building_blocks/looping_code/index.md index fcd352b560..11c8dc0c25 100644 --- a/files/fr/learn/javascript/building_blocks/looping_code/index.md +++ b/files/fr/learn/javascript/building_blocks/looping_code/index.md @@ -18,72 +18,73 @@ tags: translation_of: Learn/JavaScript/Building_blocks/Looping_code original_slug: Apprendre/JavaScript/Building_blocks/Looping_code --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}</div> - -<p>Les langages de programmation sont très utiles pour effectuer des tâches répétitives, allant de calculs basiques à à peu près n'importe quelle autre situation où vous avez un certain nombre d'actions similaires à répéter. Ici, nous allons étudier les structures de boucle disponible dans JavaScript qui répondent à un tel besoin.</p> +Les langages de programmation sont très utiles pour effectuer des tâches répétitives, allant de calculs basiques à à peu près n'importe quelle autre situation où vous avez un certain nombre d'actions similaires à répéter. Ici, nous allons étudier les structures de boucle disponible dans JavaScript qui répondent à un tel besoin. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Culture informatique basique, compréhension basique du HTML et du CSS, <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript...</a></td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre comment utiliser les boucles dans JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Culture informatique basique, compréhension basique du HTML et du CSS, + <a href="/fr/docs/Learn/JavaScript/First_steps" + >Premiers pas en JavaScript...</a + > + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre comment utiliser les boucles dans JavaScript.</td> + </tr> + </tbody> </table> -<h2 id="Laissez-moi_dans_la_boucle">Laissez-moi dans la boucle</h2> +## Laissez-moi dans la boucle -<p>Boucles, boucles, boucles. Alors qu'elles sont associées aux <a href="https://fr.wikipedia.org/wiki/Boucles_d%27or_et_les_Trois_Ours">cheveux d'une célèbre héroïne de fiction</a>, elles sont également un concept extrêmement important en programmation. Les boucles de programmation ne font que faire la même action encore et toujours – ce qui se traduit par <strong>itérer</strong> en langage de programmeur.</p> +Boucles, boucles, boucles. Alors qu'elles sont associées aux [cheveux d'une célèbre héroïne de fiction](https://fr.wikipedia.org/wiki/Boucles_d%27or_et_les_Trois_Ours), elles sont également un concept extrêmement important en programmation. Les boucles de programmation ne font que faire la même action encore et toujours – ce qui se traduit par **itérer** en langage de programmeur. -<p>Commençons par examiner le cas d'un fermier qui doit s'assurer d'avoir assez de nourriture pour nourrir sa famille pour la semaine. Il pourrait ainsi utiliser la boucle suivante :</p> +Commençons par examiner le cas d'un fermier qui doit s'assurer d'avoir assez de nourriture pour nourrir sa famille pour la semaine. Il pourrait ainsi utiliser la boucle suivante : -<p><br> - <img alt="" src="loop_js-02-farm.png"></p> + -<p>Une boucle a normalement un ou plusieurs des composants suivants :</p> +Une boucle a normalement un ou plusieurs des composants suivants : -<ul> - <li> Un <strong>compteur</strong>, qui est initialisé à une certaine valeur - c'est le point de départ de la boucle ("Départ : Je n'ai pas de nourriture / I have no food", ci-dessus).</li> - <li>Une <strong>condition de sortie</strong>, qui est le critère grâce auquel la boucle s'arrête - la plupart du temps, il s'agira d'une certaine valeur que le compteur doit atteindre. Elle est illustrée ci-dessus par "Ai-je assez de nourriture ? / Have I got enough food?". Disons qu'il aura besoin de 10 portions de nourriture pour nourir sa famille.</li> - <li>Un <strong>itérateur</strong>, qui incrémente généralement le compteur petit-à-petit à chaque boucle successive, jusqu'à ce que ceui-ci remplisse la condition de sortie. Nous n'avons pas explicitement illustré cela ci-dessus, mais nous pouvons penser que le fermier peut récolter 2 portions de nourriture par heure. On peut donc dire que, toutes les heures, la quantité de nourriture collectée est incrémentée de 2, et il regarde s'il a assez de nourriture. S'il a atteint 10 portions (la condition de sortie), il peut arrêter sa récolte et rentrer chez lui, satisfait de sa journée.</li> -</ul> +- Un **compteur**, qui est initialisé à une certaine valeur - c'est le point de départ de la boucle ("Départ : Je n'ai pas de nourriture / I have no food", ci-dessus). +- Une **condition de sortie**, qui est le critère grâce auquel la boucle s'arrête - la plupart du temps, il s'agira d'une certaine valeur que le compteur doit atteindre. Elle est illustrée ci-dessus par "Ai-je assez de nourriture ? / Have I got enough food?". Disons qu'il aura besoin de 10 portions de nourriture pour nourir sa famille. +- Un **itérateur**, qui incrémente généralement le compteur petit-à-petit à chaque boucle successive, jusqu'à ce que ceui-ci remplisse la condition de sortie. Nous n'avons pas explicitement illustré cela ci-dessus, mais nous pouvons penser que le fermier peut récolter 2 portions de nourriture par heure. On peut donc dire que, toutes les heures, la quantité de nourriture collectée est incrémentée de 2, et il regarde s'il a assez de nourriture. S'il a atteint 10 portions (la condition de sortie), il peut arrêter sa récolte et rentrer chez lui, satisfait de sa journée. -<p>En {{glossary("pseudocode")}}, cela ressemblerait à ce qui suit :</p> +En {{glossary("pseudocode")}}, cela ressemblerait à ce qui suit : -<pre>loop(nourriture = 0; besoinNourriture = 10) { - if (nourriture = besoinNourriture) { - exit loop; - // Nous avons assez de nourriture, on rentre - } else { - nourriture += 2; // On doit rester 1 heure de plus - // La boucle se répète ensuite - } -}</pre> + loop(nourriture = 0; besoinNourriture = 10) { + if (nourriture = besoinNourriture) { + exit loop; + // Nous avons assez de nourriture, on rentre + } else { + nourriture += 2; // On doit rester 1 heure de plus + // La boucle se répète ensuite + } + } -<p>La quantité de nourriture dont le fermier a besoin est donc initialisée à 10, et la quantité dont il dispose est initialisée à 0. A chaque itération de la boucle, on vérifie si la quantité de nourriture dont le fermier dispose est égale à la quantité requise. Si c'est le cas, on peut sortir de la boucle. Sinon, le fermier passe une heure de plus à récolter de la nourriture, et la boucle itère à nouveau.</p> +La quantité de nourriture dont le fermier a besoin est donc initialisée à 10, et la quantité dont il dispose est initialisée à 0. A chaque itération de la boucle, on vérifie si la quantité de nourriture dont le fermier dispose est égale à la quantité requise. Si c'est le cas, on peut sortir de la boucle. Sinon, le fermier passe une heure de plus à récolter de la nourriture, et la boucle itère à nouveau. -<h3 id="À_quoi_ça_sert">À quoi ça sert ?</h3> +### À quoi ça sert ? -<p>Arrivé à ce stade, vous avez sans doute compris le concept global des boucles, mais vous vous dites probablement : "Ok, bien, mais comment cela va-t-il m'aider à améliorer mes codes en JavaScript ?". Comme nous l'avons dit plus tôt, <strong>les boucles ne font rien d'autre que répéter la même action encore et encore</strong>, ce qui peut s'avérer utile pour <strong>effectuer rapidement des tâches répétitives</strong>.</p> +Arrivé à ce stade, vous avez sans doute compris le concept global des boucles, mais vous vous dites probablement : "Ok, bien, mais comment cela va-t-il m'aider à améliorer mes codes en JavaScript ?". Comme nous l'avons dit plus tôt, **les boucles ne font rien d'autre que répéter la même action encore et encore**, ce qui peut s'avérer utile pour **effectuer rapidement des tâches répétitives**. -<p>Souvent, le code sera légèrement différent à chaque itération successive, ce qui signifie que vous pouvez effectuer une certaine quantité de tâches similaires, mais néanmoins quelque peu différentes - si vous avez beaucoup de calculs différents à effectuer, vous n'allez pas effectuer le même calcul encore et encore !</p> +Souvent, le code sera légèrement différent à chaque itération successive, ce qui signifie que vous pouvez effectuer une certaine quantité de tâches similaires, mais néanmoins quelque peu différentes - si vous avez beaucoup de calculs différents à effectuer, vous n'allez pas effectuer le même calcul encore et encore ! -<p>Regardons maintenant un exemple qui illustre parfaitement en quoi les boucles sont si intéressantes. Disons que nous voulons dessiner 100 cercles aléatoirement sur un <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/random-canvas-circles.html" title="L'élément <canvas> permet de modifier une zone graphique via un script (habituellement en JavaScript ou grâce à WebGL). Il peut par exemple être utilisé afin de dessiner des graphiques, manipuler des images ou jouer des animations."><code><canvas></code></a> (appuyez sur le bouton <em>Update</em> pour lancer le programme à nouveau et voir différentes dispositions aléatoires).</p> +Regardons maintenant un exemple qui illustre parfaitement en quoi les boucles sont si intéressantes. Disons que nous voulons dessiner 100 cercles aléatoirement sur un [`<canvas>`](http://mdn.github.io/learning-area/javascript/building-blocks/loops/random-canvas-circles.html "L'élément <canvas> permet de modifier une zone graphique via un script (habituellement en JavaScript ou grâce à WebGL). Il peut par exemple être utilisé afin de dessiner des graphiques, manipuler des images ou jouer des animations.") (appuyez sur le bouton _Update_ pour lancer le programme à nouveau et voir différentes dispositions aléatoires). -<h4>Exemple</h4> +#### Exemple -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Random canvas circles</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Random canvas circles</title> + <style> html { width: 100%; height: inherit; @@ -103,15 +104,15 @@ original_slug: Apprendre/JavaScript/Building_blocks/Looping_code top: 5px; left: 5px; } - </style> - </head> - <body> + </style> + </head> + <body> - <button>Update</button> + <button>Update</button> - <canvas></canvas> + <canvas></canvas> - <script> + <script> const bouton = document.querySelector('button'); const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); @@ -128,7 +129,7 @@ original_slug: Apprendre/JavaScript/Building_blocks/Looping_code function draw() { ctx.clearRect(0, 0, WIDTH, HEIGHT); - for (let i = 0; i < 100; i++) { + for (let i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = 'rgba(255,0,0,0.5)'; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); @@ -138,169 +139,165 @@ original_slug: Apprendre/JavaScript/Building_blocks/Looping_code bouton.addEventListener('click',draw); - </script> + </script> - </body> -</html></pre> + </body> +</html> +``` -<p>{{ EmbedLiveSample('Exemple', '100%', 400) }}</p> +{{ EmbedLiveSample('Exemple', '100%', 400) }} -<h4>Principe de boucle</h4> +#### Principe de boucle -<p>Vous n'avez pas besoin de comprendre entièrement le code pour l'instant, mais regardons plus en détail la partie du code qui trace les 100 cercles :</p> +Vous n'avez pas besoin de comprendre entièrement le code pour l'instant, mais regardons plus en détail la partie du code qui trace les 100 cercles : -<pre class="brush: js">for (let i = 0; i < 100; i++) { +```js +for (let i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = 'rgba(255,0,0,0.5)'; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); ctx.fill(); -}</pre> +} +``` -<p>Vous devriez comprendre l'idée basique - nous utilisons une boucle pour effectuer 100 itérations de ce code, chacune dessinant un cercle à une position quelconque sur la page. La quantité de lignes de code nécessaire serait identique si l'on voulait tracer 100 cercles, 1000 ou même 100000. Seul le nombre d'itérations devrait changer.</p> +Vous devriez comprendre l'idée basique - nous utilisons une boucle pour effectuer 100 itérations de ce code, chacune dessinant un cercle à une position quelconque sur la page. La quantité de lignes de code nécessaire serait identique si l'on voulait tracer 100 cercles, 1000 ou même 100000. Seul le nombre d'itérations devrait changer. -<p>Si nous n'utilisions pas de boucle ici, nous aurions du répéter le code suivant pour chaque cercle que nous aurions voulu dessiner :</p> +Si nous n'utilisions pas de boucle ici, nous aurions du répéter le code suivant pour chaque cercle que nous aurions voulu dessiner : -<pre class="brush: js">ctx.beginPath(); +```js +ctx.beginPath(); ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); -ctx.fill();</pre> +ctx.fill(); +``` + +Mais cela prend du temps inutilement, et rend le code difficilement maintenable. Les boucles sont vraiment les meilleures. -<p>Mais cela prend du temps inutilement, et rend le code difficilement maintenable. Les boucles sont vraiment les meilleures.</p> +## La boucle standard -<h2 id="La_boucle_standard">La boucle standard</h2> +Commençons maintenant à voir quelques formes de boucles spécifiques. La première, celle que vous utiliserez le plus souvent, est la boucle [for](/fr/docs/Web/JavaScript/Reference/Instructions/for). Elle a la syntaxe suivante : -<p>Commençons maintenant à voir quelques formes de boucles spécifiques. La première, celle que vous utiliserez le plus souvent, est la boucle <a href="/fr/docs/Web/JavaScript/Reference/Instructions/for">for</a>. Elle a la syntaxe suivante :</p> + for (initialisation; condition de sortie; expression finale) { + // code à exécuter + } + +Nous avons ici : -<pre>for (initialisation; condition de sortie; expression finale) { - // code à exécuter -}</pre> +1. Le mot-clé `for`, suivi par des parenthèses. +2. A l'intérieur des parenthèses, on a trois objets : -<p>Nous avons ici :</p> + 1. Une **initialisation** — il s'agit souvent d'une variable initialisée à une certaine valeur, qui est incrémentée afin de compter le nombre de fois où la boucle s'est exécutée. On peut également la nommer **compteur**. + 2. Une **condition de sortie** — comme mentionné précédemment, cela définit le moment où la boucle doit arrêter de s'exécuter. C'est généralement une expression contenant un opérateur de comparaison, un test pour voir si la condition de sortie est atteinte. + 3. Une **expression finale** — Elle est toujours évaluée (ou exécutée) chaque fois que la boucle a effectué une itération complète. Cela sert souvent à incrémenter (ou dans certains cas décrémenter) le compteur, pour le rapprocher de la valeur de la condition de sortie. -<ol> - <li>Le mot-clé <code>for</code>, suivi par des parenthèses.</li> - <li>A l'intérieur des parenthèses, on a trois objets : - <ol> - <li>Une <strong>initialisation</strong> — il s'agit souvent d'une variable initialisée à une certaine valeur, qui est incrémentée afin de compter le nombre de fois où la boucle s'est exécutée. On peut également la nommer <strong>compteur</strong>.</li> - <li>Une <strong>condition de sortie</strong> — comme mentionné précédemment, cela définit le moment où la boucle doit arrêter de s'exécuter. C'est généralement une expression contenant un opérateur de comparaison, un test pour voir si la condition de sortie est atteinte.</li> - <li>Une <strong>expression finale</strong> — Elle est toujours évaluée (ou exécutée) chaque fois que la boucle a effectué une itération complète. Cela sert souvent à incrémenter (ou dans certains cas décrémenter) le compteur, pour le rapprocher de la valeur de la condition de sortie.</li> - </ol> - </li> - <li>Des accolades contenant un bloc de code — ce code sera exécuté chaque fois que la boucle itère.</li> -</ol> +3. Des accolades contenant un bloc de code — ce code sera exécuté chaque fois que la boucle itère. -<p>Regardons maintenant un vrai exemple, afin de visualiser leurs actions plus clairement.</p> +Regardons maintenant un vrai exemple, afin de visualiser leurs actions plus clairement. -<pre class="brush: js">const chats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; +```js +const chats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; let info = "Mes chat s'appellent "; const paragraphe = document.querySelector('p'); -for (let i = 0; i < chats.length; i++) { +for (let i = 0; i < chats.length; i++) { info += chats[i] + ', '; } -paragraphe.textContent = info;</pre> +paragraphe.textContent = info; +``` -<h3>Sortie</h3> +### Sortie -<p>Cela nous donne la sortie suivante :</p> +Cela nous donne la sortie suivante : -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Exemple de boucles</title> - </head> - <body> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Exemple de boucles</title> + </head> + <body> - <p></p> + <p></p> - <script> + <script> const chats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; let info = "Mes chats s'appellent "; const paragraphe = document.querySelector('p'); - for (let i = 0; i < chats.length; i++) { + for (let i = 0; i < chats.length; i++) { info += chats[i] + ', '; } paragraphe.textContent = info; - </script> + </script> - </body> -</html></pre> + </body> +</html> +``` -<p>{{ EmbedLiveSample('Sortie', '100%', 60) }}</p> +{{ EmbedLiveSample('Sortie', '100%', 60) }} -<div class="note"> -<p><strong>Note :</strong> Vous pouvez trouver aussi cet <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for.html">exemple de code sur GitHub</a> (et<a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for.html"> le voir tourner en live</a>).</p> -</div> +> **Note :** Vous pouvez trouver aussi cet [exemple de code sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for.html) (et[ le voir tourner en live](http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for.html)). -<p>Cela montre une boucle utiliser pour itérer sur les éléments d'un tableau et faire quelque chose avec chacun d'eux — un schéma très commun en JavaScript. Ici :</p> - -<ol> - <li>L'itérateur, <code>i</code>, commence à <code>0</code> (<code>let i = 0</code>).</li> - <li>On lui a demandé de s'exécuter jusqu'à ce que sa valeur ne soit plus inférieure à la longueur du tableau chats. C'est important — la condition de sortie montre la condition à laquelle la boucle continue de s'exécuter. C'est à dire dans ce cas, tant que <code>i < chats.length</code> est vrai, la boucle continuera à s'exécuter.</li> - <li>Au sein de la boucle, on concatène les élèments présents dans cette boucle (<code>cats[i]</code> est <code>cats[quelque soit la valeur de i lors de l'iteration]</code>) avec une virgule et un espace, à la fin de la variable <code>info</code>. Donc : - <ol> - <li>Pendant le premier lancement, <code>i = 0</code>, donc <code>cats[0] + ', '</code> sera concaténé à ("Bill, ")</li> - <li>Au second lancement, <code>i = 1</code>, donc <code>cats[1] + ', '</code> et sera concaténé à ("Jeff, ")</li> - <li>Et ainsi de suite. Aprés chaque tour de boucle, 1 est ajouté à <code>i</code> (<code>i++</code>), et alors le processus recommence encore.</li> - </ol> - </li> - <li>Quand <code>i</code> devient égal à <code>cats.length</code>, la boucle s'arrête, et le navigateur va bouger au prochain bout de code aprés la boucle.</li> -</ol> - -<div class="note"> -<p><strong>Note :</strong> Nous avons fait sortir la condition <code>i < cats.length</code>, et pas <code>i <= cats.length</code>, parce que les ordinateurs comptent à partir de 0, pas 1 — nous avons démarré <code>i</code> à <code>0</code>, et allons allers jusqu'à <code>i = 4</code> (l'index du dernier item de la table/tableau). <code>cats.length</code> retourne 5, comme il y a 5 items dans la table, nous n'allont pas aller à <code>i = 5</code>, cela retournerai <code>undefined</code> pour le dernier item (il n'y a pas de item de table avec un index de 5). Par conséquent, nous voulons aller de 1 à moins que <code>cats.length</code> (<code>i <</code>), ce n'est pas la même chose que <code>cats.length</code> (<code>i <=</code>).</p> -</div> +Cela montre une boucle utiliser pour itérer sur les éléments d'un tableau et faire quelque chose avec chacun d'eux — un schéma très commun en JavaScript. Ici : -<div class="note"> -<p><strong>Note :</strong> Une erreur commune avec les conditions de sortie est de les faire utiliser "égal à" plutôt que de dire "inférieur ou égal à". Si nous voulions faire tourner notre boucle jusqu'à i = 5, la condition de sortie aurait besoin d'être i <= cats.length / Si nous la mettons à i = cats.length, la boucle ne fonctionnerait pas du tout parce que i n'est pas égal à 5 sur la première itération de la boucle, de sorte que cela s'arrête immédiatement.</p> -</div> +1. L'itérateur, `i`, commence à `0` (`let i = 0`). +2. On lui a demandé de s'exécuter jusqu'à ce que sa valeur ne soit plus inférieure à la longueur du tableau chats. C'est important — la condition de sortie montre la condition à laquelle la boucle continue de s'exécuter. C'est à dire dans ce cas, tant que `i < chats.length` est vrai, la boucle continuera à s'exécuter. +3. Au sein de la boucle, on concatène les élèments présents dans cette boucle (`cats[i]` est `cats[quelque soit la valeur de i lors de l'iteration]`) avec une virgule et un espace, à la fin de la variable `info`. Donc : + + 1. Pendant le premier lancement, `i = 0`, donc `cats[0] + ', '` sera concaténé à ("Bill, ") + 2. Au second lancement, `i = 1`, donc `cats[1] + ', '` et sera concaténé à ("Jeff, ") + 3. Et ainsi de suite. Aprés chaque tour de boucle, 1 est ajouté à `i` (`i++`), et alors le processus recommence encore. + +4. Quand `i` devient égal à `cats.length`, la boucle s'arrête, et le navigateur va bouger au prochain bout de code aprés la boucle. -<p>Un petit problème est que nous avons laissé la phrase de sortie mal formée :</p> +> **Note :** Nous avons fait sortir la condition `i < cats.length`, et pas `i <= cats.length`, parce que les ordinateurs comptent à partir de 0, pas 1 — nous avons démarré `i` à `0`, et allons allers jusqu'à `i = 4` (l'index du dernier item de la table/tableau). `cats.length` retourne 5, comme il y a 5 items dans la table, nous n'allont pas aller à `i = 5`, cela retournerai `undefined` pour le dernier item (il n'y a pas de item de table avec un index de 5). Par conséquent, nous voulons aller de 1 à moins que `cats.length` (`i <`), ce n'est pas la même chose que `cats.length` (`i <=`). -<blockquote> -<p>Mes chats s'appellent Bill, Jeff, Pete, Biggles, Jasmin,</p> -</blockquote> +> **Note :** Une erreur commune avec les conditions de sortie est de les faire utiliser "égal à" plutôt que de dire "inférieur ou égal à". Si nous voulions faire tourner notre boucle jusqu'à i = 5, la condition de sortie aurait besoin d'être i <= cats.length / Si nous la mettons à i = cats.length, la boucle ne fonctionnerait pas du tout parce que i n'est pas égal à 5 sur la première itération de la boucle, de sorte que cela s'arrête immédiatement. -<p>Idéalement, nous voulons changer la concaténation sur l'itération de la boucle finale de sorte que nous n'ayons pas de virgule à la fin de la phrase. Bien, pas de problème – nous pouvons heureusement insérer une structure conditionnelle dans notre boucle for pour gérer ce cas particulier :</p> +Un petit problème est que nous avons laissé la phrase de sortie mal formée : -<pre class="brush: js">for (let i = 0; i < cats.length; i++) { +> Mes chats s'appellent Bill, Jeff, Pete, Biggles, Jasmin, + +Idéalement, nous voulons changer la concaténation sur l'itération de la boucle finale de sorte que nous n'ayons pas de virgule à la fin de la phrase. Bien, pas de problème – nous pouvons heureusement insérer une structure conditionnelle dans notre boucle for pour gérer ce cas particulier : + +```js +for (let i = 0; i < cats.length; i++) { if (i === cats.length - 1) { info += 'and ' + cats[i] + '.'; } else { info += cats[i] + ', '; } -}</pre> +} +``` -<div class="note"> -<p><strong>Note :</strong> Vous pouvez trouver cet exemple de code sur <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for-improved.html">GitHub</a> (et aussi le <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for-improved.html">voir en ligne</a>).</p> -</div> +> **Note :** Vous pouvez trouver cet exemple de code sur [GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for-improved.html) (et aussi le [voir en ligne](http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for-improved.html)). -<div class="warning"> -<p><strong>Attention :</strong> Avec for — comme avec toutes les boucles — vous devez vous assurer que l'initialiseur est itéré de sorte qu'il finisse par atteindre la condition de sortie. Si ce n'est pas le cas, la boucle continuera indéfiniment, et soit le navigateur l'arrêtera, soit il se bloquera. C'est ce qu'on appelle une <strong>boucle infinie.</strong></p> -</div> +> **Attention :** Avec for — comme avec toutes les boucles — vous devez vous assurer que l'initialiseur est itéré de sorte qu'il finisse par atteindre la condition de sortie. Si ce n'est pas le cas, la boucle continuera indéfiniment, et soit le navigateur l'arrêtera, soit il se bloquera. C'est ce qu'on appelle une **boucle infinie.** -<h2 id="Quitter_une_boucle_avec_break">Quitter une boucle avec break</h2> +## Quitter une boucle avec break -<p>Si vous voulez quitter une boucle avant que toutes les itérations aient été terminées, vous pouvez utiliser l'instruction <a href="/fr/docs/Web/JavaScript/Reference/Instructions/break">break</a>. Nous l'avons déjà rencontré dans l'article précédent lorsque nous examinions les <a href="/fr/Apprendre/JavaScript/Building_blocks/conditionals#Instruction_switch">instructions switch </a>: lorsqu'un argument est rencontré dans une instruction switch qui correspond à l'expression d'entrée, l'instruction break quitte immédiatement l'instruction switch et passe au code après elle.</p> +Si vous voulez quitter une boucle avant que toutes les itérations aient été terminées, vous pouvez utiliser l'instruction [break](/fr/docs/Web/JavaScript/Reference/Instructions/break). Nous l'avons déjà rencontré dans l'article précédent lorsque nous examinions les [instructions switch ](/fr/Apprendre/JavaScript/Building_blocks/conditionals#Instruction_switch): lorsqu'un argument est rencontré dans une instruction switch qui correspond à l'expression d'entrée, l'instruction break quitte immédiatement l'instruction switch et passe au code après elle. -<p>C'est la même chose avec les boucles – un <code>break</code> quittera immédiatement la boucle et fera passer le navigateur sur n'importe quel code qui le suit.</p> +C'est la même chose avec les boucles – un `break` quittera immédiatement la boucle et fera passer le navigateur sur n'importe quel code qui le suit. -<p>Supposons que nous voulions effectuer une recherche parmi une liste de contacts et de numéros de téléphone et que nous ne renvoyions que le nombre que nous voulions trouver. Tout d'abord, du HTML simple - un texte {{htmlelement ("input")}} nous permettant d'entrer un nom à rechercher, un élément {{htmlelement ("button")}} pour soumettre une recherche, et un {{htmlelement ("p")}} élément pour afficher les résultats dans :</p> +Supposons que nous voulions effectuer une recherche parmi une liste de contacts et de numéros de téléphone et que nous ne renvoyions que le nombre que nous voulions trouver. Tout d'abord, du HTML simple - un texte {{htmlelement ("input")}} nous permettant d'entrer un nom à rechercher, un élément {{htmlelement ("button")}} pour soumettre une recherche, et un {{htmlelement ("p")}} élément pour afficher les résultats dans : -<pre class="brush: html"><label for="search">Search by contact name: </label> -<input id="search" type="text"> -<button>Search</button> +```html +<label for="search">Search by contact name: </label> +<input id="search" type="text"> +<button>Search</button> -<p></p></pre> +<p></p> +``` -<p>Maintenant sur le JavaScript :</p> +Maintenant sur le JavaScript : -<pre class="brush: js">const contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; +```js +const contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; const paragraphe = document.querySelector('p'); const input = document.querySelector('input'); const bouton = document.querySelector('button'); @@ -309,7 +306,7 @@ bouton.addEventListener('click', function() { let searchName = input.value; input.value = ''; input.focus(); - for (let i = 0; i < contacts.length; i++) { + for (let i = 0; i < contacts.length; i++) { let splitContact = contacts[i].split(':'); if (splitContact[0] === searchName) { paragraphe.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.'; @@ -318,25 +315,27 @@ bouton.addEventListener('click', function() { paragraphe.textContent = 'Contact not found.'; } } -});</pre> +}); +``` -<h3>Résultat</h3> +### Résultat -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Simple contact search example</title> - </head> - <body> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Simple contact search example</title> + </head> + <body> - <label for="search">Search by contact name: </label> - <input id="search" type="text"> - <button>Search</button> + <label for="search">Search by contact name: </label> + <input id="search" type="text"> + <button>Search</button> - <p></p> + <p></p> - <script> + <script> const contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; const paragraphe = document.querySelector('p'); const input = document.querySelector('input'); @@ -346,7 +345,7 @@ bouton.addEventListener('click', function() { let searchName = input.value; input.value = ''; input.focus(); - for (let i = 0; i < contacts.length; i++) { + for (let i = 0; i < contacts.length; i++) { let splitContact = contacts[i].split(':'); if (splitContact[0] === searchName) { paragraphe.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.'; @@ -356,64 +355,64 @@ bouton.addEventListener('click', function() { } } }); - </script> - - </body> -</html></pre> -<p>{{ EmbedLiveSample('Résultat', '100%', 100) }}</p> - -<ol> - <li>Tout d'abord, nous avons quelques définitions de variables — nous avons un tableau d'informations de contact, avec chaque élément étant une chaîne contenant un nom et un numéro de téléphone séparés par deux points.</li> - <li>Ensuite, nous attachons un écouteur d'événement au bouton (<code>bouton</code>), de sorte que quand il est pressé, du code est exécuté pour effectuer la recherche et renvoyer les résultats.</li> - <li>Nous stockons la valeur saisie dans l'input dans une variable appelée <code>searchName</code>, , avant de vider l'input et le recentrer, prêt pour la recherche suivante.</li> - <li>Maintenant sur la partie intéressante, la boucle for : - <ol> - <li>Nous commençons le compteur à <code>0</code>, exécutons la boucle jusqu'à ce que le compteur ne soit plus inférieur à <code>contacts.length</code>, et incrémentons <code>i</code> par 1 après chaque itération de la boucle.</li> - <li>À l'intérieur de la boucle, nous divisons d'abord le contact actuel (<code>contacts[i]</code>) au caractère deux-points et stockons les deux valeurs résultantes dans un tableau appelé <code>splitContact</code>.</li> - <li>Nous utilisons ensuite une instruction conditionnelle pour tester si <code>splitContact[0] </code>(le nom du contact) est égal au <code>searchName</code> entré. Si c'est le cas, nous introduisons une <code>string / chaîne de caractère</code><strong> </strong>dans le paragraphe pour indiquer quel est le numéro du contact et utiliser <code>break</code> pour terminer la boucle.</li> - </ol> - </li> - <li>Si le nom du contact ne correspond pas à la recherche entrée, le texte du paragraphe est défini sur "Contact not found." et la boucle continue son itération.</li> -</ol> - -<div class="note"> -<p><strong>Note :</strong> Vous pouvez trouver cet exemple de code sur <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/contact-search.html">GitHub</a> (aussi <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/contact-search.html">voir en ligne</a>).</p> -</div> + </script> -<h2 id="Passer_des_itérations_avec_continue">Passer des itérations avec continue</h2> + </body> +</html> +``` -<p>L'instruction <a href="/fr/docs/Web/JavaScript/Reference/Instructions/continue">continue</a> fonctionne d'une manière similaire à <code>break</code>, mais au lieu de sortir complètement de la boucle, elle passe à l'itération suivante de la boucle. Regardons un autre exemple qui prend un nombre comme une entrée, et retourne seulement les nombres qui sont des carrés d'entiers (nombres entiers).</p> +{{ EmbedLiveSample('Résultat', '100%', 100) }} -<p>Le HTML est fondamentalement le même que le dernier exemple — une entrée de texte simple, et un paragraphe pour la sortie. Le JavaScript est la plupart du temps identique, même si la boucle elle-même est un peu différente :</p> +1. Tout d'abord, nous avons quelques définitions de variables — nous avons un tableau d'informations de contact, avec chaque élément étant une chaîne contenant un nom et un numéro de téléphone séparés par deux points. +2. Ensuite, nous attachons un écouteur d'événement au bouton (`bouton`), de sorte que quand il est pressé, du code est exécuté pour effectuer la recherche et renvoyer les résultats. +3. Nous stockons la valeur saisie dans l'input dans une variable appelée `searchName`, , avant de vider l'input et le recentrer, prêt pour la recherche suivante. +4. Maintenant sur la partie intéressante, la boucle for : -<pre class="brush: js">let num = input.value; + 1. Nous commençons le compteur à `0`, exécutons la boucle jusqu'à ce que le compteur ne soit plus inférieur à `contacts.length`, et incrémentons `i` par 1 après chaque itération de la boucle. + 2. À l'intérieur de la boucle, nous divisons d'abord le contact actuel (`contacts[i]`) au caractère deux-points et stockons les deux valeurs résultantes dans un tableau appelé `splitContact`. + 3. Nous utilisons ensuite une instruction conditionnelle pour tester si `splitContact[0] `(le nom du contact) est égal au `searchName` entré. Si c'est le cas, nous introduisons une `string / chaîne de caractère`\*\* \*\*dans le paragraphe pour indiquer quel est le numéro du contact et utiliser `break` pour terminer la boucle. -for (let i = 1; i <= num; i++) { +5. Si le nom du contact ne correspond pas à la recherche entrée, le texte du paragraphe est défini sur "Contact not found." et la boucle continue son itération. + +> **Note :** Vous pouvez trouver cet exemple de code sur [GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/contact-search.html) (aussi [voir en ligne](http://mdn.github.io/learning-area/javascript/building-blocks/loops/contact-search.html)). + +## Passer des itérations avec continue + +L'instruction [continue](/fr/docs/Web/JavaScript/Reference/Instructions/continue) fonctionne d'une manière similaire à `break`, mais au lieu de sortir complètement de la boucle, elle passe à l'itération suivante de la boucle. Regardons un autre exemple qui prend un nombre comme une entrée, et retourne seulement les nombres qui sont des carrés d'entiers (nombres entiers). + +Le HTML est fondamentalement le même que le dernier exemple — une entrée de texte simple, et un paragraphe pour la sortie. Le JavaScript est la plupart du temps identique, même si la boucle elle-même est un peu différente : + +```js +let num = input.value; + +for (let i = 1; i <= num; i++) { let sqRoot = Math.sqrt(i); if (Math.floor(sqRoot) !== sqRoot) { continue; } paragraphe.textContent += i + ' '; -}</pre> +} +``` -<p>Ici la sortie :</p> +Ici la sortie : -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Integer squares generator</title> - </head> - <body> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Integer squares generator</title> + </head> + <body> - <label for="number">Enter number: </label> - <input id="number" type="text"> - <button>Generate integer squares</button> + <label for="number">Enter number: </label> + <input id="number" type="text"> + <button>Generate integer squares</button> - <p>Output: </p> + <p>Output: </p> - <script> + <script> const paragraphe = document.querySelector('p'); const input = document.querySelector('input'); const bouton = document.querySelector('button'); @@ -423,7 +422,7 @@ for (let i = 1; i <= num; i++) { let num = input.value; input.value = ''; input.focus(); - for (let i = 1; i <= num; i++) { + for (let i = 1; i <= num; i++) { let sqRoot = Math.sqrt(i); if (Math.floor(sqRoot) !== sqRoot) { continue; @@ -432,46 +431,44 @@ for (let i = 1; i <= num; i++) { paragraphe.textContent += i + ' '; } }); - </script> + </script> - </body> -</html></pre> + </body> +</html> +``` -<p>{{ EmbedLiveSample('Passer_des_itérations_avec_continue', '100%', 100) }}</p> +{{ EmbedLiveSample('Passer_des_itérations_avec_continue', '100%', 100) }} -<ol> - <li>Dans ce cas, l'entrée doit être un nombre (<code>num</code>). La boucle <code>for</code> est dotée d'un compteur commençant à 1 (car nous ne sommes pas intéressés par 0 dans ce cas), une condition de sortie indiquant que la boucle s'arrêtera lorsque le compteur deviendra plus grand que l'entrée <code>num</code>, et un itérateur ajoutera 1 au compteur à chaque fois.</li> - <li>À l'intérieur de la boucle, nous trouvons la racine carrée de chaque nombre en utilisant <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt">Math.sqrt(i), </a><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/sqrt">, </a>puis vérifions si la racine carrée est un entier en vérifiant si elle est identique à elle-même lorsqu'elle a été arrondie à l'entier le plus proche (ceci est ce que <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/floor">Math.floor() </a>fait au nombre auquel il est passé).</li> - <li>Si la racine carrée et la racine carrée arrondie ne sont pas égales les unes aux autres (<code>! ==</code>), cela signifie que la racine carrée n'est pas un entier, donc cela ne nous intéresse pas. Dans un tel cas, nous utilisons l'instruction <code>continue</code> pour passer à l'itération de la boucle suivante sans enregistrer le numéro n'importe où.</li> - <li>Si la racine carrée est un entier, nous passons complètement le bloc if pour que l'instruction <code>continue</code> ne soit pas exécutée; à la place, nous concaténons la valeur <code>i </code>actuelle plus un espace sur la fin du contenu du paragraphe.</li> -</ol> +1. Dans ce cas, l'entrée doit être un nombre (`num`). La boucle `for` est dotée d'un compteur commençant à 1 (car nous ne sommes pas intéressés par 0 dans ce cas), une condition de sortie indiquant que la boucle s'arrêtera lorsque le compteur deviendra plus grand que l'entrée `num`, et un itérateur ajoutera 1 au compteur à chaque fois. +2. À l'intérieur de la boucle, nous trouvons la racine carrée de chaque nombre en utilisant [Math.sqrt(i), ](/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt)[, ](/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/sqrt)puis vérifions si la racine carrée est un entier en vérifiant si elle est identique à elle-même lorsqu'elle a été arrondie à l'entier le plus proche (ceci est ce que [Math.floor() ](/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/floor)fait au nombre auquel il est passé). +3. Si la racine carrée et la racine carrée arrondie ne sont pas égales les unes aux autres (`! ==`), cela signifie que la racine carrée n'est pas un entier, donc cela ne nous intéresse pas. Dans un tel cas, nous utilisons l'instruction `continue` pour passer à l'itération de la boucle suivante sans enregistrer le numéro n'importe où. +4. Si la racine carrée est un entier, nous passons complètement le bloc if pour que l'instruction `continue` ne soit pas exécutée; à la place, nous concaténons la valeur `i `actuelle plus un espace sur la fin du contenu du paragraphe. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez trouver cet exemple de code sur <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/integer-squares.html">GitHub</a> (aussi <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/integer-squares.html">voir en ligne</a>).</p> -</div> +> **Note :** Vous pouvez trouver cet exemple de code sur [GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/integer-squares.html) (aussi [voir en ligne](http://mdn.github.io/learning-area/javascript/building-blocks/loops/integer-squares.html)). -<h2 id="while_et_do_..._while">while et do ... while</h2> +## while et do ... while -<p><code>for</code> n'est pas le seul type de boucle disponible en JavaScript. Il y en a beaucoup d'autres et, même si vous n'avez pas besoin de comprendre tout cela maintenant, il vaut mieux jeter un coup d'œil à la structure de quelques autres pour pouvoir reconnaître les mêmes caractéristiques au travail d'une manière légèrement différente.</p> +`for` n'est pas le seul type de boucle disponible en JavaScript. Il y en a beaucoup d'autres et, même si vous n'avez pas besoin de comprendre tout cela maintenant, il vaut mieux jeter un coup d'œil à la structure de quelques autres pour pouvoir reconnaître les mêmes caractéristiques au travail d'une manière légèrement différente. -<p>D'abord, regardons la boucle <a href="/fr/docs/Web/JavaScript/Reference/Instructions/while">while</a>. La syntaxe de cette boucle ressemble à ceci:</p> +D'abord, regardons la boucle [while](/fr/docs/Web/JavaScript/Reference/Instructions/while). La syntaxe de cette boucle ressemble à ceci: -<pre>initializer -while (exit-condition) { - // code to run + initializer + while (exit-condition) { + // code to run - final-expression -}</pre> + final-expression + } -<p>Cela fonctionne de manière très similaire à la boucle for, sauf que la variable de départ est définie avant la boucle, et l'expression finale est incluse dans la boucle après le code à exécuter — plutôt que ces deux éléments soient inclus dans les parenthèses. La condition de sortie est incluse dans les parenthèses, précédées du mot-clé <code>while </code>au lieu de <code>for</code>.</p> +Cela fonctionne de manière très similaire à la boucle for, sauf que la variable de départ est définie avant la boucle, et l'expression finale est incluse dans la boucle après le code à exécuter — plutôt que ces deux éléments soient inclus dans les parenthèses. La condition de sortie est incluse dans les parenthèses, précédées du mot-clé `while `au lieu de `for`. -<p>Les mêmes trois éléments sont toujours présents, et ils sont toujours définis dans le même ordre que dans la boucle for - cela est logique, car vous devez toujours définir un initialiseur avant de pouvoir vérifier s'il a atteint la condition de sortie ; la condition finale est ensuite exécutée après l'exécution du code à l'intérieur de la boucle (une itération a été effectuée), ce qui ne se produira que si la condition de sortie n'a pas encore été atteinte.</p> +Les mêmes trois éléments sont toujours présents, et ils sont toujours définis dans le même ordre que dans la boucle for - cela est logique, car vous devez toujours définir un initialiseur avant de pouvoir vérifier s'il a atteint la condition de sortie ; la condition finale est ensuite exécutée après l'exécution du code à l'intérieur de la boucle (une itération a été effectuée), ce qui ne se produira que si la condition de sortie n'a pas encore été atteinte. -<p>Jetons un coup d'oeil à notre exemple de liste de chats, mais réécrit pour utiliser une boucle while:</p> +Jetons un coup d'oeil à notre exemple de liste de chats, mais réécrit pour utiliser une boucle while: -<pre class="brush: js">let i = 0; +```js +let i = 0; -while (i < cats.length) { +while (i < cats.length) { if (i === cats.length - 1) { info += 'and ' + cats[i] + '.'; } else { @@ -479,28 +476,28 @@ while (i < cats.length) { } i++; -}</pre> +} +``` -<div class="note"> -<p><strong>Note :</strong> Cela fonctionne toujours comme prévu regardez le ici <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/while.html">GitHub</a> (<a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/while.html">Voir en ligne</a> le code complet).</p> -</div> +> **Note :** Cela fonctionne toujours comme prévu regardez le ici [GitHub](http://mdn.github.io/learning-area/javascript/building-blocks/loops/while.html) ([Voir en ligne](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/while.html) le code complet). -<p>La boucle<a href="/fr/docs/Web/JavaScript/Reference/Instructions/do...while"> do...while</a> est très similaire, mais dénote une variation par rapport à la structure de la boucle while :</p> +La boucle[ do...while](/fr/docs/Web/JavaScript/Reference/Instructions/do...while) est très similaire, mais dénote une variation par rapport à la structure de la boucle while : -<pre>initializer -do { - // code to run + initializer + do { + // code to run - final-expression -} while (exit-condition)</pre> + final-expression + } while (exit-condition) -<p>Dans ce cas, l'initialiseur vient en premier, avant que la boucle ne commence. Le mot-clé <code>do </code>précède directement les accolades contenant le code à exécuter et l'expression finale.</p> +Dans ce cas, l'initialiseur vient en premier, avant que la boucle ne commence. Le mot-clé `do `précède directement les accolades contenant le code à exécuter et l'expression finale. -<p>Le différentiateur ici est que la condition de sortie vient après tout, enveloppée entre parenthèses et précédée d'un mot-clé <code>while</code>. Dans une boucle <code>do ... while</code>, le code à l'intérieur des accolades est toujours exécuté une fois avant que la vérification ne soit effectuée pour voir si elle doit être exécutée à nouveau (dans while et for, la vérification arrive en premier, donc le code pourrait ne jamais être exécuté ).</p> +Le différentiateur ici est que la condition de sortie vient après tout, enveloppée entre parenthèses et précédée d'un mot-clé `while`. Dans une boucle `do ... while`, le code à l'intérieur des accolades est toujours exécuté une fois avant que la vérification ne soit effectuée pour voir si elle doit être exécutée à nouveau (dans while et for, la vérification arrive en premier, donc le code pourrait ne jamais être exécuté ). -<p>Réécrivons notre exemple de listing de chat pour utiliser une boucle <code>do ... while </code>:</p> +Réécrivons notre exemple de listing de chat pour utiliser une boucle `do ... while `: -<pre class="brush: js">let i = 0; +```js +let i = 0; do { if (i === cats.length - 1) { @@ -510,48 +507,42 @@ do { } i++; -} while (i < cats.length);</pre> +} while (i < cats.length); +``` -<div class="note"> -<p><strong>Note :</strong> Encore, cela fonctionne toujours comme prévu — regardez le ici <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/do-while.html">GitHub</a> (<a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/do-while.html">Voir en ligne</a> le code complet).</p> -</div> +> **Note :** Encore, cela fonctionne toujours comme prévu — regardez le ici [GitHub](http://mdn.github.io/learning-area/javascript/building-blocks/loops/do-while.html) ([Voir en ligne](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/do-while.html) le code complet). -<div class="warning"> -<p><strong>Attention :</strong> Avec while et do ... while – comme avec toutes les boucles – vous devez vous assurer que l'initialiseur est itéré pour qu'il atteigne finalement la condition de sortie. Si ce n'est pas le cas, la boucle continuera indéfiniment, et soit le navigateur l'arrêtera, soit il se bloquera. C'est ce qu'on appelle une <strong>boucle infinie.</strong></p> -</div> +> **Attention :** Avec while et do ... while – comme avec toutes les boucles – vous devez vous assurer que l'initialiseur est itéré pour qu'il atteigne finalement la condition de sortie. Si ce n'est pas le cas, la boucle continuera indéfiniment, et soit le navigateur l'arrêtera, soit il se bloquera. C'est ce qu'on appelle une **boucle infinie.** + +## Apprentissage actif : Lancer le compte à rebours + +Dans cet exercice, nous vous proposons d'écrire un compte à rebours de lancement dans la boîte de sortie, de 10 jusqu'à "Blast Off." Plus précisément, il s'agit de : + +- Créer une boucle de 10 jusqu'à 0. Nous vous avons fourni un initialiseur — `let i = 10;` +- Pour chaque itération, créer un nouveau paragraphe à ajouter dans la balise de sortie `<div>` que nous avons selectionnée en utilisant : `const output = document.querySelector('.output');` En commentaire, nous vous avons fourni trois lignes de code qui doivent être utilisées quelque part à l'intérieur de la boucle : + + - `const paragraphe = document.createElement('p');` — crée un nouveau paragraphe. + - `output.appendChild(para);` — ajoute le paragraphe à la sortie `<div>`. + - `paragraphe.textContent =` — Rend le texte à l'intérieur du paragraphe identique à ce que vous avez entré du côté droit du signe égal. + +- Chaque nombre de l'itération nécessite un texte différent dans le paragraphe de cette itération (vous aurez besoin d'une expression conditionnelle et plusieurs lignes du type : `paragraphe.textContent = )` + + - Si le nombre est 10, écrire "Countdown 10" dans le paragraphe. + - Si le nombre est 0, écrire "Blast off!" dans le paragraphe. + - Pour tout autre nombre, écrire simplement le nombre dans le paragraphe. + +- Noubliez pas d'inclure un itérateur ! Quoi qu'il en soit, dans cet exemple nous comptons à rebours après chaque itération, pas de manière croissante, alors vous ne voudrez pas `i++` — Comment allez vous créer l'itération décroissante ? -<h2 id="Apprentissage_actif_Lancer_le_compte_à_rebours">Apprentissage actif : Lancer le compte à rebours</h2> - -<p>Dans cet exercice, nous vous proposons d'écrire un compte à rebours de lancement dans la boîte de sortie, de 10 jusqu'à "Blast Off." Plus précisément, il s'agit de :</p> - -<ul> - <li>Créer une boucle de 10 jusqu'à 0. Nous vous avons fourni un initialiseur — <code>let i = 10; </code></li> - <li>Pour chaque itération, créer un nouveau paragraphe à ajouter dans la balise de sortie <code><div></code> que nous avons selectionnée en utilisant : <code>const output = document.querySelector('.output');</code> En commentaire, nous vous avons fourni trois lignes de code qui doivent être utilisées quelque part à l'intérieur de la boucle : - <ul> - <li><code>const paragraphe = document.createElement('p');</code> — crée un nouveau paragraphe.</li> - <li><code>output.appendChild(para);</code> — ajoute le paragraphe à la sortie <code><div></code>.</li> - <li><code>paragraphe.textContent =</code> — Rend le texte à l'intérieur du paragraphe identique à ce que vous avez entré du côté droit du signe égal.</li> - </ul> - </li> - <li>Chaque nombre de l'itération nécessite un texte différent dans le paragraphe de cette itération (vous aurez besoin d'une expression conditionnelle et plusieurs lignes du type : <code>paragraphe.textContent = )</code> - <ul> - <li>Si le nombre est 10, écrire "Countdown 10" dans le paragraphe.</li> - <li>Si le nombre est 0, écrire "Blast off!" dans le paragraphe.</li> - <li>Pour tout autre nombre, écrire simplement le nombre dans le paragraphe.</li> - </ul> - </li> - <li>Noubliez pas d'inclure un itérateur ! Quoi qu'il en soit, dans cet exemple nous comptons à rebours après chaque itération, pas de manière croissante, alors vous ne voudrez pas <code>i++</code> — Comment allez vous créer l'itération décroissante ?</li> -</ul> - -<p>Si vous faites une erreur, vous pourrez toujours réinitialiser l'exemple avec le bouton "Reset". Si vous êtes vraiment bloqué, appuyez sur le bouton "Show solution" pour voir une solution.</p> - -<pre class="brush: html hidden"><h2>Sortie en direct</h2> -<div class="output" style="height: 410px;overflow: auto;"> - -</div> -<h2>Code modifiable</h2> -<p class="a11y-label">Appuyer sur Échap pour décibler le code</p> -<textarea id="code" class="playable-code" style="height: 300px;"> +Si vous faites une erreur, vous pourrez toujours réinitialiser l'exemple avec le bouton "Reset". Si vous êtes vraiment bloqué, appuyez sur le bouton "Show solution" pour voir une solution. + +```html hidden +<h2>Sortie en direct</h2> +<div class="output" style="height: 410px;overflow: auto;"> + +</div> +<h2>Code modifiable</h2> +<p class="a11y-label">Appuyer sur Échap pour décibler le code</p> +<textarea id="code" class="playable-code" style="height: 300px;"> const output = document.querySelector('.output'); output.innerHTML = ''; @@ -560,15 +551,16 @@ output.innerHTML = ''; // const paragraphe = document.createElement('p'); // paragraphe.textContent = ; // output.appendChild(para); -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: js hidden">const textarea = document.getElementById('code'); +```js hidden +const textarea = document.getElementById('code'); const reset = document.getElementById('reset'); const solution = document.getElementById('solution'); const code = textarea.value; @@ -596,7 +588,7 @@ solution.addEventListener('click', function() { updateCode(); }); -let jsSolution = 'let output = document.querySelector(\'.output\');\noutput.innerHTML = \'\';\n\nlet i = 10;\n\nwhile(i >= 0) {\n let para = document.createElement(\'p\');\n if(i === 10) {\n para.textContent = \'Countdown \' + i;\n } else if(i === 0) {\n para.textContent = \'Blast off!\';\n } else {\n para.textContent = i;\n }\n\n output.appendChild(para);\n\n i--;\n}'; +let jsSolution = 'let output = document.querySelector(\'.output\');\noutput.innerHTML = \'\';\n\nlet i = 10;\n\nwhile(i >= 0) {\n let para = document.createElement(\'p\');\n if(i === 10) {\n para.textContent = \'Countdown \' + i;\n } else if(i === 0) {\n para.textContent = \'Blast off!\';\n } else {\n para.textContent = i;\n }\n\n output.appendChild(para);\n\n i--;\n}'; let solutionEntry = jsSolution; textarea.addEventListener('input', updateCode); @@ -643,47 +635,42 @@ textarea.onkeyup = function(){ updateCode(); }; -</pre> +``` -<p>{{ EmbedLiveSample('Apprentissage_actif_Lancer_le_compte_à_rebours', '100%', 780) }}</p> +{{ EmbedLiveSample('Apprentissage_actif_Lancer_le_compte_à_rebours', '100%', 780) }} -<h2 id="Apprentissage_actif_remplir_une_liste_d'invités.">Apprentissage actif : remplir une liste d'invités.</h2> +## Apprentissage actif : remplir une liste d'invités. -<p>Dans cet exercice, nous vous proposons de prendre une liste d'invités stockée dans un tableau et de la mettre sur une liste d'invités. Mais cela n'est pas si simple — nous ne voulons pas laisser entrer Phil et Lola parce que ce sont des goinfres et qu'ils sont mal élevés, et ils mangent toujours toute la nourriture ! Nous avons deux listes, une pour les invités admis, une pour ceux que l'on refuse.</p> +Dans cet exercice, nous vous proposons de prendre une liste d'invités stockée dans un tableau et de la mettre sur une liste d'invités. Mais cela n'est pas si simple — nous ne voulons pas laisser entrer Phil et Lola parce que ce sont des goinfres et qu'ils sont mal élevés, et ils mangent toujours toute la nourriture ! Nous avons deux listes, une pour les invités admis, une pour ceux que l'on refuse. -<p>Plus précisément, nous attendons de vous :</p> +Plus précisément, nous attendons de vous : -<ul> - <li>Que vous écriviez une boucle qui créé une itération de 0 jusqu'à la fin du tableau <code>people</code>. Vous aurez besoin de commencer avec un initialiseur type <code>let i = 0;</code> , mais quelle sera la condition de sortie</li> - <li>Au cours de chaque itération, vérifiez si l'élément actuel du tableau est "Phil" ou "Lola" en utilisant une déclaration conditionnelle. - <ul> - <li>Si tel est le cas, concaténez l'élément à la fin du paragraphe <code>refused</code> du <code>textContent</code>, suivi d'une virgule et d'un espace.</li> - <li>Dans le cas contraire, concaténez l'élément à la fin du paragraphe <code>admitted</code> du <code>textContent</code> suivi d'une virgule et d'un espace.</li> - </ul> - </li> -</ul> +- Que vous écriviez une boucle qui créé une itération de 0 jusqu'à la fin du tableau `people`. Vous aurez besoin de commencer avec un initialiseur type `let i = 0;` , mais quelle sera la condition de sortie +- Au cours de chaque itération, vérifiez si l'élément actuel du tableau est "Phil" ou "Lola" en utilisant une déclaration conditionnelle. -<p>Nous vous avons déjà fourni les éléments suivants :</p> + - Si tel est le cas, concaténez l'élément à la fin du paragraphe `refused` du `textContent`, suivi d'une virgule et d'un espace. + - Dans le cas contraire, concaténez l'élément à la fin du paragraphe `admitted` du `textContent` suivi d'une virgule et d'un espace. -<ul> - <li><code>let i = 0;</code> — Votre initialiseur.</li> - <li><code>refused.textContent +=</code> — le début de la ligne qui va concaténer un élément à la fin du <code>refused.textContent</code>.</li> - <li><code>admitted.textContent +=</code> — le début de la ligne qui va concaténer un élément à la fin du <code>admitted.textContent</code>.</li> -</ul> +Nous vous avons déjà fourni les éléments suivants : -<p>Question bonus — après avoir accompli les tâches ci-dessus, il vous restera deux listes de noms séparées par des virgules, mais elles seront mal présentées— il y aura des virgules à la fin de chacune d'elles. Pouvez-vous faire en sorte d'écrire des lignes de code qui coupent les dernières virgules dans chacune d'elles, et ajoute un arrêt total à la fin ? Jetez un oeil à l'article <a href="/fr/docs/Learn/JavaScript/First_steps/methode_chaine_utile">Méthodes utiles pour les chaînes de caractères </a>pour obtenir de l'aide.</p> +- `let i = 0;` — Votre initialiseur. +- `refused.textContent +=` — le début de la ligne qui va concaténer un élément à la fin du `refused.textContent`. +- `admitted.textContent +=` — le début de la ligne qui va concaténer un élément à la fin du `admitted.textContent`. -<p>Si vous faites une erreur, vous pourrez toujours ré-initialiser l'exemple avec le bouton "Reset". Si vous êtes vraiment bloqué, appuyez sur le bouton "Show solution" pour voir une solution.</p> +Question bonus — après avoir accompli les tâches ci-dessus, il vous restera deux listes de noms séparées par des virgules, mais elles seront mal présentées— il y aura des virgules à la fin de chacune d'elles. Pouvez-vous faire en sorte d'écrire des lignes de code qui coupent les dernières virgules dans chacune d'elles, et ajoute un arrêt total à la fin ? Jetez un oeil à l'article [Méthodes utiles pour les chaînes de caractères ](/fr/docs/Learn/JavaScript/First_steps/methode_chaine_utile)pour obtenir de l'aide. -<pre class="brush: html hidden"><h2>Live output</h2> -<div class="output" style="height: 100px;overflow: auto;"> - <p class="admitted">Admettre : </p> - <p class="refused">Refuser : </p> -</div> +Si vous faites une erreur, vous pourrez toujours ré-initialiser l'exemple avec le bouton "Reset". Si vous êtes vraiment bloqué, appuyez sur le bouton "Show solution" pour voir une solution. -<h2>Editable code</h2> -<p class="a11y-label">Appuyer sur Échap pour décibler le code</p> -<textarea id="code" class="playable-code" style="height: 400px;width: 95%"> +```html hidden +<h2>Live output</h2> +<div class="output" style="height: 100px;overflow: auto;"> + <p class="admitted">Admettre : </p> + <p class="refused">Refuser : </p> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Appuyer sur Échap pour décibler le code</p> +<textarea id="code" class="playable-code" style="height: 400px;width: 95%"> const people = ['Chris', 'Anne', 'Colin', 'Terri', 'Phil', 'Lola', 'Sam', 'Kay', 'Bruce']; const admitted = document.querySelector('.admitted'); @@ -696,14 +683,16 @@ refused.textContent = 'Refuse: ' // refused.textContent += ; // admitted.textContent += ; -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div></pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: css hidden">html { +```css hidden +html { font-family: sans-serif; } @@ -721,9 +710,11 @@ h2 { body { margin: 10px; background: #f5f9fa; -}</pre> +} +``` -<pre class="brush: js hidden">const textarea = document.getElementById('code'); +```js hidden +const textarea = document.getElementById('code'); const reset = document.getElementById('reset'); const solution = document.getElementById('solution'); let code = textarea.value; @@ -752,7 +743,7 @@ solution.addEventListener('click', function() { updateCode(); }); -let jsSolution = 'const people = [\'Chris\', \'Anne\', \'Colin\', \'Terri\', \'Phil\', \'Lola\', \'Sam\', \'Kay\', \'Bruce\'];\n\nconst admitted = document.querySelector(\'.admitted\');\nconst refused = document.querySelector(\'.refused\');\n\nadmitted.textContent = \'Admit: \';\nrefused.textContent = \'Refuse: \'\nlet i = 0;\n\ndo {\n if(people[i] === \'Phil\' || people[i] === \'Lola\') {\n refused.textContent += people[i] + \', \';\n } else {\n admitted.textContent += people[i] + \', \';\n }\n i++;\n} while(i < people.length);\n\nrefused.textContent = refused.textContent.slice(0,refused.textContent.length-2) + \'.\';\nadmitted.textContent = admitted.textContent.slice(0,admitted.textContent.length-2) + \'.\';'; +let jsSolution = 'const people = [\'Chris\', \'Anne\', \'Colin\', \'Terri\', \'Phil\', \'Lola\', \'Sam\', \'Kay\', \'Bruce\'];\n\nconst admitted = document.querySelector(\'.admitted\');\nconst refused = document.querySelector(\'.refused\');\n\nadmitted.textContent = \'Admit: \';\nrefused.textContent = \'Refuse: \'\nlet i = 0;\n\ndo {\n if(people[i] === \'Phil\' || people[i] === \'Lola\') {\n refused.textContent += people[i] + \', \';\n } else {\n admitted.textContent += people[i] + \', \';\n }\n i++;\n} while(i < people.length);\n\nrefused.textContent = refused.textContent.slice(0,refused.textContent.length-2) + \'.\';\nadmitted.textContent = admitted.textContent.slice(0,admitted.textContent.length-2) + \'.\';'; let solutionEntry = jsSolution; textarea.addEventListener('input', updateCode); @@ -798,59 +789,55 @@ textarea.onkeyup = function(){ } updateCode(); -};</pre> +}; +``` -<p>{{ EmbedLiveSample("Apprentissage_actif_remplir_une_liste_d'invités.", '100%', 580) }}</p> +{{ EmbedLiveSample("Apprentissage_actif_remplir_une_liste_d'invités.", '100%', 580) }} -<h2 id="Quel_type_de_boucle_utiliser">Quel type de boucle utiliser ?</h2> +## Quel type de boucle utiliser ? -<p>Pour des usages basiques les boucles <code>for</code>, <code>while</code>, et <code>do...while</code> sont largement interchangeables. Elles résolvent toutes le même problème et celle que vous utiliserez dépendra de vos préférences personnelles — celle que vous trouverez le plus facile à mémoriser ou la plus intuitive. Jetons-y un coup d'oeil à nouveau.</p> +Pour des usages basiques les boucles `for`, `while`, et `do...while` sont largement interchangeables. Elles résolvent toutes le même problème et celle que vous utiliserez dépendra de vos préférences personnelles — celle que vous trouverez le plus facile à mémoriser ou la plus intuitive. Jetons-y un coup d'oeil à nouveau. -<p>Premièrement <code>for</code>:</p> +Premièrement `for`: -<pre>for (initialisation; condition de sortie; expression finale) { - // code à exécuter -}</pre> + for (initialisation; condition de sortie; expression finale) { + // code à exécuter + } -<p><code>while</code>:</p> +`while`: -<pre>initialisation -while (condition de sortie) { - // code à exécuter + initialisation + while (condition de sortie) { + // code à exécuter - expression finale -}</pre> + expression finale + } -<p>et enfin <code>do...while</code>:</p> +et enfin `do...while`: -<pre>initialisation -do { - // code à exécuter + initialisation + do { + // code à exécuter - expression finale -} while (condition de sortie)</pre> + expression finale + } while (condition de sortie) -<p>Nous recommandons <code>for</code>, au moins pour commencer, car elle est probablement la plus facile pour tout se remémorer — l'initialisation, la condition de sortie, l'expression finale, le tout soigneusement placé entre des parenthèses. De cette façon, il est facile de voir où elles se trouvent et de vérifier qu'on ne les a pas oubliées.</p> +Nous recommandons `for`, au moins pour commencer, car elle est probablement la plus facile pour tout se remémorer — l'initialisation, la condition de sortie, l'expression finale, le tout soigneusement placé entre des parenthèses. De cette façon, il est facile de voir où elles se trouvent et de vérifier qu'on ne les a pas oubliées. -<div class="note"> -<p><strong>Note :</strong> Il y a d'autres types de boucles et de particularités, qui sont très utiles pour des situations spéciales et qui ne sont pas décrites dans cet article. Si vous voulez aller plus loin dans l'apprentissage des boucles, lisez le guide <a href="/fr/docs/Web/JavaScript/Guide/Boucles_et_it%C3%A9ration">Boucles et itérations</a>.</p> -</div> +> **Note :** Il y a d'autres types de boucles et de particularités, qui sont très utiles pour des situations spéciales et qui ne sont pas décrites dans cet article. Si vous voulez aller plus loin dans l'apprentissage des boucles, lisez le guide [Boucles et itérations](/fr/docs/Web/JavaScript/Guide/Boucles_et_it%C3%A9ration). -<h2 id="Conclusion">Conclusion</h2> +## Conclusion -<p>Cet article vous a révélé les concepts basiques et les différentes options disponibles pour créer des boucles en JavaScript. Vous devriez à présent être en mesure de comprendre en quoi les boucles constituent un bon mécanisme lorsqu'il s'agit de répéter une action dans le code, et vous devez être impatient de les utiliser dans vos propres exemples !</p> +Cet article vous a révélé les concepts basiques et les différentes options disponibles pour créer des boucles en JavaScript. Vous devriez à présent être en mesure de comprendre en quoi les boucles constituent un bon mécanisme lorsqu'il s'agit de répéter une action dans le code, et vous devez être impatient de les utiliser dans vos propres exemples ! -<p>S'il y a quelque chose que vous n'avez pas compris, n'hésitez pas à relire l'article ou à <a href="/fr/Apprendre#Nous_contacter">nous contacter </a>pour demander de l'aide.</p> +S'il y a quelque chose que vous n'avez pas compris, n'hésitez pas à relire l'article ou à [nous contacter ](/fr/Apprendre#Nous_contacter)pour demander de l'aide. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/JavaScript/Guide/Boucles_et_it%C3%A9ration">Boucles et itération</a></li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for">L'instruction for</a></li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Instructions/while">while</a> et <a href="/fr/docs/Web/JavaScript/Reference/Instructions/do...while">do...while</a></li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Instructions/break">break</a> et <a href="/fr/docs/Web/JavaScript/Reference/Instructions/continue">continue</a></li> - <li><p><a href="https://www.impressivewebs.com/javascript-for-loop/">What’s the Best Way to Write a JavaScript For Loop?</a> — quelques bonnes pratiques en matière de boucles</p> - </li> -</ul> +- [Boucles et itération](/fr/docs/Web/JavaScript/Guide/Boucles_et_it%C3%A9ration) +- [L'instruction for](/fr/docs/Web/JavaScript/Reference/Instructions/for) +- [while](/fr/docs/Web/JavaScript/Reference/Instructions/while) et [do...while](/fr/docs/Web/JavaScript/Reference/Instructions/do...while) +- [break](/fr/docs/Web/JavaScript/Reference/Instructions/break) et [continue](/fr/docs/Web/JavaScript/Reference/Instructions/continue) +- [What’s the Best Way to Write a JavaScript For Loop?](https://www.impressivewebs.com/javascript-for-loop/) — quelques bonnes pratiques en matière de boucles -<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}} diff --git a/files/fr/learn/javascript/building_blocks/return_values/index.md b/files/fr/learn/javascript/building_blocks/return_values/index.md index 2d2b9f628e..c93c4c94a6 100644 --- a/files/fr/learn/javascript/building_blocks/return_values/index.md +++ b/files/fr/learn/javascript/building_blocks/return_values/index.md @@ -14,170 +14,184 @@ tags: translation_of: Learn/JavaScript/Building_blocks/Return_values original_slug: Apprendre/JavaScript/Building_blocks/Return_values --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</div> - -<p>Il y a un concept essentiel que nous devons aborder dans ce cours, pour être complet sur les fonctions: les valeurs de retour. Certaines fonctions ne retournent pas de valeur significative après avoir été exécutées, mais d'autres oui, il est important de comprendre ces valeurs, comment les utiliser dans votre code et comment faire pour que vos propres fonctions retournent des valeurs utiles. Nous aborderons tout cela dans cet article.</p> +Il y a un concept essentiel que nous devons aborder dans ce cours, pour être complet sur les fonctions: les valeurs de retour. Certaines fonctions ne retournent pas de valeur significative après avoir été exécutées, mais d'autres oui, il est important de comprendre ces valeurs, comment les utiliser dans votre code et comment faire pour que vos propres fonctions retournent des valeurs utiles. Nous aborderons tout cela dans cet article. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis:</th> - <td> - <p>Base en langage informatique, une compréhension basic de HTML et CSS, <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions">Fonctions — blocks de code réutilisable</a>.</p> - </td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Comprendre les valeurs de retour, et comment les utiliser.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td> + <p> + Base en langage informatique, une compréhension basic de HTML et CSS, + <a href="/fr/docs/Learn/JavaScript/First_steps" + >Premiers pas en JavaScript</a + >, + <a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions" + >Fonctions — blocks de code réutilisable</a + >. + </p> + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td>Comprendre les valeurs de retour, et comment les utiliser.</td> + </tr> + </tbody> </table> -<h2 id="Qu'est-ce_que_les_valeurs_de_retour">Qu'est-ce que les valeurs de retour?</h2> +## Qu'est-ce que les valeurs de retour? -<p><strong>Les valeurs de retour </strong>sont, comme leur nom l'indique, les valeurs retournées par une fonction après son exécution. Vous en avez déjà rencontré plusieurs fois sans y avoir pensé explicitement. Revenons à notre code:</p> +**Les valeurs de retour** sont, comme leur nom l'indique, les valeurs retournées par une fonction après son exécution. Vous en avez déjà rencontré plusieurs fois sans y avoir pensé explicitement. Revenons à notre code: -<pre class="brush: js">var myText = 'I am a string'; +```js +var myText = 'I am a string'; var newString = myText.replace('string', 'sausage'); console.log(newString); // the replace() string function takes a string, // replaces one substring with another, and returns -// a new string with the replacement made</pre> +// a new string with the replacement made +``` -<p>Nous avons vu ce bloc de code dans notre premier article sur les fonctions. Nous appelons la fonction <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a> sur la chaîne de caractères <code>myText</code> , et lui passons deux paramètres: la chaîne à trouver ('string'), et la chaîne de remplacement ('sausage'). Lorsque cette fonction a fini de s'exécuter, elle retourne une valeur qui est une chaîne avec le remplacement effectué. Dans le code ci-dessus, nous sauvegardons cette valeur avec la variable newString.</p> +Nous avons vu ce bloc de code dans notre premier article sur les fonctions. Nous appelons la fonction [replace()](/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace) sur la chaîne de caractères `myText` , et lui passons deux paramètres: la chaîne à trouver ('string'), et la chaîne de remplacement ('sausage'). Lorsque cette fonction a fini de s'exécuter, elle retourne une valeur qui est une chaîne avec le remplacement effectué. Dans le code ci-dessus, nous sauvegardons cette valeur avec la variable newString. -<p>Si vous regardez la page de référence MDN sur le remplacement de fonction, vous verrez une section intitulée <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Return_value">Valeur retournée</a>. Il est utile de savoir et de comprendre quelles sont les valeurs retournées par les fonctions, nous avons donc essayé d'inclure cette information partout où cela était possible.</p> +Si vous regardez la page de référence MDN sur le remplacement de fonction, vous verrez une section intitulée [Valeur retournée](/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Return_value). Il est utile de savoir et de comprendre quelles sont les valeurs retournées par les fonctions, nous avons donc essayé d'inclure cette information partout où cela était possible. -<p>Certaines fonctions ne retournent pas de valeur comme telle (dans nos pages de référence, la valeur de retour est définie comme <code>void</code> ou <code>undefined</code> dans de tels cas). Par exemple, dans la fonction <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html#L50">displayMessage() </a> construite dans l'article précédent, aucune valeur spécifique n'est retournée comme résultat de la fonction appelée. Il y a seulement une boîte qui apparaît, c'est tout !</p> +Certaines fonctions ne retournent pas de valeur comme telle (dans nos pages de référence, la valeur de retour est définie comme `void` ou `undefined` dans de tels cas). Par exemple, dans la fonction [displayMessage() ](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html#L50) construite dans l'article précédent, aucune valeur spécifique n'est retournée comme résultat de la fonction appelée. Il y a seulement une boîte qui apparaît, c'est tout ! -<p>Généralement, une valeur de retour est utilisée lorsque la fonction est une étape intermédiaire dans un programme. Ces valeurs intermédiaires doivent être d'abord évaluées par une fonction, le résultat renvoyé pourra être ensuite utilisé dans l'étape suivante du programme.</p> +Généralement, une valeur de retour est utilisée lorsque la fonction est une étape intermédiaire dans un programme. Ces valeurs intermédiaires doivent être d'abord évaluées par une fonction, le résultat renvoyé pourra être ensuite utilisé dans l'étape suivante du programme. -<h3 id="Utiliser_des_valeurs_de_retour_dans_vos_fonctions">Utiliser des valeurs de retour dans vos fonctions</h3> +### Utiliser des valeurs de retour dans vos fonctions -<p>Pour retourner une valeur d'une fonction que vous avez créée, vous devez utiliser... suspense... le mot-clef <a href="/fr/docs/Web/JavaScript/Reference/Statements/return">return</a> . Nous avons vu son utilisation dans l'exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html">random-canvas-circles.html</a>. Notre fonction <code>draw()</code> dessine 100 cercles aléatoires en HTML. {{htmlelement("canvas")}}:</p> +Pour retourner une valeur d'une fonction que vous avez créée, vous devez utiliser... suspense... le mot-clef [return](/fr/docs/Web/JavaScript/Reference/Statements/return) . Nous avons vu son utilisation dans l'exemple [random-canvas-circles.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html). Notre fonction `draw()` dessine 100 cercles aléatoires en HTML. {{htmlelement("canvas")}}: -<pre class="brush: js">function draw() { +```js +function draw() { ctx.clearRect(0,0,WIDTH,HEIGHT); - for (var i = 0; i < 100; i++) { + for (var i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = 'rgba(255,0,0,0.5)'; ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); ctx.fill(); } -}</pre> +} +``` -<p>À chaque itération de la boucle, on fait trois fois appel à la fonction <code>random()</code> pour générer respectivement une valeur aléatoire pour les coordonnées x et y du cercle, ainsi que pour son rayon. La fonction <code>random()</code> prend un seul paramètre — un nombre entier — et elle retourne un nombre entier aléatoire compris entre 0 et ce nombre. Voici à quoi cela ressemble:</p> +À chaque itération de la boucle, on fait trois fois appel à la fonction `random()` pour générer respectivement une valeur aléatoire pour les coordonnées x et y du cercle, ainsi que pour son rayon. La fonction `random()` prend un seul paramètre — un nombre entier — et elle retourne un nombre entier aléatoire compris entre 0 et ce nombre. Voici à quoi cela ressemble: -<pre class="brush: js">function random(number) { +```js +function random(number) { return Math.floor(Math.random()*number); -}</pre> +} +``` -<p>Cela peut aussi s'écrire ainsi:</p> +Cela peut aussi s'écrire ainsi: -<pre class="brush: js">function random(number) { +```js +function random(number) { var result = Math.floor(Math.random()*number); return result; -}</pre> +} +``` -<p>Mais la première version est plus rapide à écrire, et plus compacte.</p> +Mais la première version est plus rapide à écrire, et plus compacte. -<p>La fonction retourne le résultat de <code>Math.floor(Math.random()*number)</code> chaque fois qu'elle est appelée. Cette valeur de retour apparaît à l'endroit où la fonction a été appelée, puis le code continue. Si, par exemple, nous exécutons la ligne suivante:</p> +La fonction retourne le résultat de `Math.floor(Math.random()*number)` chaque fois qu'elle est appelée. Cette valeur de retour apparaît à l'endroit où la fonction a été appelée, puis le code continue. Si, par exemple, nous exécutons la ligne suivante: -<pre class="brush: js">ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);</pre> +```js +ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); +``` -<p>et que les trois appels <code>random()</code> retournent respectivement les valeurs 500, 200 et 35, la ligne pourrait être écrite de cette façon:</p> +et que les trois appels `random()` retournent respectivement les valeurs 500, 200 et 35, la ligne pourrait être écrite de cette façon: -<pre class="brush: js">ctx.arc(500, 200, 35, 0, 2 * Math.PI);</pre> +```js +ctx.arc(500, 200, 35, 0, 2 * Math.PI); +``` -<p>Les fonctions de la ligne sont évaluées en premières, et leurs valeurs de retour viennent remplacer les appels de fonctions avant que la ligne elle-même ne soit exécutée.</p> +Les fonctions de la ligne sont évaluées en premières, et leurs valeurs de retour viennent remplacer les appels de fonctions avant que la ligne elle-même ne soit exécutée. -<h2 id="Apprentissage_actif_notre_propre_fonction_avec_valeur_de_retour">Apprentissage actif: notre propre fonction avec valeur de retour</h2> +## Apprentissage actif: notre propre fonction avec valeur de retour -<p>Allons-y, écrivons nos propres fonctions avec des valeurs de retour.</p> +Allons-y, écrivons nos propres fonctions avec des valeurs de retour. -<ol> - <li>Pour commencer, faites une copie locale du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library.html">function-library.html</a> à partir de GitHub. Il s'agit d'une simple page HTML contenant un champ texte {{htmlelement("input")}} et un paragraphe. Il y a également un élément {{htmlelement("script")}} qui référence ces éléments HTML dans deux variables. Cette page vous permettra d'entrer un nombre dans le champ texte, et affichera, dans le paragraphe au-dessous, différents nombres en lien avec celui entré.</li> - <li>Ajoutons quelques fonctions dans <code><script></code> . Sous les deux lignes existantes de JavaScript, ajoutez les définitions des fonctions suivantes: - <pre class="brush: js">function squared(num) { - return num * num; -} +1. Pour commencer, faites une copie locale du fichier [function-library.html](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library.html) à partir de GitHub. Il s'agit d'une simple page HTML contenant un champ texte {{htmlelement("input")}} et un paragraphe. Il y a également un élément {{htmlelement("script")}} qui référence ces éléments HTML dans deux variables. Cette page vous permettra d'entrer un nombre dans le champ texte, et affichera, dans le paragraphe au-dessous, différents nombres en lien avec celui entré. +2. Ajoutons quelques fonctions dans `<script>` . Sous les deux lignes existantes de JavaScript, ajoutez les définitions des fonctions suivantes: -function cubed(num) { - return num * num * num; -} + ```js + function squared(num) { + return num * num; + } -function factorial(num) { - var x = num; - while (x > 1) { - num *= x-1; - x--; - } - return num; -}</pre> - Les fonctions <code>squared()</code> et <code>cubed()</code> sont plutôt évidentes, elle retournent le carré et le cube du nombre donné en paramètre. La fonction <code>factorial()</code> retourne la <a href="https://en.wikipedia.org/wiki/Factorial">factorielle</a> du nombre donné.</li> - <li>Ensuite, nous allons ajouter un moyen d'afficher des informations sur le nombre entré dans le champ texte. Ajoutez le gestionnaire d'événement suivant à la suite des fonctions: - <pre class="brush: js">input.onchange = function() { - var num = input.value; - if (isNaN(num)) { - para.textContent = 'You need to enter a number!'; - } else { - para.textContent = num + ' squared is ' + squared(num) + '. ' + - num + ' cubed is ' + cubed(num) + '. ' + - num + ' factorial is ' + factorial(num) + '.'; - } -}</pre> + function cubed(num) { + return num * num * num; + } + + function factorial(num) { + var x = num; + while (x > 1) { + num *= x-1; + x--; + } + return num; + } + ``` + + Les fonctions `squared()` et `cubed()` sont plutôt évidentes, elle retournent le carré et le cube du nombre donné en paramètre. La fonction `factorial()` retourne la [factorielle](https://en.wikipedia.org/wiki/Factorial) du nombre donné. + +3. Ensuite, nous allons ajouter un moyen d'afficher des informations sur le nombre entré dans le champ texte. Ajoutez le gestionnaire d'événement suivant à la suite des fonctions: + + ```js + input.onchange = function() { + var num = input.value; + if (isNaN(num)) { + para.textContent = 'You need to enter a number!'; + } else { + para.textContent = num + ' squared is ' + squared(num) + '. ' + + num + ' cubed is ' + cubed(num) + '. ' + + num + ' factorial is ' + factorial(num) + '.'; + } + } + ``` + + Ici nous créons un gestionnaire d'événement `onchange` qui s'exécute chaque fois que l'événement `change` se déclenche sur le champ de saisie de texte, c'est-à-dire lorsqu'une nouvelle valeur est entrée dans le champ de saisie de texte, puis qu'elle est soumise (par exemple lorsqu'on entre une valeur puis qu'on appuie sur Tab). Quand cette fonction anonyme s'exécute, la valeur entrée dans le champ de saisie est stockée dans la variable `num`. - <p>Ici nous créons un gestionnaire d'événement <code>onchange</code> qui s'exécute chaque fois que l'événement <code>change</code> se déclenche sur le champ de saisie de texte, c'est-à-dire lorsqu'une nouvelle valeur est entrée dans le champ de saisie de texte, puis qu'elle est soumise (par exemple lorsqu'on entre une valeur puis qu'on appuie sur Tab). Quand cette fonction anonyme s'exécute, la valeur entrée dans le champ de saisie est stockée dans la variable <code>num</code>.</p> + Ensuite, nous faisons un test: Si la valeur entrée n'est pas un nombre, un message d'erreur s'affiche dans le paragraphe. Le test vérifie si l'expression `isNaN(num)` retourne `true`. Nous utilisons la fonction [isNaN()](/fr/docs/Web/JavaScript/Reference/Global_Objects/isNaN) pour vérifier si la valeur `num` est un nombre — si c'est le cas, elle retourne `false`, sinon `true`. - <p>Ensuite, nous faisons un test: Si la valeur entrée n'est pas un nombre, un message d'erreur s'affiche dans le paragraphe. Le test vérifie si l'expression <code>isNaN(num)</code> retourne <code>true</code>. Nous utilisons la fonction <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/isNaN">isNaN()</a> pour vérifier si la valeur <code>num</code> est un nombre — si c'est le cas, elle retourne <code>false</code>, sinon <code>true</code>.</p> + Si le test retourne `false`, la valeur `num` est un nombre, alors une phrase s'affiche dans le paragraphe indiquant le carré, le cube et la factorielle du nombre. La phrase appelle les fonctions `squared()`, `cubed()` et `factorial()` pour obtenir les valeurs désirées. - <p>Si le test retourne <code>false</code>, la valeur <code>num</code> est un nombre, alors une phrase s'affiche dans le paragraphe indiquant le carré, le cube et la factorielle du nombre. La phrase appelle les fonctions <code>squared()</code>, <code>cubed()</code> et <code>factorial()</code> pour obtenir les valeurs désirées.</p> - </li> - <li>Sauvegardez votre code, chargez-le dans votre navigateur et testez-le.</li> -</ol> +4. Sauvegardez votre code, chargez-le dans votre navigateur et testez-le. -<div class="note"> -<p><strong>Note :</strong> Si vous rencontrez des difficultés pour faire fonctionner cet exemple, vous pouvez vérifier le code en le comparant à la <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library-finished.html">Version final sur GitHub</a> (également <a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-library-finished.html">Démonstration en direct</a>), ou demandez-nous de l'aide.</p> -</div> +> **Note :** Si vous rencontrez des difficultés pour faire fonctionner cet exemple, vous pouvez vérifier le code en le comparant à la [Version final sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library-finished.html) (également [Démonstration en direct](http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-library-finished.html)), ou demandez-nous de l'aide. -<p>À ce stade, nous aimerions que vous essayiez d'écrire quelque fonctions de votre choix et que vous les ajoutiez à la bibliothèque. Que diriez-vous des racines carré et cubique du nombre, ou de la circonférence d'un cercle de rayon <code>num</code>?</p> +À ce stade, nous aimerions que vous essayiez d'écrire quelque fonctions de votre choix et que vous les ajoutiez à la bibliothèque. Que diriez-vous des racines carré et cubique du nombre, ou de la circonférence d'un cercle de rayon `num`? -<p>Cet exercice a soulevé quelques points importants en plus de nous avoir permis d'étudier l'utilisation de la déclaration <code>return</code>. De plus, nous avons:</p> +Cet exercice a soulevé quelques points importants en plus de nous avoir permis d'étudier l'utilisation de la déclaration `return`. De plus, nous avons: -<ul> - <li>Examiné un autre exemple d'écriture de gestion d'erreurs dans nos fonctions. C'est une bonne idée de vérifier que tous les paramètres nécessaires ont été fournis, avec les bons types de données, et, s'ils sont facultatifs, qu'une valeur par défaut est fournie. De cette façon, votre programme sera moins susceptible de lever des erreurs.</li> - <li>Pensé à créer une bibliothèque de fonctions. À mesure que vous avancerez dans votre carrière de développeur, vous recommencerez les mêmes choses encore et encore. C'est une bonne idée de commencer à créer votre propre bibliothèque de fonctions utilitaires que vous utilisez très souvent — vous pouvez ensuite copier ces fonctions dans votre nouveau code, ou même utiliser la bibliothèque dans les pages HTML où vous en avez besoin.</li> -</ul> +- Examiné un autre exemple d'écriture de gestion d'erreurs dans nos fonctions. C'est une bonne idée de vérifier que tous les paramètres nécessaires ont été fournis, avec les bons types de données, et, s'ils sont facultatifs, qu'une valeur par défaut est fournie. De cette façon, votre programme sera moins susceptible de lever des erreurs. +- Pensé à créer une bibliothèque de fonctions. À mesure que vous avancerez dans votre carrière de développeur, vous recommencerez les mêmes choses encore et encore. C'est une bonne idée de commencer à créer votre propre bibliothèque de fonctions utilitaires que vous utilisez très souvent — vous pouvez ensuite copier ces fonctions dans votre nouveau code, ou même utiliser la bibliothèque dans les pages HTML où vous en avez besoin. -<h2 id="Conclusion">Conclusion</h2> +## Conclusion -<p>Nous l'avons vu, les fonctions sont amusantes, très utiles et, bien qu'il y ait beaucoup à dire en termes de syntaxe et de fonctionnalités, elles sont assez compréhensibles si elles sont étudiés correctement.</p> +Nous l'avons vu, les fonctions sont amusantes, très utiles et, bien qu'il y ait beaucoup à dire en termes de syntaxe et de fonctionnalités, elles sont assez compréhensibles si elles sont étudiés correctement. -<p>Si vous n'avez pas compris quelque chose, n'hésitez pas à relire l'article, ou <a href="/fr/Learn#Contact_us">contactez-nous</a> pour obtenir de l'aide.</p> +Si vous n'avez pas compris quelque chose, n'hésitez pas à relire l'article, ou [contactez-nous](/fr/Learn#Contact_us) pour obtenir de l'aide. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/JavaScript/Reference/Functions">Fonctions en profondeur</a> — Un guide détaillé couvrant des information plus avancées sur les fonctions.</li> - <li><a href="https://www.impressivewebs.com/callback-functions-javascript/">Fonction Callback en JavaScript</a> — Une façon courante en JavaScript consiste à passer une fonction à une autre en tant qu'argument, qui est alors appelée à l'intérieur de la première fonction. Cela va au delà de la portée de ce cours, mais mériterait d'être étudier rapidement.</li> -</ul> +- [Fonctions en profondeur](/fr/docs/Web/JavaScript/Reference/Functions) — Un guide détaillé couvrant des information plus avancées sur les fonctions. +- [Fonction Callback en JavaScript](https://www.impressivewebs.com/callback-functions-javascript/) — Une façon courante en JavaScript consiste à passer une fonction à une autre en tant qu'argument, qui est alors appelée à l'intérieur de la première fonction. Cela va au delà de la portée de ce cours, mais mériterait d'être étudier rapidement. -<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}} -<p> </p> -<h2 id="Dans_ce_module">Dans ce module</h2> -<ul> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/conditionals">Prendre des décisions dans le code — conditions</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code">Les boucles dans le code</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Fonctions">Fonctions — Des blocs de code réutilisables</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Build_your_own_function">Construire vos propres fonctions</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Return_values">Valeurs de retour des fonctions</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">Introduction aux événements</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Image_gallery">Galerie d'images</a></li> -</ul> +## Dans ce module -<p> </p> +- [Prendre des décisions dans le code — conditions](/fr/docs/Apprendre/JavaScript/Building_blocks/conditionals) +- [Les boucles dans le code](/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code) +- [Fonctions — Des blocs de code réutilisables](/fr/docs/Apprendre/JavaScript/Building_blocks/Fonctions) +- [Construire vos propres fonctions](/fr/docs/Apprendre/JavaScript/Building_blocks/Build_your_own_function) +- [Valeurs de retour des fonctions](/fr/docs/Apprendre/JavaScript/Building_blocks/Return_values) +- [Introduction aux événements](/fr/docs/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements) +- [Galerie d'images](/fr/docs/Apprendre/JavaScript/Building_blocks/Image_gallery) diff --git a/files/fr/learn/javascript/client-side_web_apis/client-side_storage/index.md b/files/fr/learn/javascript/client-side_web_apis/client-side_storage/index.md index 60cc11cd4a..5940cfeb39 100644 --- a/files/fr/learn/javascript/client-side_web_apis/client-side_storage/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/client-side_storage/index.md @@ -13,478 +13,445 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Client-side_storage original_slug: Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage --- -<p>{{LearnSidebar}}</p> +{{LearnSidebar}} -<div>{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> +{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}} -<div></div> - -<p>Les navigateurs web modernes permettent aux sites web de stocker des données sur l'ordinateur de l'utilisateur — avec sa permission — puis de les récupérer au besoin. Cela permet d'enregistrer des données pour du stockage à long terme, de sauvegarder des documents ou des sites hors-ligne, de conserver des préférences spécifiques à l'utilisateur et plus encore. Cet article explique les fondamentaux pour y parvenir.</p> +Les navigateurs web modernes permettent aux sites web de stocker des données sur l'ordinateur de l'utilisateur — avec sa permission — puis de les récupérer au besoin. Cela permet d'enregistrer des données pour du stockage à long terme, de sauvegarder des documents ou des sites hors-ligne, de conserver des préférences spécifiques à l'utilisateur et plus encore. Cet article explique les fondamentaux pour y parvenir. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis:</th> - <td>Notions de bases de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, <a href="/fr/Apprendre/JavaScript/Building_blocks">les briques JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), les <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">notions de base des APIs côté client</a></td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Apprendre à utiliser les APIs de stockage côté client pour stocker des données de l'application.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td> + Notions de bases de JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, + <a href="/fr/Apprendre/JavaScript/Building_blocks" + >les briques JavaScript</a + >, + <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), + les + <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction" + >notions de base des APIs côté client</a + > + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td> + Apprendre à utiliser les APIs de stockage côté client pour stocker des + données de l'application. + </td> + </tr> + </tbody> </table> -<h2 id="Stockage_côté_client">Stockage côté client ?</h2> +## Stockage côté client ? -<p>Ailleurs dans la zone d'apprentissage de MDN, nous avons parlé de la différence entre les <a href="/fr/docs/Learn/Server-side/First_steps/Client-Server_overview#Static_sites">sites statiques</a> et les <a href="/fr/docs/Learn/Server-side/First_steps/Client-Server_overview#Dynamic_sites">sites dynamiques</a> — ces derniers stockent des données <a href="/fr/docs/Learn/Server-side">côté serveur</a> en utilisant une base de données. Ensuite, ils exécutent du code pour récupérer les données et les insérer dans des templates de page statique. Finalement, le HTML résultant est envoyé au client, qui est alors affiché par le navigateur de l'utilisateur.</p> +Ailleurs dans la zone d'apprentissage de MDN, nous avons parlé de la différence entre les [sites statiques](/fr/docs/Learn/Server-side/First_steps/Client-Server_overview#Static_sites) et les [sites dynamiques](/fr/docs/Learn/Server-side/First_steps/Client-Server_overview#Dynamic_sites) — ces derniers stockent des données [côté serveur](/fr/docs/Learn/Server-side) en utilisant une base de données. Ensuite, ils exécutent du code pour récupérer les données et les insérer dans des templates de page statique. Finalement, le HTML résultant est envoyé au client, qui est alors affiché par le navigateur de l'utilisateur. -<p>Le stockage côté client fonctionne sur des principes similaires, mais pour une utilisation différente. Le stockage côté client repose sur des APIs JavaScript qui permettent de stocker des données sur la machine de l'utilisateur et de les récupérer au besoin. Cela peut se révéler utile dans différents cas comme :</p> +Le stockage côté client fonctionne sur des principes similaires, mais pour une utilisation différente. Le stockage côté client repose sur des APIs JavaScript qui permettent de stocker des données sur la machine de l'utilisateur et de les récupérer au besoin. Cela peut se révéler utile dans différents cas comme : -<ul> - <li>Personnaliser les préférences du site (par exemple, afficher des widgets personnalisés selon le choix de l'utilisateur, changer le thème du site ou la taille de la police).</li> - <li>Enregistrer les activités sur le site (comme le contenu d'un panier d'achat d'une session précédente, ou encore se souvenir si l'utilisateur s'est déjà connecté).</li> - <li>Sauvegarder des données et ressources localement pour pouvoir accéder au site plus rapidement ou même sans connexion réseau.</li> - <li>Sauvegarder des documents générés par l'application pour une utilisation hors ligne.</li> -</ul> +- Personnaliser les préférences du site (par exemple, afficher des widgets personnalisés selon le choix de l'utilisateur, changer le thème du site ou la taille de la police). +- Enregistrer les activités sur le site (comme le contenu d'un panier d'achat d'une session précédente, ou encore se souvenir si l'utilisateur s'est déjà connecté). +- Sauvegarder des données et ressources localement pour pouvoir accéder au site plus rapidement ou même sans connexion réseau. +- Sauvegarder des documents générés par l'application pour une utilisation hors ligne. -<p>Souvent, le stockage côté client et côté serveur sont utilisés ensemble. Par exemple, vous pouvez télécharger à partir d'une base de données côté serveur une série de fichiers mp3 utilisés par un site web (comme un jeu ou une application de musique) vers une base de données côté client et ainsi pouvoir les lire quand vous le voulez. Avec cette stratégie, l'utilisateur n'a à télécharger le fichier qu'une seule fois — les visites suivantes, ils sont récupérés à partir de la base de données locale.</p> +Souvent, le stockage côté client et côté serveur sont utilisés ensemble. Par exemple, vous pouvez télécharger à partir d'une base de données côté serveur une série de fichiers mp3 utilisés par un site web (comme un jeu ou une application de musique) vers une base de données côté client et ainsi pouvoir les lire quand vous le voulez. Avec cette stratégie, l'utilisateur n'a à télécharger le fichier qu'une seule fois — les visites suivantes, ils sont récupérés à partir de la base de données locale. -<div class="note"> -<p><strong>Note :</strong> La quantité de données que l'on peut stocker à l'aide des APIs de stockage côté client est limitée (limite par API et limite globale), la limite exacte dépend du navigateur et des configurations. Voir <a href="/fr/docs/Web/API/API_IndexedDB/Browser_storage_limits_and_eviction_criteria">Limites de stockage du navigateur et critères d'éviction</a> pour plus d'informations.</p> -</div> +> **Note :** La quantité de données que l'on peut stocker à l'aide des APIs de stockage côté client est limitée (limite par API et limite globale), la limite exacte dépend du navigateur et des configurations. Voir [Limites de stockage du navigateur et critères d'éviction](/fr/docs/Web/API/API_IndexedDB/Browser_storage_limits_and_eviction_criteria) pour plus d'informations. -<h3 id="À_lancienne_les_cookies">À l'ancienne : les cookies</h3> +### À l'ancienne : les cookies -<p>Le concept de stockage côté client existe depuis longtemps. Au début du web, les sites utilisaient des <a href="/fr/docs/Web/HTTP/Cookies">cookies</a> pour stocker des informations et personnaliser l'expérience utilisateur. C'est la méthode de stockage côté client la plus couramment utilisée et la plus ancienne.</p> +Le concept de stockage côté client existe depuis longtemps. Au début du web, les sites utilisaient des [cookies](/fr/docs/Web/HTTP/Cookies) pour stocker des informations et personnaliser l'expérience utilisateur. C'est la méthode de stockage côté client la plus couramment utilisée et la plus ancienne. -<p>De par leur histoire, les cookies souffrent d'un certain nombre de problèmes — tant techniques qu'au niveau de l'expérience utilisateur. Ces problèmes sont suffisamment importants pour imposer un message d'information aux utilisateurs habitant en Europe lors de leur première visite si le site utilise des cookies pour stocker des informations sur eux. Cela est dû à une loi de l'Union Européenne connue sous le nom de <a href="/fr/docs/Web/HTTP/Cookies#EU_cookie_directive">directive Cookie</a>.</p> +De par leur histoire, les cookies souffrent d'un certain nombre de problèmes — tant techniques qu'au niveau de l'expérience utilisateur. Ces problèmes sont suffisamment importants pour imposer un message d'information aux utilisateurs habitant en Europe lors de leur première visite si le site utilise des cookies pour stocker des informations sur eux. Cela est dû à une loi de l'Union Européenne connue sous le nom de [directive Cookie](/fr/docs/Web/HTTP/Cookies#EU_cookie_directive). -<p><img alt="" src="cookies-notice.png"></p> + -<p>Pour ces raisons, nous ne verrons pas dans cet article comment utiliser les cookies. Entre le fait qu'ils sont dépassés, les <a href="/fr/docs/Web/HTTP/Cookies#Security">problèmes de sécurité</a> qu'ils présentent et l'incapacité de stocker des données complexes, les cookies ne sont pas la meilleure manière pour stocker des données. Il y a de meilleures alternatives, modernes, permettant de stocker des données variées sur l'ordinateur de l'utilisateur.</p> +Pour ces raisons, nous ne verrons pas dans cet article comment utiliser les cookies. Entre le fait qu'ils sont dépassés, les [problèmes de sécurité](/fr/docs/Web/HTTP/Cookies#Security) qu'ils présentent et l'incapacité de stocker des données complexes, les cookies ne sont pas la meilleure manière pour stocker des données. Il y a de meilleures alternatives, modernes, permettant de stocker des données variées sur l'ordinateur de l'utilisateur. -<p>Le seul avantage des cookies est qu'ils sont supportés par des navigateurs anciens : si votre projet requiert le support de navigateurs obsolètes (comme Internet Explorer 8 et inférieur), les cookies peuvent se révéler utiles. Pour la plupart des projets, vous ne devriez pas avoir besoin d'y recourir.</p> +Le seul avantage des cookies est qu'ils sont supportés par des navigateurs anciens : si votre projet requiert le support de navigateurs obsolètes (comme Internet Explorer 8 et inférieur), les cookies peuvent se révéler utiles. Pour la plupart des projets, vous ne devriez pas avoir besoin d'y recourir. -<div class="note"> -<p><strong>Note :</strong> Pourquoi existe-t-il encore de nouveaux sites crées à l'aide de cookies? Principalement de par les habitudes des développeurs, l'utilisation de bibliothèques anciennes qui utilisent encore des cookies et l'existence de nombreux sites web fournissant des formations et références dépassées pour apprendre à stocker des données.</p> -</div> +> **Note :** Pourquoi existe-t-il encore de nouveaux sites crées à l'aide de cookies? Principalement de par les habitudes des développeurs, l'utilisation de bibliothèques anciennes qui utilisent encore des cookies et l'existence de nombreux sites web fournissant des formations et références dépassées pour apprendre à stocker des données. -<h3 id="La_nouvelle_école_Web_Storage_et_IndexedDB">La nouvelle école : Web Storage et IndexedDB</h3> +### La nouvelle école : Web Storage et IndexedDB -<p>Les navigateurs modernes ont des APIs beaucoup plus efficaces et faciles d'utilisation pour stocker des données côté client.</p> +Les navigateurs modernes ont des APIs beaucoup plus efficaces et faciles d'utilisation pour stocker des données côté client. -<ul> - <li>L'<a href="/fr/docs/Web/API/Web_Storage_API">API Web Storage</a> fournit une syntaxe très simple pour stocker et récupérer des données de petite taille, basé sur un système de clé/valeur. C'est utile lorsque vous avez besoin de stocker des données simples, comme le nom de l'utilisateur, le fait qu'il soit connecté ou non, la couleur à utiliser pour l'arrière-plan de l'écran, etc.</li> - <li>L'<a href="/fr/docs/Web/API/API_IndexedDB">API IndexedDB</a> fournit au navigateur un système de base de données complet pour stocker des données complexes. C'est utile pour des choses allant de simples sauvegardes côté client (texte) au stockage de données complexes tels que des fichiers audio ou vidéo.</li> -</ul> +- L'[API Web Storage](/fr/docs/Web/API/Web_Storage_API) fournit une syntaxe très simple pour stocker et récupérer des données de petite taille, basé sur un système de clé/valeur. C'est utile lorsque vous avez besoin de stocker des données simples, comme le nom de l'utilisateur, le fait qu'il soit connecté ou non, la couleur à utiliser pour l'arrière-plan de l'écran, etc. +- L'[API IndexedDB](/fr/docs/Web/API/API_IndexedDB) fournit au navigateur un système de base de données complet pour stocker des données complexes. C'est utile pour des choses allant de simples sauvegardes côté client (texte) au stockage de données complexes tels que des fichiers audio ou vidéo. -<p>Vous en apprendrez plus sur ces APIs ci-dessous.</p> +Vous en apprendrez plus sur ces APIs ci-dessous. -<h3 id="Le_futur_lAPI_Cache">Le futur : l'API Cache</h3> +### Le futur : l'API Cache -<p>Certains navigateurs modernes prennent en charge la nouvelle API {{domxref("Cache")}}. Cette API a été conçue pour stocker les réponses HTTP de requêtes données et est très utile pour stocker des ressources du site afin qu'il soit accessible sans connexion réseau par exemple. Le cache est généralement utilisé avec l'<a href="/fr/docs/Web/API/Service_Worker_API">API Service Worker</a>, mais ce n'est pas obligatoire.</p> +Certains navigateurs modernes prennent en charge la nouvelle API {{domxref("Cache")}}. Cette API a été conçue pour stocker les réponses HTTP de requêtes données et est très utile pour stocker des ressources du site afin qu'il soit accessible sans connexion réseau par exemple. Le cache est généralement utilisé avec l'[API Service Worker](/fr/docs/Web/API/Service_Worker_API), mais ce n'est pas obligatoire. -<p>L'utilisation du Cache et des Service Workers est un sujet avancé, nous ne le traiterons pas en détail dans cet article, nous ne montrerons qu'un simple exemple dans la section {{anch("Stockage hors-ligne de ressources")}} plus bas.</p> +L'utilisation du Cache et des Service Workers est un sujet avancé, nous ne le traiterons pas en détail dans cet article, nous ne montrerons qu'un simple exemple dans la section {{anch("Stockage hors-ligne de ressources")}} plus bas. -<h2 id="Stocker_des_données_simples_—_web_storage">Stocker des données simples — web storage</h2> +## Stocker des données simples — web storage -<p>L'<a href="/fr/docs/Web/API/Web_Storage_API">API Web Storage</a> est très facile à utiliser — on stocke une simple paire clé/valeur de données (limité aux données scalaires) et on les récupére au besoin.</p> +L'[API Web Storage](/fr/docs/Web/API/Web_Storage_API) est très facile à utiliser — on stocke une simple paire clé/valeur de données (limité aux données scalaires) et on les récupére au besoin. -<h3 id="Syntaxe_basique">Syntaxe basique</h3> +### Syntaxe basique -<p>Nous allons vous guider pas à pas :</p> +Nous allons vous guider pas à pas : -<ol> - <li> - <p>Tout d'abord, ouvez notre template vide de <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/web-storage/index.html">web storage sur GitHub</a> dans un nouvel onglet.</p> - </li> - <li> - <p>Ouvrez la console JavaScript de votre navigateur.</p> - </li> - <li> - <p>Toutes les données du web storage sont contenues dans deux structures de type objet : {{domxref("Window.sessionStorage", "sessionStorage")}} et {{domxref("Window.localStorage", "localStorage")}}. Le premier conserve les données aussi longtemps que le navigateur est ouvert (elles sont perdues lorsque le navigateur est fermé) et le second conserve les données même après que le navigateur ait été fermé puis ré-ouvert. Nous allons utiliser le second dans cet article car il est généralement plus utile.</p> +1. Tout d'abord, ouvez notre template vide de [web storage sur GitHub](https://mdn.github.io/learning-area/javascript/apis/client-side-storage/web-storage/index.html) dans un nouvel onglet. +2. Ouvrez la console JavaScript de votre navigateur. +3. Toutes les données du web storage sont contenues dans deux structures de type objet : {{domxref("Window.sessionStorage", "sessionStorage")}} et {{domxref("Window.localStorage", "localStorage")}}. Le premier conserve les données aussi longtemps que le navigateur est ouvert (elles sont perdues lorsque le navigateur est fermé) et le second conserve les données même après que le navigateur ait été fermé puis ré-ouvert. Nous allons utiliser le second dans cet article car il est généralement plus utile. - <p>La méthode {{domxref("Storage.setItem()")}} permet de sauvegarder des données dans le storage — elle prend deux paramètres : le nom de l'entrée à enregistrer et sa valeur. Essayez de taper ce qui suit dans votre console JavaScript (changez le nom et la valeur si vous le voulez !) :</p> + La méthode {{domxref("Storage.setItem()")}} permet de sauvegarder des données dans le storage — elle prend deux paramètres : le nom de l'entrée à enregistrer et sa valeur. Essayez de taper ce qui suit dans votre console JavaScript (changez le nom et la valeur si vous le voulez !) : - <pre class="brush: js">localStorage.setItem('name','Chris');</pre> - </li> - <li> - <p>La méthode {{domxref("Storage.getItem()")}} prend un paramètre — le nom de l'entrée que vous voulez récupérer — et retourne la valeur de l'entrée. Maintenant, tapez ces lignes dans votre console JavaScript :</p> + ```js + localStorage.setItem('name','Chris'); + ``` - <pre class="brush: js">var myName = localStorage.getItem('name'); -myName</pre> +4. La méthode {{domxref("Storage.getItem()")}} prend un paramètre — le nom de l'entrée que vous voulez récupérer — et retourne la valeur de l'entrée. Maintenant, tapez ces lignes dans votre console JavaScript : - <p>En tapant la deuxième ligne, vous devriez voir que la variable <code>myName</code> contient la valeur de l'entrée <code>name</code>.</p> - </li> - <li> - <p>La méthode {{domxref("Storage.removeItem()")}} prend un paramètre — le nom de l'entrée de vous voulez supprimer — et supprime l'entrée du web storage. Tapez les lignes suivantes dans votre console JavaScript :</p> + ```js + var myName = localStorage.getItem('name'); + myName + ``` - <pre class="brush: js">localStorage.removeItem('name'); -var myName = localStorage.getItem('name'); -myName</pre> + En tapant la deuxième ligne, vous devriez voir que la variable `myName` contient la valeur de l'entrée `name`. - <p>La troisième ligne devrait maintenant retourner <code>null</code> — l'entrée <code>name</code> n'existe plus dans le web storage.</p> - </li> -</ol> +5. La méthode {{domxref("Storage.removeItem()")}} prend un paramètre — le nom de l'entrée de vous voulez supprimer — et supprime l'entrée du web storage. Tapez les lignes suivantes dans votre console JavaScript : -<h3 id="Les_données_persistent_!">Les données persistent !</h3> + ```js + localStorage.removeItem('name'); + var myName = localStorage.getItem('name'); + myName + ``` -<p>Une caractéristique clé du web storage est que les données persistent entre les différents chargements de page (et même lorsque le navigateur est arrêté dans le cas du <code>localStorage</code>). Regardons ça en action :</p> + La troisième ligne devrait maintenant retourner `null` — l'entrée `name` n'existe plus dans le web storage. -<ol> - <li> - <p>Ouvrez notre template vide une fois de plus, mais cette fois dans un navigateur différent de celui dans lequel vous avez ouvert ce tutoriel. Cela rendra la suite plus facile.</p> - </li> - <li> - <p>Tapez ces lignes dans la console JavaScript du navigateur que vous venez d'ouvrir :</p> +### Les données persistent ! - <pre class="brush: js">localStorage.setItem('name','Chris'); -var myName = localStorage.getItem('name'); -myName</pre> - - <p>Vous devriez voir que l'entrée <code>name</code> est bien là.</p> - </li> - <li> - <p>Maintenant, fermez le navigateur et ouvrez-le de nouveau.</p> - </li> - <li> - <p>Entrez les lignes suivantes :</p> - - <pre class="brush: js">var myName = localStorage.getItem('name'); -myName</pre> - - <p>Vous devriez voir que la valeur est toujours accessible, quand bien même le navigateur a été redémarré.</p> - </li> -</ol> - -<h3 id="Stockage_séparé_pour_chaque_domaine">Stockage séparé pour chaque domaine</h3> - -<p>Il existe un système de stockage distinct pour chaque domaine (chaque adresse web chargée dans le navigateur a accès à son propre storage et pas aux autres). Vous verrez que si vous chargez deux sites web (disons google.com et amazon.com) et essayez de stocker un élément, il ne sera pas disponible sur l'autre site.</p> - -<p>C'est plutôt logique — imaginez les problèmes de sécurité qui se poseraient si les sites web pouvaient voir les données d'un autre !</p> - -<h3 id="Un_exemple_plus_impliqué">Un exemple plus impliqué</h3> - -<p>Appliquons cette nouvelle connaissance pour écrire un exemple, cela vous donnera une idée de la façon dont le web storage peut être utilisé. Notre exemple permettra d'envoyer un nom, à la suite de quoi la page sera mise à jour pour donner un accueil personnalisé. Cet état persistera également après un rechargement de la page ou redémarrage du navigateur, puisqu'il sera stocké dans le web storage.</p> - -<p>Le HTML de l'exemple est disponible à <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/personal-greeting.html">personal-greeting.html</a> — il s'agit d'un site web très simple avec entête, contenu et pied de page, ainsi qu'un formulaire pour entrer votre nom.</p> - -<p><img alt="" src="web-storage-demo.png"></p> - -<p>Nous allons construire cet exemple pas à pas, cela vous permettra de comprendre comment ça marche.</p> - -<ol> - <li> - <p>D'abord, copiez notre fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/personal-greeting.html">personal-greeting.html</a> dans un nouveau répertoire sur votre ordinateur.</p> - </li> - <li> - <p>Ensuite, créez un fichier <code>index.js</code> dans le même répertoire que le fichier HTML — le fichier HTML inclut ce script (voir ligne 40).</p> - </li> - <li> - <p>Nous allons commencer par récupérer les références de tous les éléments HTML qu'on manipulera dans cet exemple — nous les créons en tant que constantes car ces références n'ont pas besoin d'être modifiées au cours de l'exécution de l'application. Ajoutez les lignes suivantes à votre fichier JavaScript:</p> - - <pre class="brush: js">// créer les constantes nécessaires -const rememberDiv = document.querySelector('.remember'); -const forgetDiv = document.querySelector('.forget'); -const form = document.querySelector('form'); -const nameInput = document.querySelector('#entername'); -const submitBtn = document.querySelector('#submitname'); -const forgetBtn = document.querySelector('#forgetname'); - -const h1 = document.querySelector('h1'); -const personalGreeting = document.querySelector('.personal-greeting');</pre> - </li> - <li> - <p>Ensuite, on doit ajouter un gestionnaire d'événement pour empêcher le formulaire d'être véritablement soumis lorsque le bouton de soumission est cliqué, puisque ce n'est pas le comportement que l'on veut. Ajoutez le bout de code suivant à la suite de du code précédent :</p> - - <pre class="brush: js">// Empêcher le form d'être soumis -form.addEventListener('submit', function(e) { - e.preventDefault(); -});</pre> - </li> - <li> - <p>Maintenant, on doit ajouter un gestionnaire d'événement pour gérer le clic sur le bouton "Say hello" (dire bonjour). Les commentaires expliquent ce que chaque instruction fait, mais, en substance, on prend le nom que l'utilisateur a entré dans le champs texte et on l'enregistre dans le web storage avec <code>setItem()</code>. Ensuite, on exécute une fonction appelée <code>nameDisplayCheck()</code> qui se charge de mettre à jour le contenu du site web. Ajoutez ceci au bas de votre code :</p> - - <pre class="brush: js">// exécuter la fonction quand le bouton 'Say hello' est cliqué -submitBtn.addEventListener('click', function() { - // stocker le nom entré dans le web storage - localStorage.setItem('name', nameInput.value); - // exécuter nameDisplayCheck() pour afficher la - // page personnalisée et changer le formulaire - nameDisplayCheck(); -});</pre> - </li> - <li> - <p>On doit maintenant gérer l'événement lorsque le bouton "Forget" (oublier) est cliqué — il est affiché une fois que le bouton "Say hello" a été cliqué (les deux boutons permettent de basculer d'un état à l'autre). Dans cette fonction, on supprime l'élément <code>name</code> du web storage en utilisant <code>removeItem()</code>, puis on exécute <code>nameDisplayCheck()</code> pour mettre à jour l'affichage. Ajoutez ceci au bas de votre code :</p> - - <pre class="brush: js">// exécuter la fonction quand le bouton 'Forget' est cliqué -forgetBtn.addEventListener('click', function() { - // supprimer l'item name du web storage - localStorage.removeItem('name'); - // exécuter nameDisplayCheck() pour afficher la - // page personnalisée et changer le formulaire - nameDisplayCheck(); -});</pre> - </li> - <li> - <p>Il est maintenant temps de définir la fonction <code>nameDisplayCheck()</code> elle-même. Ici, on vérifie si l'élément <code>name</code> est stocké dans le web storage en utilisant <code>localStorage.getItem('name')</code> comme condition. S'il existe, la valeur retournée sera évaluée à <code>true</code>; sinon, comme <code>false</code>. S'il existe, on affiche un message d'accueil personnalisé et le bouton "Forget" du formulaire, tout en masquant le bouton "Say hello" du formulaire. Sinon, on affiche un message d'accueil générique et le bouton "Say hello". Encore une fois, mettez les lignes suivantes au bas de votre code :</p> - - <pre class="brush: js">// définit la fonction nameDisplayCheck() -function nameDisplayCheck() { - // vérifie si l'élément 'name' est stocké dans le web storage - if(localStorage.getItem('name')) { - // Si c'est le cas, affiche un accueil personnalisé - let name = localStorage.getItem('name'); - h1.textContent = 'Welcome, ' + name; - personalGreeting.textContent = 'Welcome to our website, ' + name + '! We hope you have fun while you are here.'; - // cache la partie 'remember' du formulaire et affiche la partie 'forget' - forgetDiv.style.display = 'block'; - rememberDiv.style.display = 'none'; - } else { - // Sinon, affiche un accueil générique - h1.textContent = 'Welcome to our website '; - personalGreeting.textContent = 'Welcome to our website. We hope you have fun while you are here.'; - // cache la partie 'forget' du formulaire et affiche la partie 'remember' - forgetDiv.style.display = 'none'; - rememberDiv.style.display = 'block'; - } -}</pre> - </li> - <li> - <p>Dernier point, mais non des moindres, on exécute la fonction <code>nameDisplayCheck()</code> à chaque fois que la page est chargée. Si on ne le faisait pas, l'accueil personnalisé ne serait pas affiché après qu'on ait rafraichit la page. Ajoutez ce qui suit au bas de votre code :</p> +Une caractéristique clé du web storage est que les données persistent entre les différents chargements de page (et même lorsque le navigateur est arrêté dans le cas du `localStorage`). Regardons ça en action : + +1. Ouvrez notre template vide une fois de plus, mais cette fois dans un navigateur différent de celui dans lequel vous avez ouvert ce tutoriel. Cela rendra la suite plus facile. +2. Tapez ces lignes dans la console JavaScript du navigateur que vous venez d'ouvrir : + + ```js + localStorage.setItem('name','Chris'); + var myName = localStorage.getItem('name'); + myName + ``` + + Vous devriez voir que l'entrée `name` est bien là. + +3. Maintenant, fermez le navigateur et ouvrez-le de nouveau. +4. Entrez les lignes suivantes : + + ```js + var myName = localStorage.getItem('name'); + myName + ``` + + Vous devriez voir que la valeur est toujours accessible, quand bien même le navigateur a été redémarré. + +### Stockage séparé pour chaque domaine + +Il existe un système de stockage distinct pour chaque domaine (chaque adresse web chargée dans le navigateur a accès à son propre storage et pas aux autres). Vous verrez que si vous chargez deux sites web (disons google.com et amazon.com) et essayez de stocker un élément, il ne sera pas disponible sur l'autre site. + +C'est plutôt logique — imaginez les problèmes de sécurité qui se poseraient si les sites web pouvaient voir les données d'un autre ! + +### Un exemple plus impliqué - <pre class="brush: js">document.body.onload = nameDisplayCheck;</pre> - </li> -</ol> +Appliquons cette nouvelle connaissance pour écrire un exemple, cela vous donnera une idée de la façon dont le web storage peut être utilisé. Notre exemple permettra d'envoyer un nom, à la suite de quoi la page sera mise à jour pour donner un accueil personnalisé. Cet état persistera également après un rechargement de la page ou redémarrage du navigateur, puisqu'il sera stocké dans le web storage. -<p>Notre exemple est terminé — bien joué ! Il ne vous reste plus qu'à enregistrer votre code et tester votre page HTML dans un navigateur. Vous pouvez voir notre <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/web-storage/personal-greeting.html">version terminée en direct ici</a> (ou le <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/index.js">code JavaScript terminé</a>).</p> +Le HTML de l'exemple est disponible à [personal-greeting.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/personal-greeting.html) — il s'agit d'un site web très simple avec entête, contenu et pied de page, ainsi qu'un formulaire pour entrer votre nom. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez trouver un exemple un peu plus complexe dans l'article <a href="/fr/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API">Utiliser l'API de stockage web</a>.</p> -</div> + -<div class="note"> -<p><strong>Note :</strong> Dans la ligne <code><script src="index.js" defer></script></code> de notre version finie, l'attribut <code>defer</code> spécifie que le contenu de l'élément {{htmlelement("script")}} ne doit pas s'exécuter avant que la page ait fini de charger.</p> -</div> +Nous allons construire cet exemple pas à pas, cela vous permettra de comprendre comment ça marche. -<h2 id="Stocker_des_données_complexes_—_IndexedDB">Stocker des données complexes — IndexedDB</h2> +1. D'abord, copiez notre fichier [personal-greeting.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/personal-greeting.html) dans un nouveau répertoire sur votre ordinateur. +2. Ensuite, créez un fichier `index.js` dans le même répertoire que le fichier HTML — le fichier HTML inclut ce script (voir ligne 40). +3. Nous allons commencer par récupérer les références de tous les éléments HTML qu'on manipulera dans cet exemple — nous les créons en tant que constantes car ces références n'ont pas besoin d'être modifiées au cours de l'exécution de l'application. Ajoutez les lignes suivantes à votre fichier JavaScript: -<p>L'<a href="/fr/docs/Web/API/IndexedDB_API">API IndexedDB</a> (parfois abrégé IDB) est un système de base de données complet disponible dans le navigateur. Vous pouvez y stocker des données complexes, les types ne sont pas limités à des valeurs simples de type chaînes ou nombres. Vous pouvez stocker des vidéos, des images et à peu près tout ce que vous voulez, dans une instance IndexedDB.</p> + ```js + // créer les constantes nécessaires + const rememberDiv = document.querySelector('.remember'); + const forgetDiv = document.querySelector('.forget'); + const form = document.querySelector('form'); + const nameInput = document.querySelector('#entername'); + const submitBtn = document.querySelector('#submitname'); + const forgetBtn = document.querySelector('#forgetname'); -<p>Cependant, cela a un coût : IndexedDB est beaucoup plus complexe à utiliser que l'API Web Storage. Dans cette section, nous ne ferons qu'égratigner la surface de ce qu'IndexedDB peut faire, mais nous vous en donnerons assez pour débuter.</p> + const h1 = document.querySelector('h1'); + const personalGreeting = document.querySelector('.personal-greeting'); + ``` -<h3 id="Un_exemple_de_stockage_de_notes">Un exemple de stockage de notes</h3> +4. Ensuite, on doit ajouter un gestionnaire d'événement pour empêcher le formulaire d'être véritablement soumis lorsque le bouton de soumission est cliqué, puisque ce n'est pas le comportement que l'on veut. Ajoutez le bout de code suivant à la suite de du code précédent : -<p>Nous allons voir un exemple qui vous permettra de stocker des notes dans votre navigateur, les voir et les supprimer, quand vous le souhaitez. Vous apprendrez à le construire par vous-même au fur et à mesure des explications et cela vous permettra de comprendre les parties fondamentales d'IDB.</p> + ```js + // Empêcher le form d'être soumis + form.addEventListener('submit', function(e) { + e.preventDefault(); + }); + ``` -<p>L'application ressemble à ceci :</p> +5. Maintenant, on doit ajouter un gestionnaire d'événement pour gérer le clic sur le bouton "Say hello" (dire bonjour). Les commentaires expliquent ce que chaque instruction fait, mais, en substance, on prend le nom que l'utilisateur a entré dans le champs texte et on l'enregistre dans le web storage avec `setItem()`. Ensuite, on exécute une fonction appelée `nameDisplayCheck()` qui se charge de mettre à jour le contenu du site web. Ajoutez ceci au bas de votre code : -<p><img alt="" src="idb-demo.png"></p> + ```js + // exécuter la fonction quand le bouton 'Say hello' est cliqué + submitBtn.addEventListener('click', function() { + // stocker le nom entré dans le web storage + localStorage.setItem('name', nameInput.value); + // exécuter nameDisplayCheck() pour afficher la + // page personnalisée et changer le formulaire + nameDisplayCheck(); + }); + ``` -<p>Chaque note a un titre et une description, chacun éditables individuellement. Le code JavaScript que nous allons voir ci-dessous contient des commentaires détaillés pour vous aider à comprendre ce qu'il se passe.</p> +6. On doit maintenant gérer l'événement lorsque le bouton "Forget" (oublier) est cliqué — il est affiché une fois que le bouton "Say hello" a été cliqué (les deux boutons permettent de basculer d'un état à l'autre). Dans cette fonction, on supprime l'élément `name` du web storage en utilisant `removeItem()`, puis on exécute `nameDisplayCheck()` pour mettre à jour l'affichage. Ajoutez ceci au bas de votre code : -<h3 id="Pour_commencer">Pour commencer</h3> + ```js + // exécuter la fonction quand le bouton 'Forget' est cliqué + forgetBtn.addEventListener('click', function() { + // supprimer l'item name du web storage + localStorage.removeItem('name'); + // exécuter nameDisplayCheck() pour afficher la + // page personnalisée et changer le formulaire + nameDisplayCheck(); + }); + ``` -<ol> - <li>Tout d'abord, copiez les fichiers <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index.html">index.html</a></code>, <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/style.css">style.css</a></code>, et <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index-start.js">index-start.js</a></code> dans un nouveau répertoire sur votre ordinateur.</li> - <li>Jetez un coup d'oeil aux fichiers. - <ul> - <li>Vous verrez que le HTML est assez simple : un site web avec une entête et un pied de page, ainsi qu'une zone de contenu principal contenant un emplacement pour afficher les notes et un formulaire pour en ajouter.</li> - <li>Le CSS fournit un style simple pour rendre plus clair ce qu'il se passe.</li> - <li>Le fichier JavaScript contient cinq constantes déclarées — des références à l'élément {{htmlelement("ul")}} dans lequel seront affichées les notes, les {{htmlelement("input")}} title et body, le {{htmlelement("form")}} lui-même, et un {{htmlelement("button")}}.</li> - </ul> - </li> - <li>Renommez votre fichier JavaScript en <code>index.js</code>. Vous êtes maintenant prêt pour y ajouter du code.</li> -</ol> +7. Il est maintenant temps de définir la fonction `nameDisplayCheck()` elle-même. Ici, on vérifie si l'élément `name` est stocké dans le web storage en utilisant `localStorage.getItem('name')` comme condition. S'il existe, la valeur retournée sera évaluée à `true`; sinon, comme `false`. S'il existe, on affiche un message d'accueil personnalisé et le bouton "Forget" du formulaire, tout en masquant le bouton "Say hello" du formulaire. Sinon, on affiche un message d'accueil générique et le bouton "Say hello". Encore une fois, mettez les lignes suivantes au bas de votre code : -<h3 id="Configuration_initiale_de_la_base_de_données">Configuration initiale de la base de données</h3> + ```js + // définit la fonction nameDisplayCheck() + function nameDisplayCheck() { + // vérifie si l'élément 'name' est stocké dans le web storage + if(localStorage.getItem('name')) { + // Si c'est le cas, affiche un accueil personnalisé + let name = localStorage.getItem('name'); + h1.textContent = 'Welcome, ' + name; + personalGreeting.textContent = 'Welcome to our website, ' + name + '! We hope you have fun while you are here.'; + // cache la partie 'remember' du formulaire et affiche la partie 'forget' + forgetDiv.style.display = 'block'; + rememberDiv.style.display = 'none'; + } else { + // Sinon, affiche un accueil générique + h1.textContent = 'Welcome to our website '; + personalGreeting.textContent = 'Welcome to our website. We hope you have fun while you are here.'; + // cache la partie 'forget' du formulaire et affiche la partie 'remember' + forgetDiv.style.display = 'none'; + rememberDiv.style.display = 'block'; + } + } + ``` + +8. Dernier point, mais non des moindres, on exécute la fonction `nameDisplayCheck()` à chaque fois que la page est chargée. Si on ne le faisait pas, l'accueil personnalisé ne serait pas affiché après qu'on ait rafraichit la page. Ajoutez ce qui suit au bas de votre code : + + ```js + document.body.onload = nameDisplayCheck; + ``` + +Notre exemple est terminé — bien joué ! Il ne vous reste plus qu'à enregistrer votre code et tester votre page HTML dans un navigateur. Vous pouvez voir notre [version terminée en direct ici](https://mdn.github.io/learning-area/javascript/apis/client-side-storage/web-storage/personal-greeting.html) (ou le [code JavaScript terminé](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/index.js)). -<p>Voyons maintenant la première chose à faire, mettre en place la base de données.</p> +> **Note :** Vous pouvez trouver un exemple un peu plus complexe dans l'article [Utiliser l'API de stockage web](/fr/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API). -<ol> - <li> - <p>À la suite des déclarations de constantes, ajoutez les lignes suivantes :</p> +> **Note :** Dans la ligne `<script src="index.js" defer></script>` de notre version finie, l'attribut `defer` spécifie que le contenu de l'élément {{htmlelement("script")}} ne doit pas s'exécuter avant que la page ait fini de charger. - <pre class="brush: js">// Objet db pour stocker la BDD ouverte -let db;</pre> +## Stocker des données complexes — IndexedDB - <p>Ici, on déclare une variable appelée <code>db</code> — on l'utilisera plus tard pour stocker un objet permettant d'accéder à la base de données. On l'utilisera à plusieurs endroits, on l'a donc déclaré globablement ici pour faciliter les choses.</p> - </li> - <li> - <p>Ensuite, ajoutez ce qui suit au bas de votre code :</p> +L'[API IndexedDB](/fr/docs/Web/API/IndexedDB_API) (parfois abrégé IDB) est un système de base de données complet disponible dans le navigateur. Vous pouvez y stocker des données complexes, les types ne sont pas limités à des valeurs simples de type chaînes ou nombres. Vous pouvez stocker des vidéos, des images et à peu près tout ce que vous voulez, dans une instance IndexedDB. - <pre class="brush: js">window.onload = function() { +Cependant, cela a un coût : IndexedDB est beaucoup plus complexe à utiliser que l'API Web Storage. Dans cette section, nous ne ferons qu'égratigner la surface de ce qu'IndexedDB peut faire, mais nous vous en donnerons assez pour débuter. -};</pre> +### Un exemple de stockage de notes - <p>On écrira tout notre code dans le gestionnaire d'événement <code>window.onload</code>, appelé quand l'événement {{event("load")}} de la fenêtre est chargé, pour s'assurer qu'on n'essaiera pas d'utiliser IndexedDB avant que l'application ne soit complètement chargée (ça ne marcherait pas sinon).</p> - </li> - <li> - <p>À l'intérieur de <code>window.onload</code>, ajoutez ce qui suit :</p> +Nous allons voir un exemple qui vous permettra de stocker des notes dans votre navigateur, les voir et les supprimer, quand vous le souhaitez. Vous apprendrez à le construire par vous-même au fur et à mesure des explications et cela vous permettra de comprendre les parties fondamentales d'IDB. - <pre class="brush: js">// Ouvrir la BDD; elle sera créée si elle n'existe pas déjà -// (voir onupgradeneeded) -let request = window.indexedDB.open('notes', 1);</pre> +L'application ressemble à ceci : - <p>Cette ligne crée une requête <code>request</code> pour ouvrir la version <code>1</code> de la base de données appelée <code>notes</code>. Si elle n'existe pas déjà, on devra la créer via un gestionnaire d'événement.</p> + - <p>Vous verrez très souvent ce format dans IndexedDB. Les opérations de base de données prennent du temps et on ne veut pas suspendre le navigateur le temps de récupérer le résultat, les opérations sur la base de données sont donc {{Glossary("asynchronous", "asynchrones")}} — ce qui signifie qu'au lieu d'arriver immédiatement, elles se produiront à un moment ultérieur et un événement sera déclenché lorsque cela arrivera.</p> +Chaque note a un titre et une description, chacun éditables individuellement. Le code JavaScript que nous allons voir ci-dessous contient des commentaires détaillés pour vous aider à comprendre ce qu'il se passe. - <p>Pour gérer cela dans IndexedDB, on crée d'abord une requête (que vous pouvez appeler comme vous le voulez — on l'appelle <code>request</code> pour que ce soit plus explicite). On utilise ensuite des gestionnaire d'événement pour exécuter du code lorsque les requêtes sont terminées, échouent, etc, ce que l'on va voir ci-dessous.</p> +### Pour commencer - <div class="note"> - <p><strong>Note :</strong> Le numéro de version est important. Si vous voulez mettre à jour votre base de données (par exemple, pour modifier la structure de la table), vous devez ré-exécuter votre code avec un numéro de version supérieur et spécifier le schéma de la base de données avec le gestionnaire d'événement <code>onupgradeneeded</code>. Nous ne verrons pas la mise à jour de base de données dans ce tutoriel.</p> - </div> - </li> - <li> - <p>Maintenant, ajoutez les gestionnaires d'événement suivants, juste en dessous des lignes précédentes — toujours à l'intérieur de <code>window.onload</code> :</p> +1. Tout d'abord, copiez les fichiers [`index.html`](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index.html), [`style.css`](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/style.css), et [`index-start.js`](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index-start.js) dans un nouveau répertoire sur votre ordinateur. +2. Jetez un coup d'oeil aux fichiers. - <pre class="brush: js">// la base de données n'a pas pu être ouverte avec succès -request.onerror = function() { - console.log('Database failed to open'); -}; + - Vous verrez que le HTML est assez simple : un site web avec une entête et un pied de page, ainsi qu'une zone de contenu principal contenant un emplacement pour afficher les notes et un formulaire pour en ajouter. + - Le CSS fournit un style simple pour rendre plus clair ce qu'il se passe. + - Le fichier JavaScript contient cinq constantes déclarées — des références à l'élément {{htmlelement("ul")}} dans lequel seront affichées les notes, les {{htmlelement("input")}} title et body, le {{htmlelement("form")}} lui-même, et un {{htmlelement("button")}}. -// la base de données a été ouverte avec succès -request.onsuccess = function() { - console.log('Database opened successfully'); +3. Renommez votre fichier JavaScript en `index.js`. Vous êtes maintenant prêt pour y ajouter du code. - // Stocke la base de données ouverte dans la variable db. On l'utilise par la suite - db = request.result; +### Configuration initiale de la base de données - // Exécute la fonction displayData() pour afficher les notes qui sont dans la BDD - displayData(); -};</pre> +Voyons maintenant la première chose à faire, mettre en place la base de données. - <p>Le gestionnaire d'événement {{domxref("IDBRequest.onerror", "request.onerror")}} s'exécutera si la requête échoue. Cela vous permet de gérer le problème si cela arrive. Dans notre exemple, on affiche simplement un message dans la console JavaScript.</p> +1. À la suite des déclarations de constantes, ajoutez les lignes suivantes : + + ```js + // Objet db pour stocker la BDD ouverte + let db; + ``` + + Ici, on déclare une variable appelée `db` — on l'utilisera plus tard pour stocker un objet permettant d'accéder à la base de données. On l'utilisera à plusieurs endroits, on l'a donc déclaré globablement ici pour faciliter les choses. + +2. Ensuite, ajoutez ce qui suit au bas de votre code : + + ```js + window.onload = function() { + + }; + ``` - <p>Le gestionnare d'événement {{domxref("IDBRequest.onsuccess", "request.onsuccess")}}, d'autre part, s'exécutera si la requête aboutit, que la base de données a été ouverte avec succès. Lorsque cela arrive, la propriété {{domxref("IDBRequest.result", "request.result")}} contient alors un objet représentant la base de données ouverte, qui nous permet de la manipuler. On stocke cette valeur dans la variable <code>db</code> qu'on a crée plus tôt pour pouvoir l'utiliser ensuite. On exécute également une fonction appelée <code>displayData()</code>, qu'on définira plus tard — elle affiche les données de la base de données dans le {{HTMLElement("ul")}}. On l'exécute dès à présent pour que les notes en base de données soient affichées dès que la page est chargée.</p> - </li> - <li> - <p>Pour en finir avec cette section, on ajoute le gestionnaire d'événement qui est probablement le plus important, {{domxref("IDBOpenDBRequest.onupgradeneeded", "request.onupdateneeded")}}. Il est exécuté si la base de données n'a pas déjà été créée ou si on veut ouvrir la base de données avec un numéro de version supérieur à celle qui existe (pour faire une mise à jour). Ajoutez le code suivant en dessous de votre gestionnaire précédent :</p> + On écrira tout notre code dans le gestionnaire d'événement `window.onload`, appelé quand l'événement {{event("load")}} de la fenêtre est chargé, pour s'assurer qu'on n'essaiera pas d'utiliser IndexedDB avant que l'application ne soit complètement chargée (ça ne marcherait pas sinon). - <pre class="brush: js">// Spécifie les tables de la BDD si ce n'est pas déjà pas fait -request.onupgradeneeded = function(e) { - // Récupère une référence à la BDD ouverte - let db = e.target.result; +3. À l'intérieur de `window.onload`, ajoutez ce qui suit : - // Crée un objectStore pour stocker nos notes (une table) - // Avec un champ qui s'auto-incrémente comme clé - let objectStore = db.createObjectStore('notes', { keyPath: 'id', autoIncrement:true }); + ```js + // Ouvrir la BDD; elle sera créée si elle n'existe pas déjà + // (voir onupgradeneeded) + let request = window.indexedDB.open('notes', 1); + ``` - // Définit les champs que l'objectStore contient - objectStore.createIndex('title', 'title', { unique: false }); - objectStore.createIndex('body', 'body', { unique: false }); + Cette ligne crée une requête `request` pour ouvrir la version `1` de la base de données appelée `notes`. Si elle n'existe pas déjà, on devra la créer via un gestionnaire d'événement. - console.log('Database setup complete'); -};</pre> + Vous verrez très souvent ce format dans IndexedDB. Les opérations de base de données prennent du temps et on ne veut pas suspendre le navigateur le temps de récupérer le résultat, les opérations sur la base de données sont donc {{Glossary("asynchronous", "asynchrones")}} — ce qui signifie qu'au lieu d'arriver immédiatement, elles se produiront à un moment ultérieur et un événement sera déclenché lorsque cela arrivera. - <p>C'est ici qu'on définit le schéma (la structure) de notre base de données; c'est à dire l'ensemble des champs (ou colonnes) qu'il contient.</p> + Pour gérer cela dans IndexedDB, on crée d'abord une requête (que vous pouvez appeler comme vous le voulez — on l'appelle `request` pour que ce soit plus explicite). On utilise ensuite des gestionnaire d'événement pour exécuter du code lorsque les requêtes sont terminées, échouent, etc, ce que l'on va voir ci-dessous. - <ol> - <li> - <p>On récupère une référence à la base de données existante depuis <code>e.target.result</code> (la propriété <code>result</code> de la cible de l'événement, c'est à dire l'objet <code>request</code>). C'est l'équivalent de la ligne <code>db = request.result;</code> du gestionnaire d'événement <code>onsuccess</code>, mais on doit le faire de cette manière ici puisque le gestionnaire d'événement <code>onupgradeneeded</code> est exécuté avant <code>onsuccess</code> — la valeur de <code>db</code> n'est pas encore disponible.</p> - </li> - <li> - <p>Ensuite, on utilise {{domxref("IDBDatabase.createObjectStore()")}} pour créer un object store (un container pour une collection d'objets) à l'intérieur de notre base de données. C'est l'équivalent d'une table dans un système de base de données traditionnel. On lui a donné le nom <code>notes</code>, et un champs <code>id</code> avec <code>autoIncrement</code> — pour chaque nouvelle entrée dans cette table, une valeur auto-incrementée sera attributée au champ <code>id</code> sans que le développeur n'ait à le définir. Le champ <code>id</code> est la clé de l'object store: il sera utilisé pour identifier de manière unique les entrées, permettant de les mettre à jour ou les supprimer.</p> - </li> - <li> - <p>On crée deux autres index (champs) en utilisant la méthode {{domxref("IDBObjectStore.createIndex()")}}: <code>title</code> (qui contiendra le titre de chaque note), et <code>body</code> (qui contiendra la description de chaque note).</p> - </li> - </ol> - </li> -</ol> + > **Note :** Le numéro de version est important. Si vous voulez mettre à jour votre base de données (par exemple, pour modifier la structure de la table), vous devez ré-exécuter votre code avec un numéro de version supérieur et spécifier le schéma de la base de données avec le gestionnaire d'événement `onupgradeneeded`. Nous ne verrons pas la mise à jour de base de données dans ce tutoriel. -<p>Avec ce simple schéma de base de données en place, on va pouvoir ajouter des entrées à la base de données, des objets qui ressembleront à ça :</p> +4. Maintenant, ajoutez les gestionnaires d'événement suivants, juste en dessous des lignes précédentes — toujours à l'intérieur de `window.onload` : -<pre class="brush: js">{ + ```js + // la base de données n'a pas pu être ouverte avec succès + request.onerror = function() { + console.log('Database failed to open'); + }; + + // la base de données a été ouverte avec succès + request.onsuccess = function() { + console.log('Database opened successfully'); + + // Stocke la base de données ouverte dans la variable db. On l'utilise par la suite + db = request.result; + + // Exécute la fonction displayData() pour afficher les notes qui sont dans la BDD + displayData(); + }; + ``` + + Le gestionnaire d'événement {{domxref("IDBRequest.onerror", "request.onerror")}} s'exécutera si la requête échoue. Cela vous permet de gérer le problème si cela arrive. Dans notre exemple, on affiche simplement un message dans la console JavaScript. + + Le gestionnare d'événement {{domxref("IDBRequest.onsuccess", "request.onsuccess")}}, d'autre part, s'exécutera si la requête aboutit, que la base de données a été ouverte avec succès. Lorsque cela arrive, la propriété {{domxref("IDBRequest.result", "request.result")}} contient alors un objet représentant la base de données ouverte, qui nous permet de la manipuler. On stocke cette valeur dans la variable `db` qu'on a crée plus tôt pour pouvoir l'utiliser ensuite. On exécute également une fonction appelée `displayData()`, qu'on définira plus tard — elle affiche les données de la base de données dans le {{HTMLElement("ul")}}. On l'exécute dès à présent pour que les notes en base de données soient affichées dès que la page est chargée. + +5. Pour en finir avec cette section, on ajoute le gestionnaire d'événement qui est probablement le plus important, {{domxref("IDBOpenDBRequest.onupgradeneeded", "request.onupdateneeded")}}. Il est exécuté si la base de données n'a pas déjà été créée ou si on veut ouvrir la base de données avec un numéro de version supérieur à celle qui existe (pour faire une mise à jour). Ajoutez le code suivant en dessous de votre gestionnaire précédent : + + ```js + // Spécifie les tables de la BDD si ce n'est pas déjà pas fait + request.onupgradeneeded = function(e) { + // Récupère une référence à la BDD ouverte + let db = e.target.result; + + // Crée un objectStore pour stocker nos notes (une table) + // Avec un champ qui s'auto-incrémente comme clé + let objectStore = db.createObjectStore('notes', { keyPath: 'id', autoIncrement:true }); + + // Définit les champs que l'objectStore contient + objectStore.createIndex('title', 'title', { unique: false }); + objectStore.createIndex('body', 'body', { unique: false }); + + console.log('Database setup complete'); + }; + ``` + + C'est ici qu'on définit le schéma (la structure) de notre base de données; c'est à dire l'ensemble des champs (ou colonnes) qu'il contient. + + 1. On récupère une référence à la base de données existante depuis `e.target.result` (la propriété `result` de la cible de l'événement, c'est à dire l'objet `request`). C'est l'équivalent de la ligne `db = request.result;` du gestionnaire d'événement `onsuccess`, mais on doit le faire de cette manière ici puisque le gestionnaire d'événement `onupgradeneeded` est exécuté avant `onsuccess` — la valeur de `db` n'est pas encore disponible. + 2. Ensuite, on utilise {{domxref("IDBDatabase.createObjectStore()")}} pour créer un object store (un container pour une collection d'objets) à l'intérieur de notre base de données. C'est l'équivalent d'une table dans un système de base de données traditionnel. On lui a donné le nom `notes`, et un champs `id` avec `autoIncrement` — pour chaque nouvelle entrée dans cette table, une valeur auto-incrementée sera attributée au champ `id` sans que le développeur n'ait à le définir. Le champ `id` est la clé de l'object store: il sera utilisé pour identifier de manière unique les entrées, permettant de les mettre à jour ou les supprimer. + 3. On crée deux autres index (champs) en utilisant la méthode {{domxref("IDBObjectStore.createIndex()")}}: `title` (qui contiendra le titre de chaque note), et `body` (qui contiendra la description de chaque note). + +Avec ce simple schéma de base de données en place, on va pouvoir ajouter des entrées à la base de données, des objets qui ressembleront à ça : + +```js +{ title: "Acheter du lait", body: "Lait de vache et de soja.", id: 8 -}</pre> +} +``` -<h3 id="Ajouter_des_données_à_la_base_de_données">Ajouter des données à la base de données</h3> +### Ajouter des données à la base de données -<p>Maintenant, voyons comment ajouter des entrées dans la base de données. On le fera en utilisant le formulaire de notre page.</p> +Maintenant, voyons comment ajouter des entrées dans la base de données. On le fera en utilisant le formulaire de notre page. -<ol> - <li> - <p>À la suite du gestionnaire d'événement précédent (mais toujours dans <code>window.onload</code>), ajoutez la ligne suivante — elle définit un gestionnaire d'événement <code>onsubmit</code> pour exécuter la fonction <code>addData()</code> quand le formulaire est soumis (que le {{htmlelement("button")}} envoyer est pressé et que les champs du formulaire sont valides) :</p> +1. À la suite du gestionnaire d'événement précédent (mais toujours dans `window.onload`), ajoutez la ligne suivante — elle définit un gestionnaire d'événement `onsubmit` pour exécuter la fonction `addData()` quand le formulaire est soumis (que le {{htmlelement("button")}} envoyer est pressé et que les champs du formulaire sont valides) : - <pre class="brush: js">// Créer un gestionnaire onsubmit pour appeler la fonction addData() quand le formulaire est soumis -form.onsubmit = addData;</pre> - </li> - <li> - <p>Maintenant, définissons la fonction <code>addData()</code>. Ajoutez ce qui suit après la ligne précédente :</p> + ```js + // Créer un gestionnaire onsubmit pour appeler la fonction addData() quand le formulaire est soumis + form.onsubmit = addData; + ``` - <pre class="brush: js">// Définit la fonction addData() -function addData(e) { - // empêcher le formulaire d'être soumis vers le serveur - e.preventDefault(); +2. Maintenant, définissons la fonction `addData()`. Ajoutez ce qui suit après la ligne précédente : - // récupérer les valeurs entrées dans les champs du formulaire - // et les stocker dans un objet qui sera inséré en BDD - let newItem = { title: titleInput.value, body: bodyInput.value }; + ```js + // Définit la fonction addData() + function addData(e) { + // empêcher le formulaire d'être soumis vers le serveur + e.preventDefault(); - // ouvrir une transaction en lecture/écriture - let transaction = db.transaction(['notes'], 'readwrite'); + // récupérer les valeurs entrées dans les champs du formulaire + // et les stocker dans un objet qui sera inséré en BDD + let newItem = { title: titleInput.value, body: bodyInput.value }; - // récupérer l'object store de la base de données qui a été ouvert avec la transaction - let objectStore = transaction.objectStore('notes'); + // ouvrir une transaction en lecture/écriture + let transaction = db.transaction(['notes'], 'readwrite'); - // demander l'ajout de notre nouvel objet à l'object store - var request = objectStore.add(newItem); - request.onsuccess = function() { - // vider le formulaire, pour qu'il soit prêt pour un nouvel ajout - titleInput.value = ''; - bodyInput.value = ''; - }; + // récupérer l'object store de la base de données qui a été ouvert avec la transaction + let objectStore = transaction.objectStore('notes'); - // attendre la fin de la transaction, quand l'ajout a été effectué - transaction.oncomplete = function() { - console.log('Transaction completed: database modification finished.'); + // demander l'ajout de notre nouvel objet à l'object store + var request = objectStore.add(newItem); + request.onsuccess = function() { + // vider le formulaire, pour qu'il soit prêt pour un nouvel ajout + titleInput.value = ''; + bodyInput.value = ''; + }; - // mettre à jour l'affichage pour montrer le nouvel item en exécutant displayData() - displayData(); - }; + // attendre la fin de la transaction, quand l'ajout a été effectué + transaction.oncomplete = function() { + console.log('Transaction completed: database modification finished.'); - transaction.onerror = function() { - console.log('Transaction not opened due to error'); - }; -}</pre> - - <p>C'est assez complexe, voyons ça pas à pas :</p> - - <ol> - <li> - <p>On exécute {{domxref("Event.preventDefault()")}} sur l'objet événement pour empêcher le formulaire d'être véritablement soumis (cela provoquerait une actualisation de la page et gâcherait l'expérience utilisateur).</p> - </li> - <li> - <p>On crée un objet représentant une entrée à ajouter dans la base de données, en le remplissant avec les valeurs des champs du formulaire. Notez qu'on n'a pas besoin d'inclure explicitement une valeur <code>id</code> — comme nous l'avons précédemment expliqué, il est auto-rempli.</p> - </li> - <li> - <p>On ouvre une transaction en lecture/écritre (<code>readwrite</code>) sur l'object store <code>notes</code> en utilisant la méthode {{domxref("IDBDatabase.transaction()")}}. Cet object transaction va nous permettre d'accéder à l'object store, pour ajouter une nouvelle entrée par exemple.</p> - </li> - <li> - <p>On récupère l'object store de la transaction avec la méthode {{domxref("IDBTransaction.objectStore()")}} et on le stocke dans la variable <code>objectStore</code>.</p> - </li> - <li> - <p>On ajoute un nouvel enregistrement à la base de données en utilisant {{domxref("IDBObjectStore.add()")}}. Cela crée une requête, sur le même principe qu'on a déjà vu.</p> - </li> - <li>On ajoute des gestionnaires d'événement à <code>request</code> et <code>transaction</code> pour exécuter du code aux points importants de leur cycle de vie : - <ul> - <li>Quand la requête a réussit, on efface les champs du formulaire — pour pouvoir ajouter une nouvelle note</li> - <li>Quand la transaction est terminé, on réexécute la fonction <code>displayData()</code> — pour mettre à jour l'affichage de notes sur la page.</li> - </ul> - </li> - </ol> - </li> -</ol> - -<h3 id="Afficher_les_données">Afficher les données</h3> - -<p>Nous avons déjà appelé <code>displayData()</code> deux fois dans notre code, nous allons maintenant définir cette fonction. Ajoutez ce qui suit à votre code, en dessous de la définition de la fonction précédente :</p> - -<pre class="brush: js">// Définit la fonction displayData() + // mettre à jour l'affichage pour montrer le nouvel item en exécutant displayData() + displayData(); + }; + + transaction.onerror = function() { + console.log('Transaction not opened due to error'); + }; + } + ``` + + C'est assez complexe, voyons ça pas à pas : + + 1. On exécute {{domxref("Event.preventDefault()")}} sur l'objet événement pour empêcher le formulaire d'être véritablement soumis (cela provoquerait une actualisation de la page et gâcherait l'expérience utilisateur). + 2. On crée un objet représentant une entrée à ajouter dans la base de données, en le remplissant avec les valeurs des champs du formulaire. Notez qu'on n'a pas besoin d'inclure explicitement une valeur `id` — comme nous l'avons précédemment expliqué, il est auto-rempli. + 3. On ouvre une transaction en lecture/écritre (`readwrite`) sur l'object store `notes` en utilisant la méthode {{domxref("IDBDatabase.transaction()")}}. Cet object transaction va nous permettre d'accéder à l'object store, pour ajouter une nouvelle entrée par exemple. + 4. On récupère l'object store de la transaction avec la méthode {{domxref("IDBTransaction.objectStore()")}} et on le stocke dans la variable `objectStore`. + 5. On ajoute un nouvel enregistrement à la base de données en utilisant {{domxref("IDBObjectStore.add()")}}. Cela crée une requête, sur le même principe qu'on a déjà vu. + 6. On ajoute des gestionnaires d'événement à `request` et `transaction` pour exécuter du code aux points importants de leur cycle de vie : + + - Quand la requête a réussit, on efface les champs du formulaire — pour pouvoir ajouter une nouvelle note + - Quand la transaction est terminé, on réexécute la fonction `displayData()` — pour mettre à jour l'affichage de notes sur la page. + +### Afficher les données + +Nous avons déjà appelé `displayData()` deux fois dans notre code, nous allons maintenant définir cette fonction. Ajoutez ce qui suit à votre code, en dessous de la définition de la fonction précédente : + +```js +// Définit la fonction displayData() function displayData() { // Vide le contenu de la liste à chaque fois qu'on la met à jour // Si on ne le faisait pas, des duplicats seraient affichés à chaque ajout @@ -539,39 +506,25 @@ function displayData() { console.log('Notes all displayed'); } }; -}</pre> - -<p>Encore une fois, pas à pas :</p> - -<ol> - <li> - <p>D'abord on vide le contenu de l'élément {{htmlelement("ul")}}, pour pouvoir le remplir avec le contenu mis à jour. Si on ne le faisait pas, on obtiendrait une énorme liste de contenus dupliqués à chaque mise à jour.</p> - </li> - <li> - <p>Ensuite, on récupère une référence à l'object store <code>notes</code> en utilisant {{domxref("IDBDatabase.transaction()")}} et {{domxref("IDBTransaction.objectStore()")}} comme nous l'avons fait dans <code>addData()</code>, mais en chaînant ces deux instructions en une seule ligne.</p> - </li> - <li> - <p>L'étape suivante consiste à utiliser la méthode {{domxref("IDBObjectStore.openCursor()")}} pour ouvrir un curseur — une construction qui peut être utilisée pour itérer sur les entrées d'un object store. On chaîne un gestionnaire d'événement <code>onsuccess</code> à la fin de cette opération pour rendre le code plus concis — dès que le curseur est récupéré, le gestionnaire est exécuté.</p> - </li> - <li> - <p>On récupère une référence au curseur lui-même (un objet {{domxref("IDBCursor")}}) avec <code>cursor = e.target.result</code>.</p> - </li> - <li> - <p>Ensuite, on vérifie si le curseur contient une entrée de l'object store (<code>if(cursor){ ... }</code>) — si c'est le cas, on crée des éléments du DOM, les remplit avec les données de l'entrée, et les insère dans la page (à l'intérieur de l'élément <code><ul></code>). On inclut un bouton de suppression, qui, quand il est cliqué, supprime l'entrée en cours en appelant la fonction <code>deleteItem()</code> — que nous allons voir dans la section suivante.</p> - </li> - <li> - <p>À la fin du bloc <code>if</code>, on utilise la méthode {{domxref("IDBCursor.continue()")}} pour avancer le curseur à la prochaine entrée dans l'object store et réexécuter le bloc. S'il reste une autre entrée sur laquelle itérer, elle sera à son tour insérée dans la page, <code>continue()</code> sera exécuté à nouveau, et ainsi de suite.</p> - </li> - <li> - <p>Quand il n'y a plus d'enregistrements à parcourir, le curseur retourne <code>undefined</code>, et le bloc <code>else</code> sera donc exécuté à la place. Ce bloc vérifie si des notes ont été insérées dans le <code><ul></code> — si ce n'est pas le cas, on insère un message indiquant qu'il n'existe aucune note.</p> - </li> -</ol> - -<h3 id="Supprimer_une_note">Supprimer une note</h3> - -<p>Come nous avons vu ci-dessus, lorsque le bouton supprimer est cliqué, la note correspondante est supprimée. Cette action est réalisée par la fonction <code>deleteItem()</code>, que l'on définit ainsi :</p> - -<pre class="brush: js">// Définit la fonction deleteItem() +} +``` + +Encore une fois, pas à pas : + +1. D'abord on vide le contenu de l'élément {{htmlelement("ul")}}, pour pouvoir le remplir avec le contenu mis à jour. Si on ne le faisait pas, on obtiendrait une énorme liste de contenus dupliqués à chaque mise à jour. +2. Ensuite, on récupère une référence à l'object store `notes` en utilisant {{domxref("IDBDatabase.transaction()")}} et {{domxref("IDBTransaction.objectStore()")}} comme nous l'avons fait dans `addData()`, mais en chaînant ces deux instructions en une seule ligne. +3. L'étape suivante consiste à utiliser la méthode {{domxref("IDBObjectStore.openCursor()")}} pour ouvrir un curseur — une construction qui peut être utilisée pour itérer sur les entrées d'un object store. On chaîne un gestionnaire d'événement `onsuccess` à la fin de cette opération pour rendre le code plus concis — dès que le curseur est récupéré, le gestionnaire est exécuté. +4. On récupère une référence au curseur lui-même (un objet {{domxref("IDBCursor")}}) avec `cursor = e.target.result`. +5. Ensuite, on vérifie si le curseur contient une entrée de l'object store (`if(cursor){ ... }`) — si c'est le cas, on crée des éléments du DOM, les remplit avec les données de l'entrée, et les insère dans la page (à l'intérieur de l'élément `<ul>`). On inclut un bouton de suppression, qui, quand il est cliqué, supprime l'entrée en cours en appelant la fonction `deleteItem()` — que nous allons voir dans la section suivante. +6. À la fin du bloc `if`, on utilise la méthode {{domxref("IDBCursor.continue()")}} pour avancer le curseur à la prochaine entrée dans l'object store et réexécuter le bloc. S'il reste une autre entrée sur laquelle itérer, elle sera à son tour insérée dans la page, `continue()` sera exécuté à nouveau, et ainsi de suite. +7. Quand il n'y a plus d'enregistrements à parcourir, le curseur retourne `undefined`, et le bloc `else` sera donc exécuté à la place. Ce bloc vérifie si des notes ont été insérées dans le `<ul>` — si ce n'est pas le cas, on insère un message indiquant qu'il n'existe aucune note. + +### Supprimer une note + +Come nous avons vu ci-dessus, lorsque le bouton supprimer est cliqué, la note correspondante est supprimée. Cette action est réalisée par la fonction `deleteItem()`, que l'on définit ainsi : + +```js +// Définit la fonction deleteItem() function deleteItem(e) { // Récupère l'id de l'entrée que l'on veut supprimer // On doit le convertir en nombre avant d'essayer de récupérer l'entrée correspondante dans IDB @@ -597,190 +550,186 @@ function deleteItem(e) { list.appendChild(listItem); } }; -}</pre> - -<ul> - <li>On récupère l'ID de l'entrée à supprimer avec <code>Number(e.target.parentNode.getAttribute('data-note-id'))</code> — souvenez-vous qu'on a mis l'ID de l'entrée dans l'attribut <code>data-note-id</code> du <code><li></code> au moment de l'afficher. On fait passer l'id à travers l'objet global <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Number">Number()</a>, puisqu'on a actuellement une chaîne de caractères et on a besoin d'un nombre pour qu'il soit reconnu par la base de données.</li> - <li>On récupère ensuite une référence à l'object store de la même manière que précédemment, et on utilise la méthode {{domxref("IDBObjectStore.delete()")}} pour supprimer l'entrée de la base de données, en lui passant l'ID.</li> - <li>Quand la transaction est terminée, on supprime le <code><li></code> du DOM, et on vérifie si le <code><ul></code> est maintenant vide. Si c'est le cas, on insère un message pour l'indiquer.</li> -</ul> - -<p>Et voilà ! L'exemple devrait maintenant fonctionner.</p> - -<div class="note"> -<p><strong>Note :</strong> Si vous rencontrez des difficultés, n'hésitez pas à consulter <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/indexeddb/notes/">notre exemple en direct</a> (ou voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index.js">le code source</a>).</p> -</div> - -<h3 id="Stocker_des_données_complexes_avec_IndexedDB">Stocker des données complexes avec IndexedDB</h3> - -<p>Comme nous l'avons mentionné auparavant, IndexedDB peut être utilisé pour stocker plus que de simples chaînes de caractères. On peut stocker à peu près tout ce qu'on veux, y compris des objets complexes tels que des vidéos ou des images. Et ce n'est pas plus difficilte à réaliser qu'avec n'importe quel autre type de données.</p> - -<p>Pour vous montrer comment le faire, nous avons écrit un autre exemple appelé <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/client-side-storage/indexeddb/video-store">IndexedDB video store</a> (le <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/indexeddb/video-store/">voir en direct</a>). Lorsque vous exécutez l'exemple pour la première fois, il télécharge des vidéos à partir du réseau, les stocke dans une base de données IndexedDB, puis affiche les vidéos dans des éléments {{htmlelement("video")}} de l'interface utilisateur. Les prochaines fois que vous l'exécutez, il récupère les vidéos de la base de données — cela rend les chargements suivants beaucoup plus rapides et moins gourmands en bande passante.</p> - -<p>Passons en revue les parties les plus intéressantes de l'exemple. Nous ne regarderons pas tout — une grande partie est similaire à l'exemple précédent, et le code est bien commenté.</p> - -<ol> - <li> - <p>Pour cet exemple, nous avons stocké le nom des vidéos à récupérer dans un tableau d'objets :</p> - - <pre class="brush: js">const videos = [ - { 'name' : 'crystal' }, - { 'name' : 'elf' }, - { 'name' : 'frog' }, - { 'name' : 'monster' }, - { 'name' : 'pig' }, - { 'name' : 'rabbit' } -];</pre> - </li> - <li> - <p>Pour commencer, une fois que la base de données a été ouverte, on exécute la fonction <code>init()</code>. Elle boucle sur les noms des vidéos et essaie de charger l'entrée correspondante dans la base de données <code>videos</code>.</p> +} +``` + +- On récupère l'ID de l'entrée à supprimer avec `Number(e.target.parentNode.getAttribute('data-note-id'))` — souvenez-vous qu'on a mis l'ID de l'entrée dans l'attribut `data-note-id` du `<li>` au moment de l'afficher. On fait passer l'id à travers l'objet global [Number()](/fr/docs/Web/JavaScript/Reference/Objets_globaux/Number), puisqu'on a actuellement une chaîne de caractères et on a besoin d'un nombre pour qu'il soit reconnu par la base de données. +- On récupère ensuite une référence à l'object store de la même manière que précédemment, et on utilise la méthode {{domxref("IDBObjectStore.delete()")}} pour supprimer l'entrée de la base de données, en lui passant l'ID. +- Quand la transaction est terminée, on supprime le `<li>` du DOM, et on vérifie si le `<ul>` est maintenant vide. Si c'est le cas, on insère un message pour l'indiquer. + +Et voilà ! L'exemple devrait maintenant fonctionner. + +> **Note :** Si vous rencontrez des difficultés, n'hésitez pas à consulter [notre exemple en direct](https://mdn.github.io/learning-area/javascript/apis/client-side-storage/indexeddb/notes/) (ou voir [le code source](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index.js)). + +### Stocker des données complexes avec IndexedDB + +Comme nous l'avons mentionné auparavant, IndexedDB peut être utilisé pour stocker plus que de simples chaînes de caractères. On peut stocker à peu près tout ce qu'on veux, y compris des objets complexes tels que des vidéos ou des images. Et ce n'est pas plus difficilte à réaliser qu'avec n'importe quel autre type de données. + +Pour vous montrer comment le faire, nous avons écrit un autre exemple appelé [IndexedDB video store](https://github.com/mdn/learning-area/tree/master/javascript/apis/client-side-storage/indexeddb/video-store) (le [voir en direct](https://mdn.github.io/learning-area/javascript/apis/client-side-storage/indexeddb/video-store/)). Lorsque vous exécutez l'exemple pour la première fois, il télécharge des vidéos à partir du réseau, les stocke dans une base de données IndexedDB, puis affiche les vidéos dans des éléments {{htmlelement("video")}} de l'interface utilisateur. Les prochaines fois que vous l'exécutez, il récupère les vidéos de la base de données — cela rend les chargements suivants beaucoup plus rapides et moins gourmands en bande passante. + +Passons en revue les parties les plus intéressantes de l'exemple. Nous ne regarderons pas tout — une grande partie est similaire à l'exemple précédent, et le code est bien commenté. + +1. Pour cet exemple, nous avons stocké le nom des vidéos à récupérer dans un tableau d'objets : + + ```js + const videos = [ + { 'name' : 'crystal' }, + { 'name' : 'elf' }, + { 'name' : 'frog' }, + { 'name' : 'monster' }, + { 'name' : 'pig' }, + { 'name' : 'rabbit' } + ]; + ``` + +2. Pour commencer, une fois que la base de données a été ouverte, on exécute la fonction `init()`. Elle boucle sur les noms des vidéos et essaie de charger l'entrée correspondante dans la base de données `videos`. + + On peut facilement vérifier si une entrée a été trouvée en vérifiant si `request.result` est évalué à `true` — si l'entrée n'est pas présente, la valeur retournée est `undefined`. + + Les vidéos présentes en base de données (stockées sous formes de blobs), sont directement passées à la fonction `displayVideo()` pour les afficher dans l'interface utilisateur. Pour les vidéos non présentes, on appelle la fonction `fetchVideoFromNetwork()`, qui récupère la vidéo à partir du réseau. + + ```js + function init() { + // Boucle sur les vidéos une par une + for(let i = 0; i < videos.length; i++) { + // Ouvre une transaction, récupère l'object store, et récupère chaque video par son nom + let objectStore = db.transaction('videos').objectStore('videos'); + let request = objectStore.get(videos[i].name); + request.onsuccess = function() { + // Si l'entrée existe dans la BDD (le résultat n'est pas undefined) + if(request.result) { + // Affiche la vidéo en utilisant displayVideo() + console.log('taking videos from IDB'); + displayVideo(request.result.mp4, request.result.webm, request.result.name); + } else { + // Récupère la vidéo à partir du réseau + fetchVideoFromNetwork(videos[i]); + } + }; + } + } + ``` + +3. Le bout de code qui suit est extrait de la fonction `fetchVideoFromNetwork()` — ici, on récupère les versions MP4 et WebM de la vidéos en utilisant deux requêtes {{domxref("fetch()", "WindowOrWorkerGlobalScope.fetch()")}} distinctes. On utilise ensuite la méthode {{domxref("blob()", "Body.blob()")}} pour extraire la réponse sous forme de blob, ce qui nous donne une représentation objet de la vidéo que l'on peut stocker et afficher plus tard. + + Il reste cependant un problème — ces deux requêtes sont asynchrones et ont veut afficher/stocker la vidéo uniquement lorsque les deux promesses sont résolues. Heureusement, il existe une méthode native qui gère ce problème — {{jsxref("Promise.all()")}}. Elle prend un argument — la liste de toutes les promesses qui doivent être attendues — et retourne elle-même une promesse. Quand toutes les promesses sont résolues, alors la promesse de la méthode `all()` est résolue, avec pour valeur un tableau contenant toutes les valeurs individuelles retournées par les promesses. + + À l'intérieur du bloc `all()`, vous pouvez voir qu'on appelle la fonction `displayVideo()`, comme on l'a fait précédemment, pour afficher les vidéos dans l'interface utilisateur, puis la fonction `storeVideo()` pour stocker ces vidéos dans la base de données. + + ```js + let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response => + response.blob() + ); + let webmBlob = fetch('videos/' + video.name + '.webm').then(response => + response.blob() + ); + + // Exécuter le bloc de code suivant lorsque les deux promesses sont résolues + Promise.all([mp4Blob, webmBlob]).then(function(values) { + // Afficher la vidéo récupérée à partir du réseau avec displayVideo() + displayVideo(values[0], values[1], video.name); + // La stocker dans IDB avec storeVideo() + storeVideo(values[0], values[1], video.name); + }); + ``` + +4. Regardons `storeVideo()` en premier. Cela ressemble beaucoup à ce qu'on a fait dans l'exemple précédent pour ajouter des données à la base de données — on ouvre une transaction en lecture/écriture et on récupère l'object store de `videos`, on crée un objet à ajouter à la base de données et on l'ajoute avec {{domxref("IDBObjectStore.add()")}}. + + ```js + function storeVideo(mp4Blob, webmBlob, name) { + // Ouvre une transaction, récupère object store + let objectStore = db.transaction(['videos'], 'readwrite').objectStore('videos'); + // Crée une entrée à ajouter à IDB + let record = { + mp4 : mp4Blob, + webm : webmBlob, + name : name + } - <p>On peut facilement vérifier si une entrée a été trouvée en vérifiant si <code>request.result</code> est évalué à <code>true</code> — si l'entrée n'est pas présente, la valeur retournée est <code>undefined</code>.</p> + // Ajoute l'entrée à IDB avec add() + let request = objectStore.add(record); - <p>Les vidéos présentes en base de données (stockées sous formes de blobs), sont directement passées à la fonction <code>displayVideo()</code> pour les afficher dans l'interface utilisateur. Pour les vidéos non présentes, on appelle la fonction <code>fetchVideoFromNetwork()</code>, qui récupère la vidéo à partir du réseau.</p> + ... - <pre class="brush: js">function init() { - // Boucle sur les vidéos une par une - for(let i = 0; i < videos.length; i++) { - // Ouvre une transaction, récupère l'object store, et récupère chaque video par son nom - let objectStore = db.transaction('videos').objectStore('videos'); - let request = objectStore.get(videos[i].name); - request.onsuccess = function() { - // Si l'entrée existe dans la BDD (le résultat n'est pas undefined) - if(request.result) { - // Affiche la vidéo en utilisant displayVideo() - console.log('taking videos from IDB'); - displayVideo(request.result.mp4, request.result.webm, request.result.name); - } else { - // Récupère la vidéo à partir du réseau - fetchVideoFromNetwork(videos[i]); - } }; - } -}</pre> - </li> - <li> - <p>Le bout de code qui suit est extrait de la fonction <code>fetchVideoFromNetwork()</code> — ici, on récupère les versions MP4 et WebM de la vidéos en utilisant deux requêtes {{domxref("fetch()", "WindowOrWorkerGlobalScope.fetch()")}} distinctes. On utilise ensuite la méthode {{domxref("blob()", "Body.blob()")}} pour extraire la réponse sous forme de blob, ce qui nous donne une représentation objet de la vidéo que l'on peut stocker et afficher plus tard.</p> - - <p>Il reste cependant un problème — ces deux requêtes sont asynchrones et ont veut afficher/stocker la vidéo uniquement lorsque les deux promesses sont résolues. Heureusement, il existe une méthode native qui gère ce problème — {{jsxref("Promise.all()")}}. Elle prend un argument — la liste de toutes les promesses qui doivent être attendues — et retourne elle-même une promesse. Quand toutes les promesses sont résolues, alors la promesse de la méthode <code>all()</code> est résolue, avec pour valeur un tableau contenant toutes les valeurs individuelles retournées par les promesses.</p> - - <p>À l'intérieur du bloc <code>all()</code>, vous pouvez voir qu'on appelle la fonction <code>displayVideo()</code>, comme on l'a fait précédemment, pour afficher les vidéos dans l'interface utilisateur, puis la fonction <code>storeVideo()</code> pour stocker ces vidéos dans la base de données.</p> - - <pre class="brush: js">let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response => - response.blob() -); -let webmBlob = fetch('videos/' + video.name + '.webm').then(response => - response.blob() -); - -// Exécuter le bloc de code suivant lorsque les deux promesses sont résolues -Promise.all([mp4Blob, webmBlob]).then(function(values) { - // Afficher la vidéo récupérée à partir du réseau avec displayVideo() - displayVideo(values[0], values[1], video.name); - // La stocker dans IDB avec storeVideo() - storeVideo(values[0], values[1], video.name); -});</pre> - </li> - <li> - <p>Regardons <code>storeVideo()</code> en premier. Cela ressemble beaucoup à ce qu'on a fait dans l'exemple précédent pour ajouter des données à la base de données — on ouvre une transaction en lecture/écriture et on récupère l'object store de <code>videos</code>, on crée un objet à ajouter à la base de données et on l'ajoute avec {{domxref("IDBObjectStore.add()")}}.</p> - - <pre class="brush: js">function storeVideo(mp4Blob, webmBlob, name) { - // Ouvre une transaction, récupère object store - let objectStore = db.transaction(['videos'], 'readwrite').objectStore('videos'); - // Crée une entrée à ajouter à IDB - let record = { - mp4 : mp4Blob, - webm : webmBlob, - name : name - } - - // Ajoute l'entrée à IDB avec add() - let request = objectStore.add(record); - - ... + ``` -};</pre> - </li> - <li> - <p>Enfin, <code>displayVideo()</code> crée les éléments DOM nécessaires pour insérer la vidéo dans l'interface utilisateur, puis les ajoute à la page. Les parties les plus intéressantes sont copiées ci-dessous — pour afficher notre blob vidéo dans un élément <code><video></code>, on doit créer un objet URL (URL interne qui pointe vers un blob en mémoire) en utilisant la méthode {{domxref("URL.createObjectURL()")}}. Une fois que c'est fait, on peut assigner l'URL comme valeur d'attribut <code>src</code> de l'élément {{htmlelement("source")}}, et ça marche.</p> +5. Enfin, `displayVideo()` crée les éléments DOM nécessaires pour insérer la vidéo dans l'interface utilisateur, puis les ajoute à la page. Les parties les plus intéressantes sont copiées ci-dessous — pour afficher notre blob vidéo dans un élément `<video>`, on doit créer un objet URL (URL interne qui pointe vers un blob en mémoire) en utilisant la méthode {{domxref("URL.createObjectURL()")}}. Une fois que c'est fait, on peut assigner l'URL comme valeur d'attribut `src` de l'élément {{htmlelement("source")}}, et ça marche. - <pre class="brush: js">function displayVideo(mp4Blob, webmBlob, title) { - // Crée l'objet URL à partir du blob - let mp4URL = URL.createObjectURL(mp4Blob); - let webmURL = URL.createObjectURL(webmBlob); + ```js + function displayVideo(mp4Blob, webmBlob, title) { + // Crée l'objet URL à partir du blob + let mp4URL = URL.createObjectURL(mp4Blob); + let webmURL = URL.createObjectURL(webmBlob); - ... + ... - let video = document.createElement('video'); - video.controls = true; - let source1 = document.createElement('source'); - source1.src = mp4URL; - source1.type = 'video/mp4'; - let source2 = document.createElement('source'); - source2.src = webmURL; - source2.type = 'video/webm'; + let video = document.createElement('video'); + video.controls = true; + let source1 = document.createElement('source'); + source1.src = mp4URL; + source1.type = 'video/mp4'; + let source2 = document.createElement('source'); + source2.src = webmURL; + source2.type = 'video/webm'; - ... -}</pre> - </li> -</ol> + ... + } + ``` -<h2 id="Stockage_hors-ligne_de_ressources">Stockage hors-ligne de ressources</h2> +## Stockage hors-ligne de ressources -<p>L'exemple ci-dessus montre comment créer une application qui stocke des ressources volumineuses dans une base de données IndexedDB, évitant ainsi de devoir les télécharger plus d'une fois. C'est déjà une grande amélioration pour l'expérience utilisateur, mais il manque encore une chose: les fichiers HTML, CSS, et JavaScript doivent encore être téléchargés à chaque fois que le site est accédé, ce qui veut dire qu'il ne fonctionnera pas lorsqu'il n'y a pas de connexion réseau</p> +L'exemple ci-dessus montre comment créer une application qui stocke des ressources volumineuses dans une base de données IndexedDB, évitant ainsi de devoir les télécharger plus d'une fois. C'est déjà une grande amélioration pour l'expérience utilisateur, mais il manque encore une chose: les fichiers HTML, CSS, et JavaScript doivent encore être téléchargés à chaque fois que le site est accédé, ce qui veut dire qu'il ne fonctionnera pas lorsqu'il n'y a pas de connexion réseau -<p><img alt="" src="ff-offline.png"></p> + -<p>C'est là qu'interviennet les <a href="/fr/docs/Web/API/Service_Worker_API">Service workers</a> et l'API étroitement liée, <a href="/fr/docs/Web/API/Cache">Cache</a>.</p> +C'est là qu'interviennet les [Service workers](/fr/docs/Web/API/Service_Worker_API) et l'API étroitement liée, [Cache](/fr/docs/Web/API/Cache). -<h3 id="Service_Worker_Cache">Service Worker / Cache</h3> +### Service Worker / Cache -<p>Un service worker est un fichier JavaScript qui, pour faire simple, est associé à une origine (un site web à un domaine donné) lorsque le navigateur y accède. Une fois associé, il peut contrôler les pages disponibles pour cette origine. Il le fait en s'installant entre la page chargée et le réseau, interceptant les requêtes réseau visant cette origine.</p> +Un service worker est un fichier JavaScript qui, pour faire simple, est associé à une origine (un site web à un domaine donné) lorsque le navigateur y accède. Une fois associé, il peut contrôler les pages disponibles pour cette origine. Il le fait en s'installant entre la page chargée et le réseau, interceptant les requêtes réseau visant cette origine. -<p>Quand le service worker intercepte une requête, il peut faire tout ce que vous voulez (voir quelques <a href="/fr/docs/Web/API/Service_Worker_API#Autres_id%C3%A9es_de_cas_d'utilisation">idées de cas d'utilisation</a>), mais l'exemple le plus classique est de sauvegarder les réponses réseau hors-ligne pour fournir ces réponses aux requêtes qui suivent au lieu d'utiliser le réseau. Ainsi, cela vous permet de faire fonctionner un site web complètement hors-ligne.</p> +Quand le service worker intercepte une requête, il peut faire tout ce que vous voulez (voir quelques [idées de cas d'utilisation](/fr/docs/Web/API/Service_Worker_API#Autres_id%C3%A9es_de_cas_d'utilisation)), mais l'exemple le plus classique est de sauvegarder les réponses réseau hors-ligne pour fournir ces réponses aux requêtes qui suivent au lieu d'utiliser le réseau. Ainsi, cela vous permet de faire fonctionner un site web complètement hors-ligne. -<p>L'API Cache est un autre mécanisme de stockage côté client, il a été conçu pour enregistrer les réponses HTTP et fonctionne donc très bien en synergie avec les service workers.</p> +L'API Cache est un autre mécanisme de stockage côté client, il a été conçu pour enregistrer les réponses HTTP et fonctionne donc très bien en synergie avec les service workers. -<div class="note"> -<p><strong>Note :</strong> Les Service workers et Cache sont pris en charge par la plupart des navigateurs modernes aujourd'hui. Au moment de la rédaction de cet article, Safari était encore occupé à l'implémenter, mais il devrait bientôt être disponible.</p> -</div> +> **Note :** Les Service workers et Cache sont pris en charge par la plupart des navigateurs modernes aujourd'hui. Au moment de la rédaction de cet article, Safari était encore occupé à l'implémenter, mais il devrait bientôt être disponible. -<h3 id="Un_exemple_service_worker">Un exemple service worker</h3> +### Un exemple service worker -<p>Voyons un exemple, pour vous donner une idée de ce à quoi cela pourrait ressembler. Nous avons crée une autre version de l'exemple video store vu précédemment. Cela fonctionne de manière identique, mais enregistre également le HTML, CSS, et JavaScript dans l'API Cache via un service worker, permettant à l'exemple de marcher hors ligne!</p> +Voyons un exemple, pour vous donner une idée de ce à quoi cela pourrait ressembler. Nous avons crée une autre version de l'exemple video store vu précédemment. Cela fonctionne de manière identique, mais enregistre également le HTML, CSS, et JavaScript dans l'API Cache via un service worker, permettant à l'exemple de marcher hors ligne! -<p>Voir <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/">IndexedDB video store avec service worker en direct</a>, ou <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/client-side-storage/cache-sw/video-store-offline">voir le code source</a>.</p> +Voir [IndexedDB video store avec service worker en direct](https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/), ou [voir le code source](https://github.com/mdn/learning-area/tree/master/javascript/apis/client-side-storage/cache-sw/video-store-offline). -<h3 id="Enregistrer_le_service_worker">Enregistrer le service worker</h3> +### Enregistrer le service worker -<p>La première chose à noter est qu'il a un peu plus de code placé dans le fichier JavaScript principal (voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.js#L144">index.js</a>):</p> +La première chose à noter est qu'il a un peu plus de code placé dans le fichier JavaScript principal (voir [index.js](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.js#L144)): -<pre class="brush: js">// Enregistre un service worker pour contrôler le site hors-ligne +```js +// Enregistre un service worker pour contrôler le site hors-ligne if('serviceWorker' in navigator) { navigator.serviceWorker .register('/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js') .then(function() { console.log('Service Worker Registered'); }); -}</pre> +} +``` -<ul> - <li>On effectue d'abord un test de détection de fonctionnalité pour vérifier si l'objet <code>serviceWorker</code> existe dans l'objet {{domxref("Navigator")}}. Si c'est le cas, alors on sait qu'au moins les fonctionnalités de base des service workers sont prises en charge.</li> - <li>On utilise la méthode {{domxref("ServiceWorkerContainer.register()")}} afin d'enregistrer le service worker <code>sw.js</code> pour l'origine où il se situe, ainsi il pourra contrôler les pages qui sont dans le même répertoire que lui, ou dans un sous-répertoire.</li> - <li>Lorsque la promesse est résolue, c'est que le service worker est enregistré.</li> -</ul> +- On effectue d'abord un test de détection de fonctionnalité pour vérifier si l'objet `serviceWorker` existe dans l'objet {{domxref("Navigator")}}. Si c'est le cas, alors on sait qu'au moins les fonctionnalités de base des service workers sont prises en charge. +- On utilise la méthode {{domxref("ServiceWorkerContainer.register()")}} afin d'enregistrer le service worker `sw.js` pour l'origine où il se situe, ainsi il pourra contrôler les pages qui sont dans le même répertoire que lui, ou dans un sous-répertoire. +- Lorsque la promesse est résolue, c'est que le service worker est enregistré. -<div class="note"> -<p><strong>Note :</strong> Le chemin du fichier <code>sw.js</code> est relatif à l'origine du site, et non au fichier JavaScript qui l'appelle.<br> - Le service worker est sur <code>https://mdn.github.io/learning-area/.../sw.js</code>. L'origine est <code>https://mdn.github.io</code>. Le chemin donné doit donc être <code>/learning-area/.../sw.js</code>.<br> - Si vous vouliez héberger cet exemple sur votre propre serveur, vous devriez changer le chemin en conséquence. C'est plutôt inhabituel, mais cela doit fonctionner de cette façon pour des raisons de sécurité.</p> -</div> +> **Note :** Le chemin du fichier `sw.js` est relatif à l'origine du site, et non au fichier JavaScript qui l'appelle. +> Le service worker est sur `https://mdn.github.io/learning-area/.../sw.js`. L'origine est `https://mdn.github.io`. Le chemin donné doit donc être `/learning-area/.../sw.js`. +> Si vous vouliez héberger cet exemple sur votre propre serveur, vous devriez changer le chemin en conséquence. C'est plutôt inhabituel, mais cela doit fonctionner de cette façon pour des raisons de sécurité. -<h3 id="Installer_le_service_worker">Installer le service worker</h3> +### Installer le service worker -<p>Quand une page sous le contrôle du service worker est appelée (par exemple lorsque l'exemple est rechargé), alors le service worker est installé par rapport à cette page et il peut commencer à la contrôler. Quand cela arrive, un événement <code>install</code> est déclenché sur le service worker; vous pouvez écrire du code dans le service worker pour qu'il réponde à cette installation.</p> +Quand une page sous le contrôle du service worker est appelée (par exemple lorsque l'exemple est rechargé), alors le service worker est installé par rapport à cette page et il peut commencer à la contrôler. Quand cela arrive, un événement `install` est déclenché sur le service worker; vous pouvez écrire du code dans le service worker pour qu'il réponde à cette installation. -<p>Prenons pour exemple le fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js">sw.js</a> (le service worker) :</p> +Prenons pour exemple le fichier [sw.js](https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js) (le service worker) : -<pre class="brush: js">self.addEventListener('install', function(e) { +```js +self.addEventListener('install', function(e) { e.waitUntil( caches.open('video-store').then(function(cache) { return cache.addAll([ @@ -791,92 +740,69 @@ if('serviceWorker' in navigator) { ]); }) ); -});</pre> +}); +``` -<ol> - <li> - <p>Le gestionnaire d'événément <code>install</code> est enregistré sur <code>self</code>. Le mot-clé <code>self</code> est un moyen de faire référence au service worker de la portée globale à partir de son fichier.</p> - </li> - <li> - <p>À l'intérieur du gestionnaire d'installation, on utilise la méthode {{domxref("ExtendableEvent.waitUntil()")}}, disponible sur l'objet événement, pour signaler que le navigateur ne doit pas terminer l'installation du service worker avant que la promesse qu'il contient ne soit résolue avec succès.</p> - </li> - <li> - <p>Ici, on voit l'API Cache en action: on utilise la méthode {{domxref("CacheStorage.open()")}} pour ouvrir un nouvel objet cache dans lequel les réponses seront stockées (similaire à un object store IndexedDB). Cette promesse se résout avec un objet {{domxref("Cache")}} représentant le cache du <code>video-store</code>.</p> - </li> - <li> - <p>On utilise la méthode {{domxref("Cache.addAll()")}} pour récupérer une série de ressources et ajouter leur réponse au cache.</p> - </li> -</ol> +1. Le gestionnaire d'événément `install` est enregistré sur `self`. Le mot-clé `self` est un moyen de faire référence au service worker de la portée globale à partir de son fichier. +2. À l'intérieur du gestionnaire d'installation, on utilise la méthode {{domxref("ExtendableEvent.waitUntil()")}}, disponible sur l'objet événement, pour signaler que le navigateur ne doit pas terminer l'installation du service worker avant que la promesse qu'il contient ne soit résolue avec succès. +3. Ici, on voit l'API Cache en action: on utilise la méthode {{domxref("CacheStorage.open()")}} pour ouvrir un nouvel objet cache dans lequel les réponses seront stockées (similaire à un object store IndexedDB). Cette promesse se résout avec un objet {{domxref("Cache")}} représentant le cache du `video-store`. +4. On utilise la méthode {{domxref("Cache.addAll()")}} pour récupérer une série de ressources et ajouter leur réponse au cache. -<p>C'est tout pour l'instant, l'installation est terminée.</p> +C'est tout pour l'instant, l'installation est terminée. -<h3 id="Répondre_aux_futures_requêtes">Répondre aux futures requêtes</h3> +### Répondre aux futures requêtes -<p>Avec le service worker enregistré et installé pour notre page HTML, et les ressources pertinentes ajoutées au cache, on est presque prêts. Il n'y a plus qu'une chose à faire: écrire du code pour répondre aux prochaines requêtes réseau.</p> +Avec le service worker enregistré et installé pour notre page HTML, et les ressources pertinentes ajoutées au cache, on est presque prêts. Il n'y a plus qu'une chose à faire: écrire du code pour répondre aux prochaines requêtes réseau. -<p>C'est ce que fait le second bloc de code dans <code>sw.js</code> :</p> +C'est ce que fait le second bloc de code dans `sw.js` : -<pre class="brush: js">self.addEventListener('fetch', function(e) { +```js +self.addEventListener('fetch', function(e) { console.log(e.request.url); e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); -});</pre> - -<ol> - <li> - <p>On ajoute un deuxième gestionnaire d'événement au service worker, qui exécute une fonction quand l'événement <code>fetch</code> est déclenché. Cela arrive quand le navigateur requête une ressource dans le même répertoire que le service worker (ou sous-répertoire).</p> - </li> - <li> - <p>À l'intérieur de cette fonction, on affiche l'URL de la ressource demandée dans la console, et on utilise la méthode {{domxref("FetchEvent.respondWith()")}} pour retourner une réponse personnalisée à la requête.</p> - </li> - <li> - <p>Pour construire la réponse, on utilise d'abord {{domxref("CacheStorage.match()")}} afin de vérifier si la requête est en cache (qu'une requête correspond à l'URL demandée est en cache).</p> - </li> - <li> - <p>Si elle est trouvée, la promesse se résout avec la réponse correspondante; sinon, avec <code>undefined</code>. Dans ce cas, on récupère la réponse à partir du réseau, en utilisant <code>fetch()</code>, et on retourne le résultat.</p> - </li> -</ol> - -<p>C'est tout pour notre service worker. Il y a tout un tas de choses que vous pouvez faire avec — pour plus de détails, consultez le <a href="https://serviceworke.rs/">service worker cookbook</a>. Et merci à Paul Kinlan pour son article <a href="https://developers.google.com/web/fundamentals/codelabs/offline/">Adding a Service Worker and Offline into your Web App</a>, qui a inspiré cet exemple.</p> - -<h3 id="Tester_lexemple_hors-ligne">Tester l'exemple hors-ligne</h3> - -<p>Pour tester notre <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/">exemple de service worker</a>, rechargez d'abord la page pour vous assurer qu'il est bien installé. Une fois que c'est fait, vous pouvez soit:</p> - -<ul> - <li>Débrancher votre réseau ou éteindre votre Wifi.</li> - <li>Si vous utilisez Firefox: Sélectionner <em>Fichier > Travailler hors-connexion</em>.</li> - <li>Si vous utilisez Chrome: Aller dans les DevTols, puis choisir <em>Application > Service Workers</em>, et cocher la case à cocher <em>Offline</em>.</li> -</ul> - -<p>Si vous actualisez votre page d'exemple, vous devriez toujours la voir se charger normalemment. Tout est stocké hors connexion — les ressources de la page dans Cache et les vidéos dans une base de données IndexedDB.</p> - -<h2 id="Sommaire">Sommaire</h2> - -<p>C'est tout pour l'instant. Nous espérons que vous avez trouvé notre récapitulatif des technologies de stockage côté client utile.</p> - -<h2 id="Voir_aussi">Voir aussi</h2> - -<ul> - <li><a href="/fr/docs/Web/API/Web_Storage_API">Web storage API</a></li> - <li><a href="/fr/docs/Web/API/API_IndexedDB">IndexedDB API</a></li> - <li><a href="/fr/docs/Web/HTTP/Cookies">Cookies</a></li> - <li><a href="/fr/docs/Web/API/Service_Worker_API">Service worker API</a></li> -</ul> - -<p>{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</p> - -<h2 id="Dans_ce_module">Dans ce module</h2> - -<ul> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul> +}); +``` + +1. On ajoute un deuxième gestionnaire d'événement au service worker, qui exécute une fonction quand l'événement `fetch` est déclenché. Cela arrive quand le navigateur requête une ressource dans le même répertoire que le service worker (ou sous-répertoire). +2. À l'intérieur de cette fonction, on affiche l'URL de la ressource demandée dans la console, et on utilise la méthode {{domxref("FetchEvent.respondWith()")}} pour retourner une réponse personnalisée à la requête. +3. Pour construire la réponse, on utilise d'abord {{domxref("CacheStorage.match()")}} afin de vérifier si la requête est en cache (qu'une requête correspond à l'URL demandée est en cache). +4. Si elle est trouvée, la promesse se résout avec la réponse correspondante; sinon, avec `undefined`. Dans ce cas, on récupère la réponse à partir du réseau, en utilisant `fetch()`, et on retourne le résultat. + +C'est tout pour notre service worker. Il y a tout un tas de choses que vous pouvez faire avec — pour plus de détails, consultez le [service worker cookbook](https://serviceworke.rs/). Et merci à Paul Kinlan pour son article [Adding a Service Worker and Offline into your Web App](https://developers.google.com/web/fundamentals/codelabs/offline/), qui a inspiré cet exemple. + +### Tester l'exemple hors-ligne + +Pour tester notre [exemple de service worker](https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/), rechargez d'abord la page pour vous assurer qu'il est bien installé. Une fois que c'est fait, vous pouvez soit: + +- Débrancher votre réseau ou éteindre votre Wifi. +- Si vous utilisez Firefox: Sélectionner _Fichier > Travailler hors-connexion_. +- Si vous utilisez Chrome: Aller dans les DevTols, puis choisir _Application > Service Workers_, et cocher la case à cocher _Offline_. + +Si vous actualisez votre page d'exemple, vous devriez toujours la voir se charger normalemment. Tout est stocké hors connexion — les ressources de la page dans Cache et les vidéos dans une base de données IndexedDB. + +## Sommaire + +C'est tout pour l'instant. Nous espérons que vous avez trouvé notre récapitulatif des technologies de stockage côté client utile. + +## Voir aussi + +- [Web storage API](/fr/docs/Web/API/Web_Storage_API) +- [IndexedDB API](/fr/docs/Web/API/API_IndexedDB) +- [Cookies](/fr/docs/Web/HTTP/Cookies) +- [Service worker API](/fr/docs/Web/API/Service_Worker_API) + +{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}} + +## Dans ce module + +- [Introduction aux API du Web](/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler des documents](/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data) +- [APIs tierces](/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des éléments graphiques](/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [APIs vidéo et audio](/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/client-side_web_apis/drawing_graphics/index.md b/files/fr/learn/javascript/client-side_web_apis/drawing_graphics/index.md index 95c9f7f8e4..0c6e51987c 100644 --- a/files/fr/learn/javascript/client-side_web_apis/drawing_graphics/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/drawing_graphics/index.md @@ -14,561 +14,525 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Drawing_graphics original_slug: Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics --- -<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}} -<p>Le navigateur contient des outils de programmation graphique très puissants, du langage <a href="/fr/docs/Web/SVG">SVG</a> (Scalable Vector Graphics), aux APIs pour dessiner sur les éléments HTML {{htmlelement("canvas")}}, (voir <a href="/fr/docs/Web/HTML/Canvas">API Canvas</a> et <a href="/fr/docs/Web/API/WebGL_API">WebGL</a>). Cet article fournit une introduction à canvas et introduit d'autres ressources pour vous permettre d'en apprendre plus.</p> +Le navigateur contient des outils de programmation graphique très puissants, du langage [SVG](/fr/docs/Web/SVG) (Scalable Vector Graphics), aux APIs pour dessiner sur les éléments HTML {{htmlelement("canvas")}}, (voir [API Canvas](/fr/docs/Web/HTML/Canvas) et [WebGL](/fr/docs/Web/API/WebGL_API)). Cet article fournit une introduction à canvas et introduit d'autres ressources pour vous permettre d'en apprendre plus. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis:</th> - <td>Bases de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, <a href="/fr/Apprendre/JavaScript/Building_blocks">les briques JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Objects">introduction aux objets</a>), les <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">notions de bases des APIs côté client</a></td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Apprendre les bases pour dessiner sur des éléments <code><canvas></code> en utilisant JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td> + Bases de JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, + <a href="/fr/Apprendre/JavaScript/Building_blocks" + >les briques JavaScript</a + >, + <a href="/fr/docs/Learn/JavaScript/Objects">introduction aux objets</a + >), les + <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction" + >notions de bases des APIs côté client</a + > + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td> + Apprendre les bases pour dessiner sur des éléments + <code><canvas></code> en utilisant JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Éléments_graphiques_sur_le_Web">Éléments graphiques sur le Web</h2> +## Éléments graphiques sur le Web -<p>Comme nous en avons parlé dans notre module HTML <a href="/fr/Apprendre/HTML/Multimedia_and_embedding">Multimédia et Intégration</a>, le web était à l'origine uniquement du texte, ce qui était très ennuyeux. Les images ont donc été introduites — d'abord via l'élément {{htmlelement("img")}} et plus tard via les propriétés CSS comme {{cssxref("background-image")}}, et <a href="/fr/docs/Web/SVG">SVG</a>.</p> +Comme nous en avons parlé dans notre module HTML [Multimédia et Intégration](/fr/Apprendre/HTML/Multimedia_and_embedding), le web était à l'origine uniquement du texte, ce qui était très ennuyeux. Les images ont donc été introduites — d'abord via l'élément {{htmlelement("img")}} et plus tard via les propriétés CSS comme {{cssxref("background-image")}}, et [SVG](/fr/docs/Web/SVG). -<p>Ce n'était cependant toujours pas assez. Tandis qu'il était possible d'utiliser <a href="/fr/Apprendre/CSS">CSS</a> et <a href="/fr/Apprendre/JavaScript">JavaScript</a> pour animer (ou manipuler) les images vectorielles SVG — puisqu'elles sont définies par le balisage — il n'y avait aucun moyen de faire de même pour les images bitmap, et les outils disponibles étaient plutôt limités. Le Web n'avait toujours pas de moyen efficace de créer des animations de jeux, des scènes 3D, et autres dispositions couramment traitées par les langages de bas niveau tels que C++ ou Java.</p> +Ce n'était cependant toujours pas assez. Tandis qu'il était possible d'utiliser [CSS](/fr/Apprendre/CSS) et [JavaScript](/fr/Apprendre/JavaScript) pour animer (ou manipuler) les images vectorielles SVG — puisqu'elles sont définies par le balisage — il n'y avait aucun moyen de faire de même pour les images bitmap, et les outils disponibles étaient plutôt limités. Le Web n'avait toujours pas de moyen efficace de créer des animations de jeux, des scènes 3D, et autres dispositions couramment traitées par les langages de bas niveau tels que C++ ou Java. -<p>La situation a commencé à s'améliorer quand les navigateurs ont commencé à prendre en charge l'élément {{htmlelement("canvas")}} et l' <a href="/fr/docs/Web/HTML/Canvas">API Canvas</a> associée — Apple l'a inventée vers 2004, et les autres navigateurs l'ont l'implémentée dans les années qui ont suivi. Comme vous le verrez dans cet article, canvas fournit de nombreux outils utiles à la création d'animation 2D, jeux, visualisations de données, et autres types d'application, particulièrement quand il est combiné à d'autres APIs que la plateforme web fournit.</p> +La situation a commencé à s'améliorer quand les navigateurs ont commencé à prendre en charge l'élément {{htmlelement("canvas")}} et l' [API Canvas](/fr/docs/Web/HTML/Canvas) associée — Apple l'a inventée vers 2004, et les autres navigateurs l'ont l'implémentée dans les années qui ont suivi. Comme vous le verrez dans cet article, canvas fournit de nombreux outils utiles à la création d'animation 2D, jeux, visualisations de données, et autres types d'application, particulièrement quand il est combiné à d'autres APIs que la plateforme web fournit. -<p>L'exemple ci-dessous montre une simple animation de balles qui rebondissent en canvas 2D, que nous avons déjà vue dans notre module <a href="/fr/docs/Learn/JavaScript/Objects/la_construction_d_objet_en_pratique">La construction d'objet en pratique</a>:</p> +L'exemple ci-dessous montre une simple animation de balles qui rebondissent en canvas 2D, que nous avons déjà vue dans notre module [La construction d'objet en pratique](/fr/docs/Learn/JavaScript/Objects/la_construction_d_objet_en_pratique): -<p>{{EmbedGHLiveSample("learning-area/javascript/oojs/bouncing-balls/index-finished.html", '100%', 500)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/oojs/bouncing-balls/index-finished.html", '100%', 500)}} -<p>Autour de 2006-2007, Mozilla a commencé à travailler sur une implémentation expérimentale de canvas 3D. C'est devenu <a href="/fr/Apprendre/WebGL">WebGL</a>, lequel a gagné en popularité parmi les fournisseurs de navigateur, et a été standardisé autour de 2009-2010. WebGL permet de créer de véritables graphiques 3D dans le navigateur web; l'exemple ci-dessous montre un simple cube WebGL qui tourne:</p> +Autour de 2006-2007, Mozilla a commencé à travailler sur une implémentation expérimentale de canvas 3D. C'est devenu [WebGL](/fr/Apprendre/WebGL), lequel a gagné en popularité parmi les fournisseurs de navigateur, et a été standardisé autour de 2009-2010. WebGL permet de créer de véritables graphiques 3D dans le navigateur web; l'exemple ci-dessous montre un simple cube WebGL qui tourne: -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}} -<p>Cet article se concentrera principalement sur les canvas 2D, car le code WebGL brut est très complexe. Nous montrerons cependant comment utiliser une bibliothèque WebGL pour créer une scène 3D plus facilement, et vous pourrez par la suite suivre le tutoriel <a href="/fr/Apprendre/WebGL">WebGL</a>, qui couvre le code WebGL brut.</p> +Cet article se concentrera principalement sur les canvas 2D, car le code WebGL brut est très complexe. Nous montrerons cependant comment utiliser une bibliothèque WebGL pour créer une scène 3D plus facilement, et vous pourrez par la suite suivre le tutoriel [WebGL](/fr/Apprendre/WebGL), qui couvre le code WebGL brut. -<div class="note"> -<p><strong>Note :</strong> Canvas est très bien pris en charge parmi les différents navigateurs, à l'exception de IE 8 (et inférieur) pour les canvas 2D, et IE 11 (et inférieur) pour WebGL.</p> -</div> +> **Note :** Canvas est très bien pris en charge parmi les différents navigateurs, à l'exception de IE 8 (et inférieur) pour les canvas 2D, et IE 11 (et inférieur) pour WebGL. -<h2 id="Apprentissage_actif_Débuter_avec_un_<canvas>">Apprentissage actif: Débuter avec un <canvas></h2> +## Apprentissage actif: Débuter avec un \<canvas> -<p>Si vous voulez créer une scène 2D ou 3D sur une page web, vous devez commencer avec un élément HTML {{htmlelement("canvas")}}. Cet élément est utilisé pour définir la zone de la page où l'image sera dessinée. C'est aussi simple que d'inclure l'élément dans la page:</p> +Si vous voulez créer une scène 2D ou 3D sur une page web, vous devez commencer avec un élément HTML {{htmlelement("canvas")}}. Cet élément est utilisé pour définir la zone de la page où l'image sera dessinée. C'est aussi simple que d'inclure l'élément dans la page: -<pre class="brush: html"><canvas width="320" height="240"></canvas></pre> +```html +<canvas width="320" height="240"></canvas> +``` -<p>Cela va créer un canvas sur la page d'une taille de 320 pixels par 240.</p> +Cela va créer un canvas sur la page d'une taille de 320 pixels par 240. -<p>À l'intérieur des balises du canvas, vous pouvez mettre du contenu alternatif, qui est affiché si le navigateur de l'utilisateur ne prend pas en charge les canvas.</p> +À l'intérieur des balises du canvas, vous pouvez mettre du contenu alternatif, qui est affiché si le navigateur de l'utilisateur ne prend pas en charge les canvas. -<pre class="brush: html"><canvas width="320" height="240"> - <p>Votre navigateur ne prend pas en charge canvas. Boo hoo!</p> -</canvas></pre> +```html +<canvas width="320" height="240"> + <p>Votre navigateur ne prend pas en charge canvas. Boo hoo!</p> +</canvas> +``` -<p>Bien sûr, le message ci-dessus est vraiment inutile! Dans un exemple réel, vous voudriez plutôt associer le contenu alternatif au contenu du canvas. Par exemple, si vous voulez afficher un graphique en temps réel des cours boursiers, le contenu alternatif pourrait être une image statique du dernier graphique, avec un texte indiquant quels sont les prix.</p> +Bien sûr, le message ci-dessus est vraiment inutile! Dans un exemple réel, vous voudriez plutôt associer le contenu alternatif au contenu du canvas. Par exemple, si vous voulez afficher un graphique en temps réel des cours boursiers, le contenu alternatif pourrait être une image statique du dernier graphique, avec un texte indiquant quels sont les prix. -<h3 id="Crée_et_dimensionner_notre_canvas">Crée et dimensionner notre canvas</h3> +### Crée et dimensionner notre canvas -<p>Commençons par créer notre propre canvas, que nous utiliserons pour dessiner nos futures expériences.</p> +Commençons par créer notre propre canvas, que nous utiliserons pour dessiner nos futures expériences. -<ol> - <li> - <p>Premièrement, copiez localement notre fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/0_canvas_start.html">0_canvas_start.html</a>, et ouvez-le dans votre éditeur de texte.</p> - </li> - <li> - <p>Ajoutez le code suivant à l'intérieur, juste après la balise {{htmlelement("body")}} ouvrante:</p> +1. Premièrement, copiez localement notre fichier [0_canvas_start.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/0_canvas_start.html), et ouvez-le dans votre éditeur de texte. +2. Ajoutez le code suivant à l'intérieur, juste après la balise {{htmlelement("body")}} ouvrante: - <pre class="brush: html"><canvas class="myCanvas"> - <p>Ajouter un contenu alternatif approprié ici.</p> -</canvas></pre> + ```html + <canvas class="myCanvas"> + <p>Ajouter un contenu alternatif approprié ici.</p> + </canvas> + ``` - <p>Nous avons ajouté un attribut <code>class</code> à l'élément <code><canvas></code> pour que ce soit plus facile à sélectionner dans le cas où nous aurions plusieurs canvas sur la page. Et nous avons supprimé les attributs <code>width</code> et <code>height</code> pour le moment (vous pouvez les remettre si vous le voulez mais nous les définirons en utilisant JavaScript dans une section plus bas). Les canvas sans hauteur et largeur explicites sont définits par défaut à 300 pixels par 150.</p> - </li> - <li> - <p>Maintenant, ajoutez les lignes suivantes à l'intérieur de l'élément {{htmlelement("script")}}:</p> + Nous avons ajouté un attribut `class` à l'élément `<canvas>` pour que ce soit plus facile à sélectionner dans le cas où nous aurions plusieurs canvas sur la page. Et nous avons supprimé les attributs `width` et `height` pour le moment (vous pouvez les remettre si vous le voulez mais nous les définirons en utilisant JavaScript dans une section plus bas). Les canvas sans hauteur et largeur explicites sont définits par défaut à 300 pixels par 150. - <pre class="brush: js">var canvas = document.querySelector('.myCanvas'); -var width = canvas.width = window.innerWidth; -var height = canvas.height = window.innerHeight;</pre> +3. Maintenant, ajoutez les lignes suivantes à l'intérieur de l'élément {{htmlelement("script")}}: - <p>Ici, nous avons stocké une référence vers le canvas dans la variable <code>canvas</code>. Sur la deuxième ligne, nous affectons à la fois une nouvelle variable <code>width</code> et la propriété <code>width</code> du canvas à {{domxref("Window.innerWidth")}} (ce qui nous donne la largeur de la fenêtre). Sur la troisième ligne, nos affectons à la fois une nouvelle variable <code>height</code> et la propriété <code>height</code> du canvas à {{domxref("Window.innerHeight")}} (ce qui nous donne la hauteur de la fenêtre). Nous avons donc un canvas qui remplit toute la largeur et hauteur de la fenêtre!</p> + ```js + var canvas = document.querySelector('.myCanvas'); + var width = canvas.width = window.innerWidth; + var height = canvas.height = window.innerHeight; + ``` - <p>Vous avez également vu que nous avons chaîné les assignations ensemble avec plusieurs signes égal — ce qui est autorié en JavaScript, et c'est une bonne technique si vous voulez que plusieurs variables aient la même valeur. Nous avons gardé la hauteur et largeur du canvas facilement accessibles dans les variables width/height, ces valeurs seront utiles plus tard (par exemple, si vous voulez dessiner quelque chose exactement à mi-chemin de la largeur du canvas).</p> - </li> - <li> - <p>Si vous sauvegardez et chargez votre exemple dans le navigateur maintenant, vous ne verrez rien, ce qui est normal, mais vous verrez également des barres de défilement, ce qui est un problème pour nous. Cela se produit parce que l'élément {{htmlelement("body")}} a des {{cssxref("margin")}} qui, ajoutées à la taille du canvas, résulte en un document qui est plus large que la fenêtre. Pour se débarasser des barres de défilement, nous devons supprimer les {{cssxref("margin")}} et aussi définir {{cssxref("overflow")}} à <code>hidden</code>. Ajoutez ce qui suit à l'intérieur du {{htmlelement("head")}} du document:</p> + Ici, nous avons stocké une référence vers le canvas dans la variable `canvas`. Sur la deuxième ligne, nous affectons à la fois une nouvelle variable `width` et la propriété `width` du canvas à {{domxref("Window.innerWidth")}} (ce qui nous donne la largeur de la fenêtre). Sur la troisième ligne, nos affectons à la fois une nouvelle variable `height` et la propriété `height` du canvas à {{domxref("Window.innerHeight")}} (ce qui nous donne la hauteur de la fenêtre). Nous avons donc un canvas qui remplit toute la largeur et hauteur de la fenêtre! - <pre class="brush: html"><style> - body { - margin: 0; - overflow: hidden; - } -</style></pre> + Vous avez également vu que nous avons chaîné les assignations ensemble avec plusieurs signes égal — ce qui est autorié en JavaScript, et c'est une bonne technique si vous voulez que plusieurs variables aient la même valeur. Nous avons gardé la hauteur et largeur du canvas facilement accessibles dans les variables width/height, ces valeurs seront utiles plus tard (par exemple, si vous voulez dessiner quelque chose exactement à mi-chemin de la largeur du canvas). + +4. Si vous sauvegardez et chargez votre exemple dans le navigateur maintenant, vous ne verrez rien, ce qui est normal, mais vous verrez également des barres de défilement, ce qui est un problème pour nous. Cela se produit parce que l'élément {{htmlelement("body")}} a des {{cssxref("margin")}} qui, ajoutées à la taille du canvas, résulte en un document qui est plus large que la fenêtre. Pour se débarasser des barres de défilement, nous devons supprimer les {{cssxref("margin")}} et aussi définir {{cssxref("overflow")}} à `hidden`. Ajoutez ce qui suit à l'intérieur du {{htmlelement("head")}} du document: + + ```html + <style> + body { + margin: 0; + overflow: hidden; + } + </style> + ``` + + Les barres de défilement ne devraient plus être là. + +> **Note :** Vous devrez généralement définir la taille de l'image en utilisant les attributs HTML ou les propriétéss DOM, comme expliqué ci-dessus. Vous pourriez théoriquement utiliser CSS, le problème étant que le dimensionnement le canvas est alors effectué après que le contenu canvas n'ait été calculé, et comme toute autre image (puisque le canvas une fois affiché n'est plus qu'une simple image), elle peut devenir pixelisée/déformée. - <p>Les barres de défilement ne devraient plus être là.</p> - </li> -</ol> +### Obtenir le contexte du canvas et configuration finale -<div class="note"> -<p><strong>Note :</strong> Vous devrez généralement définir la taille de l'image en utilisant les attributs HTML ou les propriétéss DOM, comme expliqué ci-dessus. Vous pourriez théoriquement utiliser CSS, le problème étant que le dimensionnement le canvas est alors effectué après que le contenu canvas n'ait été calculé, et comme toute autre image (puisque le canvas une fois affiché n'est plus qu'une simple image), elle peut devenir pixelisée/déformée.</p> -</div> +Nous devons faire une dernière chose avant de considérer notre template finit. Pour dessiner sur le canvas, nous devons récupérer une référence à la zone de dessin, appelé un _contexte_. Pour ce faire, on utilise la méthode {{domxref("HTMLCanvasElement.getContext()")}}, qui, pour un usage basique ne prend qu'un seul paramètre, spécifiant quel type de contexte nous voulons récupérer. -<h3 id="Obtenir_le_contexte_du_canvas_et_configuration_finale">Obtenir le contexte du canvas et configuration finale</h3> +En l'occurence, nous voulons un canvas 2D, alors ajoutez le JavaScript suivant à la suite des autres instructions à l'intérieur de l'élément `<script>`: -<p>Nous devons faire une dernière chose avant de considérer notre template finit. Pour dessiner sur le canvas, nous devons récupérer une référence à la zone de dessin, appelé un <em>contexte</em>. Pour ce faire, on utilise la méthode {{domxref("HTMLCanvasElement.getContext()")}}, qui, pour un usage basique ne prend qu'un seul paramètre, spécifiant quel type de contexte nous voulons récupérer.</p> +```js +var ctx = canvas.getContext('2d'); +``` -<p>En l'occurence, nous voulons un canvas 2D, alors ajoutez le JavaScript suivant à la suite des autres instructions à l'intérieur de l'élément <code><script></code>:</p> +> **Note :** Vous pouvez choisir d'autres types de contexte comme `webgl` pour WebGL, `webgl2` pour WebGL 2, etc., mais nous n'en aurons pas besoin dans cet article. -<pre class="brush: js">var ctx = canvas.getContext('2d');</pre> +Voilà — notre canvas est maintenant préparé et prêt à être dessiné! La variable `ctx` contient désormais un objet {{domxref("CanvasRenderingContext2D")}}, et toutes les opérations de dessin sur le canvas impliqueront de manipuler cet objet. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez choisir d'autres types de contexte comme <code>webgl</code> pour WebGL, <code>webgl2</code> pour WebGL 2, etc., mais nous n'en aurons pas besoin dans cet article.</p> -</div> +Faisons une dernière chose avant de passer à autre chose. Nous allons colorier l'arrière-plan du canvas en noir, cela vous donnera un avant-goût de l'API canvas. Ajoutez les lignes suivantes au bas de votre JavaScript: -<p>Voilà — notre canvas est maintenant préparé et prêt à être dessiné! La variable <code>ctx</code> contient désormais un objet {{domxref("CanvasRenderingContext2D")}}, et toutes les opérations de dessin sur le canvas impliqueront de manipuler cet objet.</p> +```js +ctx.fillStyle = 'rgb(0, 0, 0)'; +ctx.fillRect(0, 0, width, height); +``` -<p>Faisons une dernière chose avant de passer à autre chose. Nous allons colorier l'arrière-plan du canvas en noir, cela vous donnera un avant-goût de l'API canvas. Ajoutez les lignes suivantes au bas de votre JavaScript:</p> +Ici nous définissons une couleur de remplissage en utilisant la propriété du canvas {{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle")}} (qui prend une [valeur de couleur](/fr/Apprendre/CSS/Introduction_à_CSS/Values_and_units#Couleurs) tout comme les propriétés CSS), puis nous dessinons un rectangle qui recouvre intégralement la surface du canvas avec la méthode {{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}} (les deux premiers paramètres sont les coordonnées du coin supérieur gauche du rectangle; les deux derniers sont la largeur et la hauteur du rectangle que vous voulez dessiner — on vous avait dit que ces variables `width` et `height` allaient être utiles)! -<pre class="brush: js">ctx.fillStyle = 'rgb(0, 0, 0)'; -ctx.fillRect(0, 0, width, height);</pre> +OK, notre template est prêt et il est temps de passer à autre chose. -<p>Ici nous définissons une couleur de remplissage en utilisant la propriété du canvas {{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle")}} (qui prend une <a href="/fr/Apprendre/CSS/Introduction_à_CSS/Values_and_units#Couleurs">valeur de couleur</a> tout comme les propriétés CSS), puis nous dessinons un rectangle qui recouvre intégralement la surface du canvas avec la méthode {{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}} (les deux premiers paramètres sont les coordonnées du coin supérieur gauche du rectangle; les deux derniers sont la largeur et la hauteur du rectangle que vous voulez dessiner — on vous avait dit que ces variables <code>width</code> et <code>height</code> allaient être utiles)!</p> +## Les bases du canvas 2D -<p>OK, notre template est prêt et il est temps de passer à autre chose.</p> +Pour rappel, toutes les opération de dessin sont effectuées en manipulant un objet {{domxref("CanvasRenderingContext2D")}} (dans notre cas, `ctx`). -<h2 id="Les_bases_du_canvas_2D">Les bases du canvas 2D</h2> +De nombreuses opérations doivent recevoir des coordonnées en entrée pour savoir où dessiner quelque chose — le coin supérieur gauche du canvas est le point (0, 0), l'axe horizontal (x) va de gauche à droite, et l'axe vertical (y) va de haut en bas. -<p>Pour rappel, toutes les opération de dessin sont effectuées en manipulant un objet {{domxref("CanvasRenderingContext2D")}} (dans notre cas, <code>ctx</code>).</p> + -<p>De nombreuses opérations doivent recevoir des coordonnées en entrée pour savoir où dessiner quelque chose — le coin supérieur gauche du canvas est le point (0, 0), l'axe horizontal (x) va de gauche à droite, et l'axe vertical (y) va de haut en bas.</p> +Dessiner des formes est souvent fait en utilisant la forme rectangle, ou alors en traçant une ligne le long d'un certain chemin puis en remplissant la forme. Nous allons vous montrer ci-dessous comment faire ces deux choses. -<p><img alt="" src="Canvas_default_grid.png"></p> +### Rectangles simples -<p>Dessiner des formes est souvent fait en utilisant la forme rectangle, ou alors en traçant une ligne le long d'un certain chemin puis en remplissant la forme. Nous allons vous montrer ci-dessous comment faire ces deux choses.</p> +Commençons avec quelques rectangles simples. -<h3 id="Rectangles_simples">Rectangles simples</h3> +1. Tout d'abord, faites une copie de votre template (ou copiez localement le fichier [1_canvas_template.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html) si vous n'avez pas suivit les étapes précédentes). +2. Ensuite, ajoutez les lignes suivantes au bas de votre JavaScript: -<p>Commençons avec quelques rectangles simples.</p> + ```js + ctx.fillStyle = 'rgb(255, 0, 0)'; + ctx.fillRect(50, 50, 100, 150); + ``` -<ol> - <li> - <p>Tout d'abord, faites une copie de votre template (ou copiez localement le fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html">1_canvas_template.html</a> si vous n'avez pas suivit les étapes précédentes).</p> - </li> - <li> - <p>Ensuite, ajoutez les lignes suivantes au bas de votre JavaScript:</p> + Si vous sauvegardez votre code et rafraichissez la page, vous devriez voir qu'un rectangle rouge est apparu sur le canvas. Son coin supérieur gauche est à (50,50) pixels du coin supérieur gauche du canvas (comme définit par les deux premiers paramètres), il a une largeur de 100 pixels et une hauteur de 150 pixels (comme définit par les paramètres 3 et 4). - <pre class="brush: js">ctx.fillStyle = 'rgb(255, 0, 0)'; -ctx.fillRect(50, 50, 100, 150);</pre> +3. Ajoutons un autre rectangle dans le mix — un vert cette fois. Ajoutez ce qui suit au bas de votre JavaScript: - <p>Si vous sauvegardez votre code et rafraichissez la page, vous devriez voir qu'un rectangle rouge est apparu sur le canvas. Son coin supérieur gauche est à (50,50) pixels du coin supérieur gauche du canvas (comme définit par les deux premiers paramètres), il a une largeur de 100 pixels et une hauteur de 150 pixels (comme définit par les paramètres 3 et 4).</p> - </li> - <li> - <p>Ajoutons un autre rectangle dans le mix — un vert cette fois. Ajoutez ce qui suit au bas de votre JavaScript:</p> + ```js + ctx.fillStyle = 'rgb(0, 255, 0)'; + ctx.fillRect(75, 75, 100, 100); + ``` - <pre class="brush: js">ctx.fillStyle = 'rgb(0, 255, 0)'; -ctx.fillRect(75, 75, 100, 100);</pre> + Sauvegardez et rafraichissez, et vous verrez un nouveau rectangle. Cela soulève un point important: les opérations graphiques comme dessiner des rectangles, lignes, et autres, sont executées dans l'ordre dans lequel elle apparaissent dans le code. Pensez-y comme peindre un mur, chaque couche de peinture s'ajoute par dessus les anciennes et peuvent même mettre cacher ce qu'il y a en dessous. Vous ne pouvez rien y faire, il faut donc réfléchir soigneusement à l'ordre dans lequel vous allez dessiner les éléments graphiques. - <p>Sauvegardez et rafraichissez, et vous verrez un nouveau rectangle. Cela soulève un point important: les opérations graphiques comme dessiner des rectangles, lignes, et autres, sont executées dans l'ordre dans lequel elle apparaissent dans le code. Pensez-y comme peindre un mur, chaque couche de peinture s'ajoute par dessus les anciennes et peuvent même mettre cacher ce qu'il y a en dessous. Vous ne pouvez rien y faire, il faut donc réfléchir soigneusement à l'ordre dans lequel vous allez dessiner les éléments graphiques.</p> - </li> - <li> - <p>Notez que vous pouvez dessiner des éléments graphiques semi-transparents en spécifiant une couleur semi-transparente, par exemple en utilisant <code>rgba()</code>. La valeur <code>a</code> définit ce qu'on appelle le "canal alpha", ou la quantité de transparence de la couleur. Plus la valeur de <code>a</code> est élevée, plus la couleur est opaque. Ajoutez ce qui suit à votre code:</p> +4. Notez que vous pouvez dessiner des éléments graphiques semi-transparents en spécifiant une couleur semi-transparente, par exemple en utilisant `rgba()`. La valeur `a` définit ce qu'on appelle le "canal alpha", ou la quantité de transparence de la couleur. Plus la valeur de `a` est élevée, plus la couleur est opaque. Ajoutez ce qui suit à votre code: - <pre class="brush: js">ctx.fillStyle = 'rgba(255, 0, 255, 0.75)'; -ctx.fillRect(25, 100, 175, 50);</pre> - </li> - <li> - <p>Maintenant essayez de dessiner plus de rectangles par vous-même; amusez-vous!</p> - </li> -</ol> + ```js + ctx.fillStyle = 'rgba(255, 0, 255, 0.75)'; + ctx.fillRect(25, 100, 175, 50); + ``` -<h3 id="Traits_et_épaisseurs_de_ligne">Traits et épaisseurs de ligne</h3> +5. Maintenant essayez de dessiner plus de rectangles par vous-même; amusez-vous! -<p>Jusqu'à présent nous avons vu comment dessiner des rectangles pleins, mais on peut aussi ne dessiner que les contours (dit <strong>strokes</strong> - traits - en graphic design). Pour définir la couleur que vous voulez pour le contour, utilisez la propriété {{domxref("CanvasRenderingContext2D.strokeStyle", "strokeStyle")}}. Pour dessiner le contour du rectangle, on appelle {{domxref("CanvasRenderingContext2D.strokeRect", "strokeRect")}}.</p> +### Traits et épaisseurs de ligne -<ol> - <li> - <p>Ajoutez ce qui suit au bas de votre JavaScript:</p> +Jusqu'à présent nous avons vu comment dessiner des rectangles pleins, mais on peut aussi ne dessiner que les contours (dit **strokes** - traits - en graphic design). Pour définir la couleur que vous voulez pour le contour, utilisez la propriété {{domxref("CanvasRenderingContext2D.strokeStyle", "strokeStyle")}}. Pour dessiner le contour du rectangle, on appelle {{domxref("CanvasRenderingContext2D.strokeRect", "strokeRect")}}. - <pre class="brush: js">ctx.strokeStyle = 'rgb(255, 255, 255)'; -ctx.strokeRect(25, 25, 175, 200);</pre> - </li> - <li> - <p>L'épaisseur de trait par défaut est de 1 pixel; vous pouvez ajuster la valeur de la propriété {{domxref("CanvasRenderingContext2D.lineWidth", "lineWidth")}} pour changer ça (prend un nombre spécifiant le nombre de pixels d'épaisseur de trait). Ajoutez la ligne suivante entre les deux lignes précédentes:</p> +1. Ajoutez ce qui suit au bas de votre JavaScript: - <pre class="brush: js">ctx.lineWidth = 5;</pre> + ```js + ctx.strokeStyle = 'rgb(255, 255, 255)'; + ctx.strokeRect(25, 25, 175, 200); + ``` - <p>Vous devriez maintenant voir que votre contour blanc est devenu beaucoup plus épais!</p> - </li> -</ol> +2. L'épaisseur de trait par défaut est de 1 pixel; vous pouvez ajuster la valeur de la propriété {{domxref("CanvasRenderingContext2D.lineWidth", "lineWidth")}} pour changer ça (prend un nombre spécifiant le nombre de pixels d'épaisseur de trait). Ajoutez la ligne suivante entre les deux lignes précédentes: -<p>C'est tout pour le moment. À ce stade votre exemple devrait ressembler à ça:</p> + ```js + ctx.lineWidth = 5; + ``` -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/2_canvas_rectangles.html", '100%', 250)}}</p> + Vous devriez maintenant voir que votre contour blanc est devenu beaucoup plus épais! -<div class="note"> -<p><strong>Note :</strong> Le code terminé est disponible sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/2_canvas_rectangles.html">2_canvas_rectangles.html</a>.</p> -</div> +C'est tout pour le moment. À ce stade votre exemple devrait ressembler à ça: -<h3 id="Dessiner_des_chemins">Dessiner des chemins</h3> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/2_canvas_rectangles.html", '100%', 250)}} -<p>Si vous voulez dessiner quelque chose de plus complexe qu'un rectangle, vous allez certainement devoir utiliser un <em>path</em> (chemin). En gros, cela implique de spécifier exactement où déplacer un stylo sur le canvas pour tracer la forme que vous voulez. L'API Canvas inclut des fonctions pour dessiner des lignes droites, des cercles, des courbes Bézier, et plus encore.</p> +> **Note :** Le code terminé est disponible sur GitHub, [2_canvas_rectangles.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/2_canvas_rectangles.html). -<p>Commençons la section en faisant une nouvelle copie de notre template (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html">1_canvas_template.html</a>), dans lequel nous allons dessiner le nouvel exemple.</p> +### Dessiner des chemins -<p>Nous allons utiliser quelques méthodes et propriétés communes dans les sections suivantes:</p> +Si vous voulez dessiner quelque chose de plus complexe qu'un rectangle, vous allez certainement devoir utiliser un _path_ (chemin). En gros, cela implique de spécifier exactement où déplacer un stylo sur le canvas pour tracer la forme que vous voulez. L'API Canvas inclut des fonctions pour dessiner des lignes droites, des cercles, des courbes Bézier, et plus encore. -<ul> - <li>{{domxref("CanvasRenderingContext2D.beginPath", "beginPath()")}} — commence à dessiner un path au point où le stylo se situe sur le canvas. Sur un nouveau canvas, le stylo commence au point (0, 0).</li> - <li>{{domxref("CanvasRenderingContext2D.moveTo", "moveTo()")}} — déplace le stylo à un point différent sur le canvas, sans tracer de ligne; le stylo "saute" simplement à une nouvelle position.</li> - <li>{{domxref("CanvasRenderingContext2D.fill", "fill()")}} — dessine une forme en remplissant le path définit jusqu'à présent.</li> - <li>{{domxref("CanvasRenderingContext2D.stroke", "stroke()")}} — dessine un trait en suivant le path définit jusqu'à présent.</li> - <li>Vous pouvez utiliser les fonctionnalités telles que <code>lineWidth</code> et <code>fillStyle</code>/<code>strokeStyle</code> avec les paths aussi bien qu'avec les rectangles.</li> -</ul> +Commençons la section en faisant une nouvelle copie de notre template ([1_canvas_template.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html)), dans lequel nous allons dessiner le nouvel exemple. -<p>Typiquement, une manière de dessiner un trait simple ressemblerait à ça:</p> +Nous allons utiliser quelques méthodes et propriétés communes dans les sections suivantes: -<pre class="brush: js">ctx.fillStyle = 'rgb(255, 0, 0)'; +- {{domxref("CanvasRenderingContext2D.beginPath", "beginPath()")}} — commence à dessiner un path au point où le stylo se situe sur le canvas. Sur un nouveau canvas, le stylo commence au point (0, 0). +- {{domxref("CanvasRenderingContext2D.moveTo", "moveTo()")}} — déplace le stylo à un point différent sur le canvas, sans tracer de ligne; le stylo "saute" simplement à une nouvelle position. +- {{domxref("CanvasRenderingContext2D.fill", "fill()")}} — dessine une forme en remplissant le path définit jusqu'à présent. +- {{domxref("CanvasRenderingContext2D.stroke", "stroke()")}} — dessine un trait en suivant le path définit jusqu'à présent. +- Vous pouvez utiliser les fonctionnalités telles que `lineWidth` et `fillStyle`/`strokeStyle` avec les paths aussi bien qu'avec les rectangles. + +Typiquement, une manière de dessiner un trait simple ressemblerait à ça: + +```js +ctx.fillStyle = 'rgb(255, 0, 0)'; ctx.beginPath(); ctx.moveTo(50, 50); // tracer le trait -ctx.fill();</pre> +ctx.fill(); +``` -<h4 id="Dessiner_des_lignes">Dessiner des lignes</h4> +#### Dessiner des lignes -<p>Dessinons un triangle équilatéral sur le canvas.</p> +Dessinons un triangle équilatéral sur le canvas. -<ol> - <li> - <p>Tout d'abord, ajoutez la fonction d'aide suivante au bas de votre code. Elle convertit des valeurs en degrés en radians, ce qui est utile car chaque fois que vous devez fournir une valeur d'angle en JavaScript, ce sera presque toujours en radians, tandis que les humains pensent généralement en degrés.</p> +1. Tout d'abord, ajoutez la fonction d'aide suivante au bas de votre code. Elle convertit des valeurs en degrés en radians, ce qui est utile car chaque fois que vous devez fournir une valeur d'angle en JavaScript, ce sera presque toujours en radians, tandis que les humains pensent généralement en degrés. - <pre class="brush: js">function degToRad(degrees) { - return degrees * Math.PI / 180; -};</pre> - </li> - <li> - <p>Ensuite, commencez votre path en ajoutant ce qui suit au bas de votre JavaScript. Ici, nous définissons une couleur pour notre triangle et déplaçons le stylo au point (50, 50) sans rien tracer. C'est à partir de là que nous allons dessiner notre triangle.</p> + ```js + function degToRad(degrees) { + return degrees * Math.PI / 180; + }; + ``` - <pre class="brush: js">ctx.fillStyle = 'rgb(255, 0, 0)'; -ctx.beginPath(); -ctx.moveTo(50, 50);</pre> - </li> - <li> - <p>Maintenant ajoutez le bloc de code suivant:</p> - - <pre class="brush: js">ctx.lineTo(150, 50); -var triHeight = 50 * Math.tan(degToRad(60)); -ctx.lineTo(100, 50+triHeight); -ctx.lineTo(50, 50); -ctx.fill();</pre> - - <p>Parcourons ceci dans l'ordre:</p> - - <ol> - <li> - <p>D'abord nous ajoutons une ligne vers (150, 50) — notre path va maintenant 100 pixels vers la droite le long de l'axe horizontal (x).</p> - </li> - <li> - <p>Puis, nous calculons la hauteur de notre triangle équilatéral, en utilisant un peu de trigonométrie simple. Nous dessinons un triangle pointant vers le bas.</p> - - <p>Les angles d'un triangle équilatéral sont tous de 60 degrés. Pour calculer la hauteur, nous pouvons séparer le triangle en deux triangles rectangles par le milieu, qui auront alors des angles de 90, 60 et 30 degrés.</p> - - <p>Pour ce qui est des côtés:</p> - - <ul> - <li>Le côté le plus long est appelé l'<strong>hypoténuse</strong></li> - <li>Le côté relié à l'angle de 60 degrés (et qui n'est pas l'hypothénuse) est dit <strong>adjacent</strong> à cet angle — sa longueur est de 50 pixels puisque c'est la moitié de la ligne que nous avons dessiné.</li> - <li>Le côté opposé à l'angle de 60 degrés est dit <strong>opposé</strong> à cet angle — c'est la hauteur que nous voulons calculer.</li> - </ul> - - <p> </p> - - <p><img alt="" src="trigonometry.png"></p> - - <p>Une des formule trigonométrique de base stipule que la longueur du côté adjacent mutiplié par la tangente de l'angle est égale à l'opposé, soit <code>50 * Math.tan(degToRad(60))</code>. Nous utilisons notre fonction <code>degToRad()</code> pour convertir 60 degrés en radians, puisque {{jsxref("Math.tan()")}} attend une valeur en radians.</p> - </li> - <li> - <p>Avec la hauteur calculée, nous ajoutons une nouvelle ligne vers <code>(100, 50+triHeight)</code>. La coordonnée X est simple, elle est à mi-chemin de la ligne que nous avons tracé. La valeur de Y d'autre part doit être de 50 plus la hauteur du triangle, puisque le haut du triangle est à 50 pixels du haut du canvas.</p> - </li> - <li> - <p>L'instruction qui suit ajoute une ligne vers le point de départ du triangle.</p> - </li> - <li> - <p>Pour finir, nous appelons <code>ctx.fill()</code> pour finir le path et remplir la forme.</p> - </li> - </ol> - </li> -</ol> - -<h4 id="Dessiner_des_cercles">Dessiner des cercles</h4> - -<p>Maintenant, voyons comment dessiner un cercle sur le canvas. Pour ce faire, on utilise la méthode {{domxref("CanvasRenderingContext2D.arc", "arc()")}}, qui dessine tout ou une portion de cercle à un point spécifié.</p> - -<ol> - <li> - <p>Ajoutons un arc à notre canvas en ajoutant le code qui suit:</p> - - <pre class="brush: js">ctx.fillStyle = 'rgb(0, 0, 255)'; -ctx.beginPath(); -ctx.arc(150, 106, 50, degToRad(0), degToRad(360), false); -ctx.fill();</pre> - - <p><code>arc()</code> prend six paramètres.</p> - - <ul> - <li>Les deux premiers spécifient la position du centre du cercle (X et Y respectivement).</li> - <li>Le troisième est le rayon du cercle</li> - <li>Le quatrième et le cinquième sont les angles de début et de fin pour dessiner l'arc (donc spécifier 0 et 360 nous donne un cercle fermé)</li> - <li>Et le sixième paramètre définit si le cercle doit être dessiné dans le sens des aiguilles d'une montre ou dans le sens inverse (<code>false</code> pour le sens horaire).</li> - </ul> - - <div class="note"> - <p><strong>Note :</strong> 0 degrés est horizontalement vers la droite.</p> - </div> - </li> - <li> - <p>Ajoutons un autre arc:</p> - - <pre class="brush: js">ctx.fillStyle = 'yellow'; -ctx.beginPath(); -ctx.arc(200, 106, 50, degToRad(-45), degToRad(45), true); -ctx.lineTo(200, 106); -ctx.fill();</pre> +2. Ensuite, commencez votre path en ajoutant ce qui suit au bas de votre JavaScript. Ici, nous définissons une couleur pour notre triangle et déplaçons le stylo au point (50, 50) sans rien tracer. C'est à partir de là que nous allons dessiner notre triangle. + + ```js + ctx.fillStyle = 'rgb(255, 0, 0)'; + ctx.beginPath(); + ctx.moveTo(50, 50); + ``` + +3. Maintenant ajoutez le bloc de code suivant: + + ```js + ctx.lineTo(150, 50); + var triHeight = 50 * Math.tan(degToRad(60)); + ctx.lineTo(100, 50+triHeight); + ctx.lineTo(50, 50); + ctx.fill(); + ``` + + Parcourons ceci dans l'ordre: + + 1. D'abord nous ajoutons une ligne vers (150, 50) — notre path va maintenant 100 pixels vers la droite le long de l'axe horizontal (x). + 2. Puis, nous calculons la hauteur de notre triangle équilatéral, en utilisant un peu de trigonométrie simple. Nous dessinons un triangle pointant vers le bas. + + Les angles d'un triangle équilatéral sont tous de 60 degrés. Pour calculer la hauteur, nous pouvons séparer le triangle en deux triangles rectangles par le milieu, qui auront alors des angles de 90, 60 et 30 degrés. - <p>Le motif ici est très similaire, a deux différences près:</p> + Pour ce qui est des côtés: - <ul> - <li>Nous avons mis le dernier paramètre de <code>arc()</code> à <code>true</code>, ce qui signifie que l'arc est tracé dans le sens inverse des aiguilles d'une montre. Donc si notre arc commence à -45 degrés et fini à 45 degrés, nous dessinons un arc de 270 degrés. Si vous changez <code>true</code> à <code>false</code> et ré-exécutez le code, seule une portion de 90 degrés sera dessinée.</li> - <li>Avant d'appeler <code>fill()</code>, nous ajoutons une ligne vers le centre du cercle. Nous obtenons une découpe de style Pac-Man plutôt sympa. Si vous supprimiez cette ligne (essayez!) et ré-exécutiez le code, vous auriez juste un cercle dont le bout a été coupé — entre le début et la fin de l'arc. Cela illuste un autre point important du canvas: si vous essayez de remplir une forme incomplète (qui n'est pas fermée), le navigateur ajoute une ligne droite entre le début et la fin du path et le remplit.</li> - </ul> - </li> -</ol> + - Le côté le plus long est appelé l'**hypoténuse** + - Le côté relié à l'angle de 60 degrés (et qui n'est pas l'hypothénuse) est dit **adjacent** à cet angle — sa longueur est de 50 pixels puisque c'est la moitié de la ligne que nous avons dessiné. + - Le côté opposé à l'angle de 60 degrés est dit **opposé** à cet angle — c'est la hauteur que nous voulons calculer. + + + +  + + Une des formule trigonométrique de base stipule que la longueur du côté adjacent mutiplié par la tangente de l'angle est égale à l'opposé, soit `50 * Math.tan(degToRad(60))`. Nous utilisons notre fonction `degToRad()` pour convertir 60 degrés en radians, puisque {{jsxref("Math.tan()")}} attend une valeur en radians. + + 3. Avec la hauteur calculée, nous ajoutons une nouvelle ligne vers `(100, 50+triHeight)`. La coordonnée X est simple, elle est à mi-chemin de la ligne que nous avons tracé. La valeur de Y d'autre part doit être de 50 plus la hauteur du triangle, puisque le haut du triangle est à 50 pixels du haut du canvas. + 4. L'instruction qui suit ajoute une ligne vers le point de départ du triangle. + 5. Pour finir, nous appelons `ctx.fill()` pour finir le path et remplir la forme. + +#### Dessiner des cercles + +Maintenant, voyons comment dessiner un cercle sur le canvas. Pour ce faire, on utilise la méthode {{domxref("CanvasRenderingContext2D.arc", "arc()")}}, qui dessine tout ou une portion de cercle à un point spécifié. + +1. Ajoutons un arc à notre canvas en ajoutant le code qui suit: + + ```js + ctx.fillStyle = 'rgb(0, 0, 255)'; + ctx.beginPath(); + ctx.arc(150, 106, 50, degToRad(0), degToRad(360), false); + ctx.fill(); + ``` + + `arc()` prend six paramètres. + + - Les deux premiers spécifient la position du centre du cercle (X et Y respectivement). + - Le troisième est le rayon du cercle + - Le quatrième et le cinquième sont les angles de début et de fin pour dessiner l'arc (donc spécifier 0 et 360 nous donne un cercle fermé) + - Et le sixième paramètre définit si le cercle doit être dessiné dans le sens des aiguilles d'une montre ou dans le sens inverse (`false` pour le sens horaire). + + > **Note :** 0 degrés est horizontalement vers la droite. + +2. Ajoutons un autre arc: + + ```js + ctx.fillStyle = 'yellow'; + ctx.beginPath(); + ctx.arc(200, 106, 50, degToRad(-45), degToRad(45), true); + ctx.lineTo(200, 106); + ctx.fill(); + ``` -<p>C'est tout pour le moment; votre exemple final devrait ressembler à ceci:</p> + Le motif ici est très similaire, a deux différences près: -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/3_canvas_paths.html", '100%', 200)}}</p> + - Nous avons mis le dernier paramètre de `arc()` à `true`, ce qui signifie que l'arc est tracé dans le sens inverse des aiguilles d'une montre. Donc si notre arc commence à -45 degrés et fini à 45 degrés, nous dessinons un arc de 270 degrés. Si vous changez `true` à `false` et ré-exécutez le code, seule une portion de 90 degrés sera dessinée. + - Avant d'appeler `fill()`, nous ajoutons une ligne vers le centre du cercle. Nous obtenons une découpe de style Pac-Man plutôt sympa. Si vous supprimiez cette ligne (essayez!) et ré-exécutiez le code, vous auriez juste un cercle dont le bout a été coupé — entre le début et la fin de l'arc. Cela illuste un autre point important du canvas: si vous essayez de remplir une forme incomplète (qui n'est pas fermée), le navigateur ajoute une ligne droite entre le début et la fin du path et le remplit. -<div class="note"> -<p><strong>Note :</strong> Le code finit est disponible sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/3_canvas_paths.html">3_canvas_paths.html</a>.</p> -</div> +C'est tout pour le moment; votre exemple final devrait ressembler à ceci: -<div class="note"> -<p><strong>Note :</strong> Pour en savoir plus sur les fonctions de dessin avancées, telles que les courbes Bézier, consultez notre tutoriel <a href="/fr/docs/Tutoriel_canvas/Formes_géométriques">Dessiner des formes avec le canevas</a>.</p> -</div> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/3_canvas_paths.html", '100%', 200)}} -<h3 id="Texte">Texte</h3> +> **Note :** Le code finit est disponible sur GitHub, [3_canvas_paths.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/3_canvas_paths.html). -<p>Canvas dispose également de fonctionnalités pour écrire du texte. Nous allons les explorer brièvement. Commencez par créer une nouvelle copie du template (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html">1_canvas_template.html</a>), dans lequel nous allons dessiner le nouvel exemple.</p> +> **Note :** Pour en savoir plus sur les fonctions de dessin avancées, telles que les courbes Bézier, consultez notre tutoriel [Dessiner des formes avec le canevas](/fr/docs/Tutoriel_canvas/Formes_géométriques). -<p>Le texte peut être avec deux méthodes:</p> +### Texte -<ul> - <li>{{domxref("CanvasRenderingContext2D.fillText", "fillText()")}} — dessine un texte rempli.</li> - <li>{{domxref("CanvasRenderingContext2D.strokeText", "strokeText()")}} — dessine un contour de texte.</li> -</ul> +Canvas dispose également de fonctionnalités pour écrire du texte. Nous allons les explorer brièvement. Commencez par créer une nouvelle copie du template ([1_canvas_template.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html)), dans lequel nous allons dessiner le nouvel exemple. -<p>Ces deux méthodes prennent trois paramètres: la chaîne de caractères à écrire et les coordonnées X et Y du coin supérieur gauche de la zone de texte (<strong>text box</strong>) — littéralement, la zone entourant le texte que vous écrivez.</p> +Le texte peut être avec deux méthodes: -<p>Il existe également un certain nombre de proprétés pour contrôler le rendu du texte, comme {{domxref("CanvasRenderingContext2D.font", "font")}}, qui permer de spécifier la police d'écriture, la taille, etc — elle accepte la même syntaxe que la propriété CSS {{cssxref("font")}}.</p> +- {{domxref("CanvasRenderingContext2D.fillText", "fillText()")}} — dessine un texte rempli. +- {{domxref("CanvasRenderingContext2D.strokeText", "strokeText()")}} — dessine un contour de texte. -<p>Essayez d'ajouter le bloc suivant au bas de votre javaScript:</p> +Ces deux méthodes prennent trois paramètres: la chaîne de caractères à écrire et les coordonnées X et Y du coin supérieur gauche de la zone de texte (**text box**) — littéralement, la zone entourant le texte que vous écrivez. -<pre class="brush: js">ctx.strokeStyle = 'white'; +Il existe également un certain nombre de proprétés pour contrôler le rendu du texte, comme {{domxref("CanvasRenderingContext2D.font", "font")}}, qui permer de spécifier la police d'écriture, la taille, etc — elle accepte la même syntaxe que la propriété CSS {{cssxref("font")}}. + +Essayez d'ajouter le bloc suivant au bas de votre javaScript: + +```js +ctx.strokeStyle = 'white'; ctx.lineWidth = 1; ctx.font = '36px arial'; ctx.strokeText('Canvas text', 50, 50); ctx.fillStyle = 'red'; ctx.font = '48px georgia'; -ctx.fillText('Canvas text', 50, 150);</pre> +ctx.fillText('Canvas text', 50, 150); +``` -<p>Ici nous dessinons deux lignes de texte, une avec le contour et l'autre remplie. L'exemple final devrait ressembler à ça:</p> +Ici nous dessinons deux lignes de texte, une avec le contour et l'autre remplie. L'exemple final devrait ressembler à ça: -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/4_canvas_text.html", '100%', 180)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/4_canvas_text.html", '100%', 180)}} -<div class="note"> -<p><strong>Note :</strong> Le code final est disponible sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/4_canvas_text.html">4_canvas_text.html</a>.</p> -</div> +> **Note :** Le code final est disponible sur GitHub, [4_canvas_text.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/4_canvas_text.html). -<p>Jouez avec et voyez ce que vous pouvez faire! Vous pouvez trouver plus d'information sur les options disponibles pour ajouter du texte sur un canvas dans <a href="/fr/docs/Dessin_de_texte_avec_canvas">Dessin de texte avec canvas</a>.</p> +Jouez avec et voyez ce que vous pouvez faire! Vous pouvez trouver plus d'information sur les options disponibles pour ajouter du texte sur un canvas dans [Dessin de texte avec canvas](/fr/docs/Dessin_de_texte_avec_canvas). -<h3 id="Dessiner_des_images_sur_le_canvas">Dessiner des images sur le canvas</h3> +### Dessiner des images sur le canvas -<p>Il est possible d'afficher des images externes sur le canvas. Ce peut être des images simples, des images à l'intérieur d'une vidéo, ou le contenu d'autres canvas. Pour le moment, nous allons juste nous occuper d'ajouter des images simples sur le canvas.</p> +Il est possible d'afficher des images externes sur le canvas. Ce peut être des images simples, des images à l'intérieur d'une vidéo, ou le contenu d'autres canvas. Pour le moment, nous allons juste nous occuper d'ajouter des images simples sur le canvas. -<ol> - <li> - <p>Comme précédemment, créez une nouvelle copie du template (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html">1_canvas_template.html</a>), où nous dessinerons l'exemple. Vous allez également devoir sauvegarder une copie de notre image d'exemple — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/firefox.png">firefox.png</a> — dans le même répertoire.</p> +1. Comme précédemment, créez une nouvelle copie du template ([1_canvas_template.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html)), où nous dessinerons l'exemple. Vous allez également devoir sauvegarder une copie de notre image d'exemple — [firefox.png](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/firefox.png) — dans le même répertoire. - <p>Les images sont dessinés sur le canvas en utilisant la méthode {{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}}. Dans sa version la plus simple, elle prend trois paramètres — une référence de l'image que vous voulez afficher et les coordonnées X et Y du coin supérieur gauche de l'image sur le canvas.</p> - </li> - <li> - <p>Commençons par obtenir une ressource de l'image à inclure dans notre canvas. Ajoutez les lignes suivantes au bas de votre JavaScript:</p> + Les images sont dessinés sur le canvas en utilisant la méthode {{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}}. Dans sa version la plus simple, elle prend trois paramètres — une référence de l'image que vous voulez afficher et les coordonnées X et Y du coin supérieur gauche de l'image sur le canvas. - <pre class="brush: js">var image = new Image(); -image.src = 'firefox.png';</pre> +2. Commençons par obtenir une ressource de l'image à inclure dans notre canvas. Ajoutez les lignes suivantes au bas de votre JavaScript: - <p>Ici, nous créons un nouvel objet {{domxref("HTMLImageElement")}} en utilisant le constructeur {{domxref("HTMLImageElement.Image()", "Image()")}}. (L'objet retourné est le même type que celui retourné lorsque vous récupérez une référence vers un élément {{htmlelement("img")}} existant). Nous définissons son attribut {{htmlattrxref("src", "img")}} à notre image du logo Firefox. À ce stade, le navigateur commence à charger l'image.</p> - </li> - <li> - <p>Nous pourrions essayer maintenant d'inclure l'image en utilisant <code>drawImage()</code>, mais nous devons nous assurer que le fichier image ait été chargé en premier, faute de quoi le code échouera. Nous pouvons y parvenir en utilisant le gestionnaire d'événement <code>onload</code>, qui ne sera appelé que lorsque l'image aura fini de charger. Ajoutez le bloc suivant à la suite du précédent:</p> + ```js + var image = new Image(); + image.src = 'firefox.png'; + ``` - <pre class="brush: js">image.onload = function() { - ctx.drawImage(image, 50, 50); -}</pre> + Ici, nous créons un nouvel objet {{domxref("HTMLImageElement")}} en utilisant le constructeur {{domxref("HTMLImageElement.Image()", "Image()")}}. (L'objet retourné est le même type que celui retourné lorsque vous récupérez une référence vers un élément {{htmlelement("img")}} existant). Nous définissons son attribut {{htmlattrxref("src", "img")}} à notre image du logo Firefox. À ce stade, le navigateur commence à charger l'image. - <p>Si vous chargez votre exemple dans le navigateur maintenant, vous devriez voir l'image inclue dans le canvas.</p> - </li> - <li> - <p>Mais il y en a plus! Et si nous ne voulions afficher qu'une partie de l'image, ou la redimensionner? Nous pouvons faire ces deux choses avec une version plus complexe de <code>drawImage()</code>. Mettez à jour votre ligne <code>ctx.drawImage()</code> comme suit:</p> +3. Nous pourrions essayer maintenant d'inclure l'image en utilisant `drawImage()`, mais nous devons nous assurer que le fichier image ait été chargé en premier, faute de quoi le code échouera. Nous pouvons y parvenir en utilisant le gestionnaire d'événement `onload`, qui ne sera appelé que lorsque l'image aura fini de charger. Ajoutez le bloc suivant à la suite du précédent: - <pre class="brush: js">ctx.drawImage(image, 20, 20, 185, 175, 50, 50, 185, 175);</pre> + ```js + image.onload = function() { + ctx.drawImage(image, 50, 50); + } + ``` - <ul> - <li>Le premier paramètre est la référence de l'image, comme précédemment.</li> - <li>Les paramètres 2 et 3 définissent les coordonnées à partir d'où découper l'image, relativement au coin supérieur gauche de l'image d'origine. Tout ce qui est à gauche de X (paramètre 2) ou au-dessus de Y (paramètre 3) ne sera pas dessiné.</li> - <li>Les paramètres 4 et 5 définissent la largeur et hauteur de la zone que nous voulons découper, à partir du coin supérieur gauche de l'image découpée.</li> - <li>Les paramètres 6 et 7 définissent les coordonnées où vous souhaitez placer l'image sur le canvas, relativement au coin supérieur gauche du canvas.</li> - <li>Les paramètres 8 et 9 définissent la largeur et la hauteur affichée de l'image découpée. En l'occurence, nous avons spécifié les mêmes dimensions que la découpe, mais vous pouvez la redimensionner (et la déformer) en spécifiant des valeurs différentes.</li> - </ul> - </li> -</ol> + Si vous chargez votre exemple dans le navigateur maintenant, vous devriez voir l'image inclue dans le canvas. -<p>L'exemple final devrait ressembler à ça:</p> +4. Mais il y en a plus! Et si nous ne voulions afficher qu'une partie de l'image, ou la redimensionner? Nous pouvons faire ces deux choses avec une version plus complexe de `drawImage()`. Mettez à jour votre ligne `ctx.drawImage()` comme suit: -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/5_canvas_images.html", '100%', 260)}}</p> + ```js + ctx.drawImage(image, 20, 20, 185, 175, 50, 50, 185, 175); + ``` -<div class="note"> -<p><strong>Note :</strong> Le code final est disponible sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/5_canvas_images.html">5_canvas_images.html</a>.</p> -</div> + - Le premier paramètre est la référence de l'image, comme précédemment. + - Les paramètres 2 et 3 définissent les coordonnées à partir d'où découper l'image, relativement au coin supérieur gauche de l'image d'origine. Tout ce qui est à gauche de X (paramètre 2) ou au-dessus de Y (paramètre 3) ne sera pas dessiné. + - Les paramètres 4 et 5 définissent la largeur et hauteur de la zone que nous voulons découper, à partir du coin supérieur gauche de l'image découpée. + - Les paramètres 6 et 7 définissent les coordonnées où vous souhaitez placer l'image sur le canvas, relativement au coin supérieur gauche du canvas. + - Les paramètres 8 et 9 définissent la largeur et la hauteur affichée de l'image découpée. En l'occurence, nous avons spécifié les mêmes dimensions que la découpe, mais vous pouvez la redimensionner (et la déformer) en spécifiant des valeurs différentes. -<h2 id="Boucles_et_animations">Boucles et animations</h2> +L'exemple final devrait ressembler à ça: -<p>Jusqu'ici, nous avons couvert quelques utilisations très basiques du canvas 2D, mais vous ne ressentirez la pleine puissance du canvas que si vous le mettez à jour ou l'animez d'une manière ou d'une autre. Après tout, le canvas fournit des images scriptables! Si vous n'avez pas l'intention de changer quelque chose, alors autant utiiliser des images statiques et vous épargner du travail.</p> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/getting-started/5_canvas_images.html", '100%', 260)}} -<h3 id="Créer_une_boucle">Créer une boucle</h3> +> **Note :** Le code final est disponible sur GitHub, [5_canvas_images.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/5_canvas_images.html). -<p>Jouer avec des boucles est plutôt amusant — vous pouvez exécuter des commandes de canvas à l'intérieur d'une boucle <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for">for</a></code> (ou tout autre type de boucle) comme n'importe quel autre code JavaScript.</p> +## Boucles et animations -<p>Construisons un exemple simple.</p> +Jusqu'ici, nous avons couvert quelques utilisations très basiques du canvas 2D, mais vous ne ressentirez la pleine puissance du canvas que si vous le mettez à jour ou l'animez d'une manière ou d'une autre. Après tout, le canvas fournit des images scriptables! Si vous n'avez pas l'intention de changer quelque chose, alors autant utiiliser des images statiques et vous épargner du travail. -<ol> - <li> - <p>Créez une nouvelle copie du template (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html">1_canvas_template.html</a>) et ouvrez-le dans votre éditeur de texte.</p> - </li> - <li> - <p>Ajoutez la ligne qui suit au bas de votre JavaScript. Elle contient une nouvelle méthode, {{domxref("CanvasRenderingContext2D.translate", "translate()")}}, qui déplace le point d'origine du canvas:</p> +### Créer une boucle - <pre class="brush: js">ctx.translate(width/2, height/2);</pre> +Jouer avec des boucles est plutôt amusant — vous pouvez exécuter des commandes de canvas à l'intérieur d'une boucle [`for`](/fr/docs/Web/JavaScript/Reference/Instructions/for) (ou tout autre type de boucle) comme n'importe quel autre code JavaScript. - <p>Cela a pour effet de déplacer l'origine des coordonnées (0, 0) au centre du canvas, plutôt que d'être dans le coin supérieur gauche. C'est très utile dans de nombreuses situations, comme celle-ci, où nous voulons que notre dessin soit dessiné par rapport au centre du canvas.</p> - </li> - <li> - <p>Maintenant ajoutez le code suivant au bas du Javacript:</p> +Construisons un exemple simple. - <pre class="brush: js">function degToRad(degrees) { - return degrees * Math.PI / 180; -}; +1. Créez une nouvelle copie du template ([1_canvas_template.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html)) et ouvrez-le dans votre éditeur de texte. +2. Ajoutez la ligne qui suit au bas de votre JavaScript. Elle contient une nouvelle méthode, {{domxref("CanvasRenderingContext2D.translate", "translate()")}}, qui déplace le point d'origine du canvas: -function rand(min, max) { - return Math.floor(Math.random() * (max-min+1)) + (min); -} + ```js + ctx.translate(width/2, height/2); + ``` -var length = 250; -var moveOffset = 20; + Cela a pour effet de déplacer l'origine des coordonnées (0, 0) au centre du canvas, plutôt que d'être dans le coin supérieur gauche. C'est très utile dans de nombreuses situations, comme celle-ci, où nous voulons que notre dessin soit dessiné par rapport au centre du canvas. -for(var i = 0; i < length; i++) { +3. Maintenant ajoutez le code suivant au bas du Javacript: -}</pre> + ```js + function degToRad(degrees) { + return degrees * Math.PI / 180; + }; - <p>Ici, nous implémentons</p> + function rand(min, max) { + return Math.floor(Math.random() * (max-min+1)) + (min); + } - <ul> - <li>la même fonction <code>degToRad()</code> que nous avons vu dans l'exemple du triangle auparavant,</li> - <li>une fonction <code>rand()</code>, qui retoune un nombre aléatoire entre une limite inférieure et une limite supérieure,</li> - <li>les variables <code>length</code> et <code>moveOffset</code> (que nous verrons plus loin),</li> - <li>et une boucle <code>for</code> vide.</li> - </ul> - </li> - <li> - <p>L'idée est que nous allons dessiner quelque chose sur le canvas à l'intérieur de la boucle <code>for</code>, et itérer dessus pour créer quelque chose d'intéressant. Ajoutez le code suivant à l'intérieur de la boucle <code>for</code>:</p> + var length = 250; + var moveOffset = 20; - <pre class="brush: js">ctx.fillStyle = 'rgba(' + (255-length) + ', 0, ' + (255-length) + ', 0.9)'; -ctx.beginPath(); -ctx.moveTo(moveOffset, moveOffset); -ctx.lineTo(moveOffset+length, moveOffset); -var triHeight = length/2 * Math.tan(degToRad(60)); -ctx.lineTo(moveOffset+(length/2), moveOffset+triHeight); -ctx.lineTo(moveOffset, moveOffset); -ctx.fill(); + for(var i = 0; i < length; i++) { + + } + ``` + + Ici, nous implémentons + + - la même fonction `degToRad()` que nous avons vu dans l'exemple du triangle auparavant, + - une fonction `rand()`, qui retoune un nombre aléatoire entre une limite inférieure et une limite supérieure, + - les variables `length` et `moveOffset` (que nous verrons plus loin), + - et une boucle `for` vide. -length--; -moveOffset += 0.7; -ctx.rotate(degToRad(5));</pre> +4. L'idée est que nous allons dessiner quelque chose sur le canvas à l'intérieur de la boucle `for`, et itérer dessus pour créer quelque chose d'intéressant. Ajoutez le code suivant à l'intérieur de la boucle `for`: - <p>Ainsi à chaque itération, on:</p> + ```js + ctx.fillStyle = 'rgba(' + (255-length) + ', 0, ' + (255-length) + ', 0.9)'; + ctx.beginPath(); + ctx.moveTo(moveOffset, moveOffset); + ctx.lineTo(moveOffset+length, moveOffset); + var triHeight = length/2 * Math.tan(degToRad(60)); + ctx.lineTo(moveOffset+(length/2), moveOffset+triHeight); + ctx.lineTo(moveOffset, moveOffset); + ctx.fill(); - <ol> - <li>Définit <code>fillStyle</code> comme étant une nuance de violet légèrement transparente, et qui change à chaque fois en fonction de la valeur de <code>length</code>. Comme vous le verrez plus tard, sa valeur diminue à chaque itération, ce qui a pour effet de rendre la couleur toujours plus claire.</li> - <li>Ouvre un path.</li> - <li>Déplace le stylo aux coordonnées de <code>(moveOffset, moveOffset)</code>; Cette variable définit jusqu'où nous voulons nous déplacer à chaque fois que nous dessinons.</li> - <li>Dessine une ligne aux coordonées de <code>(moveOffset+length, moveOffset)</code>. Cela dessine une ligne de longueur <code>length</code> parallèle à l'axe X.</li> - <li>Calcule la hauteur du triangle, comme vu auparavant.</li> - <li>Dessine une ligne vers le coin du bas du triangle.</li> - <li>Dessine une ligne vers le début du triangle.</li> - <li>Appelle <code>fill()</code> pour remplir le triangle.</li> - <li>Met à jour les variables qui indiquent comment dessiner le triangle, afin qu'elles soient prêtes pour la prochaine itération: - <ul> - <li>Diminue la valeur de <code>length</code> de 1, de sorte que les triangles deviennent de plus en plus petits;</li> - <li>Augmente un peu <code>moveOffset</code> pour que chaque triangle successif soit légèrement plus éloigné;</li> - <li>et utilise une nouvelle fonction, {{domxref("CanvasRenderingContext2D.rotate", "rotate()")}}, qui permet de faire pivoter entièrement le canvas! Nous le faisons pivoter de 5 degrés avant de dessiner le triangle suivant.</li> - </ul> - </li> - </ol> - </li> -</ol> + length--; + moveOffset += 0.7; + ctx.rotate(degToRad(5)); + ``` -<p>C'est tout! L'exemple final devrait ressemble à ça:</p> + Ainsi à chaque itération, on: -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/6_canvas_for_loop.html", '100%', 550)}}</p> + 1. Définit `fillStyle` comme étant une nuance de violet légèrement transparente, et qui change à chaque fois en fonction de la valeur de `length`. Comme vous le verrez plus tard, sa valeur diminue à chaque itération, ce qui a pour effet de rendre la couleur toujours plus claire. + 2. Ouvre un path. + 3. Déplace le stylo aux coordonnées de `(moveOffset, moveOffset)`; Cette variable définit jusqu'où nous voulons nous déplacer à chaque fois que nous dessinons. + 4. Dessine une ligne aux coordonées de `(moveOffset+length, moveOffset)`. Cela dessine une ligne de longueur `length` parallèle à l'axe X. + 5. Calcule la hauteur du triangle, comme vu auparavant. + 6. Dessine une ligne vers le coin du bas du triangle. + 7. Dessine une ligne vers le début du triangle. + 8. Appelle `fill()` pour remplir le triangle. + 9. Met à jour les variables qui indiquent comment dessiner le triangle, afin qu'elles soient prêtes pour la prochaine itération: -<p>À ce stade, nous vous encourageons à jouer avec l'exemple et de vous l'approprier! Par exemple:</p> + - Diminue la valeur de `length` de 1, de sorte que les triangles deviennent de plus en plus petits; + - Augmente un peu `moveOffset` pour que chaque triangle successif soit légèrement plus éloigné; + - et utilise une nouvelle fonction, {{domxref("CanvasRenderingContext2D.rotate", "rotate()")}}, qui permet de faire pivoter entièrement le canvas! Nous le faisons pivoter de 5 degrés avant de dessiner le triangle suivant. -<ul> - <li>Dessinez des rectangles ou des arcs au lieu des triangles, ou même des images externes.</li> - <li>Jouez avec les valeurs de <code>length</code> et <code>moveOffset</code>.</li> - <li>Utilisez des nombres aléatoires — grâce à la fonction <code>rand()</code> que nous avons inclue mais que nous n'avons pas utilisée.</li> -</ul> +C'est tout! L'exemple final devrait ressemble à ça: -<div class="note"> -<p><strong>Note :</strong> Le code terminé est disponible sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/6_canvas_for_loop.html">6_canvas_for_loop.html</a>.</p> -</div> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/6_canvas_for_loop.html", '100%', 550)}} -<h3 id="Animations">Animations</h3> +À ce stade, nous vous encourageons à jouer avec l'exemple et de vous l'approprier! Par exemple: -<p>L'exemple de boucle que nous avons construit ci-dessus était amusant, mais en vrai vous avez besoin d'une boucle qui continue constamment d'itérer pour toute application sérieuse de canvas (telles que les jeux et les visualisations en temps réel). Si vous pensez à votre canvas comme étant en quelque sorte un film, vous allez vouloir que l'affichage se mette à jour à chaque image pour afficher la mise à jour avec un taux de rafraichissement idéal de 60 images par seconde, afin que le mouvement soit lisse et agréable pour l'oeil humain.</p> +- Dessinez des rectangles ou des arcs au lieu des triangles, ou même des images externes. +- Jouez avec les valeurs de `length` et `moveOffset`. +- Utilisez des nombres aléatoires — grâce à la fonction `rand()` que nous avons inclue mais que nous n'avons pas utilisée. -<p>Il y a quelques fonctions JavaScript qui vous permettrons d'exécuter des fonctions de manière répétée, plusieurs fois par seconde, la meilleure étant ici {{domxref("window.requestAnimationFrame()")}}. Elle prend un paramètre — la fonction que vous voulez exécuter pour chaque image. Dès que le navigateur est prêt à mettre à jour l'écran, votre fonction sera appelée. Si cette fonction dessine la nouvelle mise à jour, puis appelle de nouveau <code>requestAnimationFrame()</code> juste avant la fin de la fonction, la boucle d'animation continuera de s'exécuter de manière fluide. La boucle s'arrête lorsque vous vous arrêtez d'appeler <code>requestAnimationFrame()</code> ou si vous appelez {{domxref("window.cancelAnimationFrame()")}} après avoir appelé <code>requestAnimationFrame()</code> mais avant que votre fonction n'ait été exécutée.</p> +> **Note :** Le code terminé est disponible sur GitHub, [6_canvas_for_loop.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/6_canvas_for_loop.html). -<div class="note"> -<p><strong>Note:</strong> C'est une bonne pratique d'appeler <code>cancelAnimationFrame()</code> à partir de votre code principal lorsque vous avez terminé d'utiliser l'animation, pour vous assurer qu'aucune mise à jour n'attend d'être exécutée.</p> -</div> +### Animations -<p>Le navigateur s'occupe des détails complexes tels qu'exécuter l'animation à une vitesse constante, et ne pas gaspiller de ressources en animant des choses qui ne sont pas visibles.</p> +L'exemple de boucle que nous avons construit ci-dessus était amusant, mais en vrai vous avez besoin d'une boucle qui continue constamment d'itérer pour toute application sérieuse de canvas (telles que les jeux et les visualisations en temps réel). Si vous pensez à votre canvas comme étant en quelque sorte un film, vous allez vouloir que l'affichage se mette à jour à chaque image pour afficher la mise à jour avec un taux de rafraichissement idéal de 60 images par seconde, afin que le mouvement soit lisse et agréable pour l'oeil humain. -<p>Pour voir comment cela fonctionne, regardons rapidement notre exemple des balles qui rebondissent (<a href="https://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html">le voir en direct</a>, et voir <a href="https://github.com/mdn/learning-area/tree/master/javascript/oojs/bouncing-balls">le code source</a>). Le code de la boucle qui garde le tout en mouvement ressemble à ceci:</p> +Il y a quelques fonctions JavaScript qui vous permettrons d'exécuter des fonctions de manière répétée, plusieurs fois par seconde, la meilleure étant ici {{domxref("window.requestAnimationFrame()")}}. Elle prend un paramètre — la fonction que vous voulez exécuter pour chaque image. Dès que le navigateur est prêt à mettre à jour l'écran, votre fonction sera appelée. Si cette fonction dessine la nouvelle mise à jour, puis appelle de nouveau `requestAnimationFrame()` juste avant la fin de la fonction, la boucle d'animation continuera de s'exécuter de manière fluide. La boucle s'arrête lorsque vous vous arrêtez d'appeler `requestAnimationFrame()` ou si vous appelez {{domxref("window.cancelAnimationFrame()")}} après avoir appelé `requestAnimationFrame()` mais avant que votre fonction n'ait été exécutée. -<pre class="brush: js">function loop() { +> **Note :** C'est une bonne pratique d'appeler `cancelAnimationFrame()` à partir de votre code principal lorsque vous avez terminé d'utiliser l'animation, pour vous assurer qu'aucune mise à jour n'attend d'être exécutée. + +Le navigateur s'occupe des détails complexes tels qu'exécuter l'animation à une vitesse constante, et ne pas gaspiller de ressources en animant des choses qui ne sont pas visibles. + +Pour voir comment cela fonctionne, regardons rapidement notre exemple des balles qui rebondissent ([le voir en direct](https://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html), et voir [le code source](https://github.com/mdn/learning-area/tree/master/javascript/oojs/bouncing-balls)). Le code de la boucle qui garde le tout en mouvement ressemble à ceci: + +```js +function loop() { ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; ctx.fillRect(0, 0, width, height); - while(balls.length < 25) { + while(balls.length < 25) { var ball = new Ball(); balls.push(ball); } - for(i = 0; i < balls.length; i++) { + for(i = 0; i < balls.length; i++) { balls[i].draw(); balls[i].update(); balls[i].collisionDetect(); @@ -577,143 +541,141 @@ ctx.rotate(degToRad(5));</pre> requestAnimationFrame(loop); } -loop();</pre> +loop(); +``` -<p>Nous lançons la fonction <code>loop()</code> une fois pour commencer le cycle et dessiner la première image de l'animation. La fonction <code>loop()</code> s'occupe ensuite d'appeler <code>requestAnimationFrame(loop)</code> pour afficher la prochaine image de l'animation, et ce continuellement.</p> +Nous lançons la fonction `loop()` une fois pour commencer le cycle et dessiner la première image de l'animation. La fonction `loop()` s'occupe ensuite d'appeler `requestAnimationFrame(loop)` pour afficher la prochaine image de l'animation, et ce continuellement. -<p>Notez que sur chaque image, nous effaçons complètement le canvas et redessinons tout. Nous créons de nouvelles balles pour chaque image — au maximum 25 — puis, pour chaque balle, la dessinons, mettons à jour sa position, et vérifions si elle est en collision avec une autre balle. Une fois que vous avez dessiné quelque chose sur un canvas, il n'y a aucun moyen pour manipuler cet élément graphique individuellement comme vous pouvez le faire avec les élément DOM. Vous ne pouvez pas déplacer les balles sur le canvas parce qu'une fois dessinée, une balle n'est plus une balle mais juste des pixels sur un canvas. Au lieu de ça, vous devez effacer et redessiner, soit en effaçant et redessinant absolutement tout le canvas, soit en ayant du code qui sait exactement quelles parties doivent être effacées, et qui efface et redessine uniquement la zone minimale nécessaire.</p> +Notez que sur chaque image, nous effaçons complètement le canvas et redessinons tout. Nous créons de nouvelles balles pour chaque image — au maximum 25 — puis, pour chaque balle, la dessinons, mettons à jour sa position, et vérifions si elle est en collision avec une autre balle. Une fois que vous avez dessiné quelque chose sur un canvas, il n'y a aucun moyen pour manipuler cet élément graphique individuellement comme vous pouvez le faire avec les élément DOM. Vous ne pouvez pas déplacer les balles sur le canvas parce qu'une fois dessinée, une balle n'est plus une balle mais juste des pixels sur un canvas. Au lieu de ça, vous devez effacer et redessiner, soit en effaçant et redessinant absolutement tout le canvas, soit en ayant du code qui sait exactement quelles parties doivent être effacées, et qui efface et redessine uniquement la zone minimale nécessaire. -<p>Optimiser l'animation graphique est une spécialité entière de programmation, avec beaucoup de techniques ingénieuses disponibles. Mais celles-ci sont au-delà de ce dont nous avons besoin pour notre exemple!</p> +Optimiser l'animation graphique est une spécialité entière de programmation, avec beaucoup de techniques ingénieuses disponibles. Mais celles-ci sont au-delà de ce dont nous avons besoin pour notre exemple! -<p>En général, le processus pour animer un canvas implique les étapes suivantes:</p> +En général, le processus pour animer un canvas implique les étapes suivantes: -<ol> - <li>Effacer le contenu du cavas (par exemple avec {{domxref("CanvasRenderingContext2D.fillRect", "fillRect()")}} ou {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}).</li> - <li>Sauvegarder l'état (si nécessaire) en utilisant {{domxref("CanvasRenderingContext2D.save", "save()")}} — c'est nécessaire lorsque vous voulez enregistrer les paramètres que vous mis à jour sur le canvas avant de continuer, ce qui est utile pour des applications plus avancées.</li> - <li>Dessiner les éléments graphiques que vous animez.</li> - <li>Restaurer les paramètres sauvegardés à l'étape 2 en utilisant {{domxref("CanvasRenderingContext2D.restore", "restore()")}}</li> - <li>Appeler <code>requestAnimationFrame()</code> pour planifier le dessin de l'image suivante de l'animation.</li> -</ol> +1. Effacer le contenu du cavas (par exemple avec {{domxref("CanvasRenderingContext2D.fillRect", "fillRect()")}} ou {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}). +2. Sauvegarder l'état (si nécessaire) en utilisant {{domxref("CanvasRenderingContext2D.save", "save()")}} — c'est nécessaire lorsque vous voulez enregistrer les paramètres que vous mis à jour sur le canvas avant de continuer, ce qui est utile pour des applications plus avancées. +3. Dessiner les éléments graphiques que vous animez. +4. Restaurer les paramètres sauvegardés à l'étape 2 en utilisant {{domxref("CanvasRenderingContext2D.restore", "restore()")}} +5. Appeler `requestAnimationFrame()` pour planifier le dessin de l'image suivante de l'animation. -<div class="note"> -<p><strong>Note :</strong> Nous ne couvrirons pas <code>save()</code> et <code>restore()</code> ici, mais elles sont bien expliquées dans notre tutoriel <a href="/fr/docs/Tutoriel_canvas/Transformations">Transformations</a> (et ceux qui le suivent).</p> -</div> +> **Note :** Nous ne couvrirons pas `save()` et `restore()` ici, mais elles sont bien expliquées dans notre tutoriel [Transformations](/fr/docs/Tutoriel_canvas/Transformations) (et ceux qui le suivent). -<h3 id="Une_animation_simple_de_personnage">Une animation simple de personnage</h3> +### Une animation simple de personnage -<p>Créons maintenant notre propre animation simple — nous allons faire parcourir l'écran à un personnage d'un certain jeu vidéo rétro plutôt génial.</p> +Créons maintenant notre propre animation simple — nous allons faire parcourir l'écran à un personnage d'un certain jeu vidéo rétro plutôt génial. -<ol> - <li> - <p>Faites une nouvelle copie du template (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html">1_canvas_template.html</a>) et ouvrez-le dans votre éditeur de texte. Sauvegardez une copie de <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/walk-right.png">walk-right.png</a> dans le même répertoire.</p> - </li> - <li> - <p>Au bas du JavaScript, ajoutez la ligne suivante pour placer une fois de plus l'origine des coordonnées au milieu du canvas:</p> +1. Faites une nouvelle copie du template ([1_canvas_template.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/getting-started/1_canvas_template.html)) et ouvrez-le dans votre éditeur de texte. Sauvegardez une copie de [walk-right.png](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/walk-right.png) dans le même répertoire. +2. Au bas du JavaScript, ajoutez la ligne suivante pour placer une fois de plus l'origine des coordonnées au milieu du canvas: - <pre class="brush: js">ctx.translate(width/2, height/2);</pre> - </li> - <li> - <p>Nous allons maintenant créer un objet {{domxref("HTMLImageElement")}}, définir son attribut {{htmlattrxref("src", "img")}} à l'image que nous voulons charger, et ajouter le gestionnaire d'événement <code>onload</code> pour appeler la fonction <code>draw()</code> quand l'image sera chargée:</p> + ```js + ctx.translate(width/2, height/2); + ``` - <pre class="brush: js">var image = new Image(); -image.src = 'walk-right.png'; -image.onload = draw;</pre> - </li> - <li> - <p>Ajoutons quelques variables pour garder une trace de la position du sprite à dessiner à l'écran, et le numéro du sprite que nous voulons afficher.</p> +3. Nous allons maintenant créer un objet {{domxref("HTMLImageElement")}}, définir son attribut {{htmlattrxref("src", "img")}} à l'image que nous voulons charger, et ajouter le gestionnaire d'événement `onload` pour appeler la fonction `draw()` quand l'image sera chargée: - <pre class="brush: js">var sprite = 0; -var posX = 0;</pre> + ```js + var image = new Image(); + image.src = 'walk-right.png'; + image.onload = draw; + ``` - <p>L'image de sprites (que nous avons respectueusement emprunté à Mike Thomas dans son article <a href="http://atomicrobotdesign.com/blog/htmlcss/create-a-sprite-sheet-walk-cycle-using-using-css-animation/" rel="bookmark" title="Permanent Link to Create a sprite sheet walk cycle using using CSS animation">Create a sprite sheet walk cycle using using CSS animation</a> — créer un cycle de marche avec une feuille de sprites en utilisant les animations CSS) ressemble à ça:</p> +4. Ajoutons quelques variables pour garder une trace de la position du sprite à dessiner à l'écran, et le numéro du sprite que nous voulons afficher. - <p><img alt="" src="walk-right.png"></p> + ```js + var sprite = 0; + var posX = 0; + ``` - <p>Elle contient six sprites qui constituent une séquence de marche — chacun a 102 pixels de large et 148 pixels de hauteur. Pour afficher chaque sprite proprement, nous allons devoir utiliser <code>drawImage()</code> pour découper un seul sprite de l'image et n'afficher que cette partie, comme nous l'avons fait précédemment avec le logo Firefox. La coordonnée X de la découpe devra être un multiple de 102 et la coordonnée Y sera toujours 0. La taille de la découpe sera toujours de 102 pixels par 148.</p> - </li> - <li> - <p>Insérons maintenant une fonction <code>draw()</code> vide au bas du code, prête à être remplie de code:</p> + L'image de sprites (que nous avons respectueusement emprunté à Mike Thomas dans son article [Create a sprite sheet walk cycle using using CSS animation](http://atomicrobotdesign.com/blog/htmlcss/create-a-sprite-sheet-walk-cycle-using-using-css-animation/ "Permanent Link to Create a sprite sheet walk cycle using using CSS animation") — créer un cycle de marche avec une feuille de sprites en utilisant les animations CSS) ressemble à ça: - <pre class="brush: js">function draw() { +  -};</pre> - </li> - <li> - <p>Le reste du code dans cette section va dans <code>draw()</code>. Tout d'abord, ajoutez la ligne suivante, qui efface le canvas pour préparer le dessin de chaque image. Notez que nous devons spécifier le coin supérieur gauche du rectangle comme étant <code>-(width/2), -(height/2)</code> puisque nous avons définit l'origine du canvas à <code>width/2, height/2</code> plus tôt.</p> + Elle contient six sprites qui constituent une séquence de marche — chacun a 102 pixels de large et 148 pixels de hauteur. Pour afficher chaque sprite proprement, nous allons devoir utiliser `drawImage()` pour découper un seul sprite de l'image et n'afficher que cette partie, comme nous l'avons fait précédemment avec le logo Firefox. La coordonnée X de la découpe devra être un multiple de 102 et la coordonnée Y sera toujours 0. La taille de la découpe sera toujours de 102 pixels par 148. - <pre class="brush: js">ctx.fillRect(-(width/2), -(height/2), width, height);</pre> - </li> - <li> - <p>Ensuite, nous allons dessinons notre image en utilisant <code>drawImage()</code> — la version à 9 paramètres. Ajoutez ce qui suit:</p> +5. Insérons maintenant une fonction `draw()` vide au bas du code, prête à être remplie de code: - <pre class="brush: js">ctx.drawImage(image, (sprite*102), 0, 102, 148, 0+posX, -74, 102, 148);</pre> + ```js + function draw() { - <p>Comme vous pouvez le voir:</p> + }; + ``` - <ul> - <li>Nous spécifions <code>image</code> comme étant l'image à inclure.</li> - <li>Les paramètres 2 et 3 spécifient le coin supérieur gauche de la portion de l'image à découper: la valeur X vaut <code>sprite</code> multiplié par 102 (où <code>sprite</code> est le numéro du sprite, entre 0 et 5) et la valeur Y vaut toujours 0.</li> - <li>Les paramètres 4 et 5 spécifient la taille de la découpe — 102 pixels par 148.</li> - <li>Les paramètres 6 et 7 spécifient le coin supérieur gauche de la découpe sur le canvas — la position de X est <code>0+posX</code>, ce qui signifie que nous pouvons modifier la position du dessin en modifiant la valeur de <code>posX</code>.</li> - <li>Les paramètres 8 et 9 spécifient la taille de l'image sur le canvas. Nous voulons garder sa taille d'origine, on définit donc 102 pour largeur et 148 pour hauteur.</li> - </ul> - </li> - <li> - <p>Maintenant, nous allons changer la valeur de <code>sprite</code> après chaque dessin — après certains d'entre eux du moins. Ajoutez le bloc de code suivant au bas de la fonction <code>draw()</code>:</p> +6. Le reste du code dans cette section va dans `draw()`. Tout d'abord, ajoutez la ligne suivante, qui efface le canvas pour préparer le dessin de chaque image. Notez que nous devons spécifier le coin supérieur gauche du rectangle comme étant `-(width/2), -(height/2)` puisque nous avons définit l'origine du canvas à `width/2, height/2` plus tôt. - <pre class="brush: js"> if (posX % 13 === 0) { - if (sprite === 5) { - sprite = 0; - } else { - sprite++; - } - }</pre> + ```js + ctx.fillRect(-(width/2), -(height/2), width, height); + ``` - <p>Nous enveloppons le bloc entier de <code>if (posX % 13 === 0) { ... }</code>. On utilise l'opérateur modulo (<code>%</code>) (aussi connu sous le nom d'<a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_arithmétiques#Reste_()">opérateur reste</a>) pour vérifier si la valeur de <code>posX</code> peut être exactement divisée par 13, sans reste. Si c'est le cas, on passe au sprite suivant en incrémentant <code>sprite</code> (en retournant à 0 après le sprite #5). Cela implique que nous ne mettons à jour le sprite que toutes les 13èmes images, ou à peu près 5 images par seconde (<code>requestAnimationFrame()</code> appelle jusqu'à 60 images par secondes si possible). Nous ralentissons délibéremment le cadence des images parce que nous n'avons que six sprites avec lesquels travailler, et si on en affiche un à chaque 60ième de seconde, notre personnage va bouger beaucoup trop vite!</p> +7. Ensuite, nous allons dessinons notre image en utilisant `drawImage()` — la version à 9 paramètres. Ajoutez ce qui suit: - <p>À l'intérieur du bloc, on utilise une instruction <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">if ... else</a></code> pour vérifier si la valeur de <code>sprite</code> vaut 5 (le dernier sprite, puisque les numéro de sprite vont de 0 à 5). Si nous sommes en train d'afficher le dernier sprite, alors on réinitialilse <code>sprite</code> à 0; sinon on l'incrémente de 1.</p> - </li> - <li> - <p>Ensuite, nous devons déterminer comment modifier la valeur de <code>posX</code> sur chaque image — ajoutez le bloc de code à la suite:</p> + ```js + ctx.drawImage(image, (sprite*102), 0, 102, 148, 0+posX, -74, 102, 148); + ``` - <pre class="brush: js"> if(posX > width/2) { - newStartPos = -((width/2) + 102); - posX = Math.ceil(newStartPos / 13) * 13; - console.log(posX); - } else { - posX += 2; - }</pre> + Comme vous pouvez le voir: - <p>Nous utilisons une autre instruction <code>if ... else</code> pour voir si la valeur de <code>posX</code> est plus grande que <code>width/2</code>, ce qui signifie que notre personnage est sortit du bord droit de l'écran. Si c'est le cas, on calcule la position qui met le personnage à gauche du bord gauche de l'écran, et on définit <code>posX</code> au multiple de 13 le plus proche de ce nombre. Il faut obligatoirement un multiple de 13 pour que le bloc de code précédent puisse toujours fonctionner!</p> + - Nous spécifions `image` comme étant l'image à inclure. + - Les paramètres 2 et 3 spécifient le coin supérieur gauche de la portion de l'image à découper: la valeur X vaut `sprite` multiplié par 102 (où `sprite` est le numéro du sprite, entre 0 et 5) et la valeur Y vaut toujours 0. + - Les paramètres 4 et 5 spécifient la taille de la découpe — 102 pixels par 148. + - Les paramètres 6 et 7 spécifient le coin supérieur gauche de la découpe sur le canvas — la position de X est `0+posX`, ce qui signifie que nous pouvons modifier la position du dessin en modifiant la valeur de `posX`. + - Les paramètres 8 et 9 spécifient la taille de l'image sur le canvas. Nous voulons garder sa taille d'origine, on définit donc 102 pour largeur et 148 pour hauteur. - <p>Si notre personnage n'a pas atteint le bord de l'écran, on incrémente <code>posX</code> de 2. Cela le fera bouger un peu vers la droite la prochaine fois qu'on le dessinera.</p> - </li> - <li> - <p>Finalement, nous devons boucler sur l'animation en appelannt {{domxref("window.requestAnimationFrame", "requestAnimationFrame()")}} en bas de la fonction <code>draw()</code>:</p> +8. Maintenant, nous allons changer la valeur de `sprite` après chaque dessin — après certains d'entre eux du moins. Ajoutez le bloc de code suivant au bas de la fonction `draw()`: - <pre class="brush: js">window.requestAnimationFrame(draw);</pre> - </li> -</ol> + ```js + if (posX % 13 === 0) { + if (sprite === 5) { + sprite = 0; + } else { + sprite++; + } + } + ``` -<p>Et voilà! L'exemple final devrait ressembler à ça:</p> + Nous enveloppons le bloc entier de `if (posX % 13 === 0) { ... }`. On utilise l'opérateur modulo (`%`) (aussi connu sous le nom d'[opérateur reste](</fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_arithmétiques#Reste_()>)) pour vérifier si la valeur de `posX` peut être exactement divisée par 13, sans reste. Si c'est le cas, on passe au sprite suivant en incrémentant `sprite` (en retournant à 0 après le sprite #5). Cela implique que nous ne mettons à jour le sprite que toutes les 13èmes images, ou à peu près 5 images par seconde (`requestAnimationFrame()` appelle jusqu'à 60 images par secondes si possible). Nous ralentissons délibéremment le cadence des images parce que nous n'avons que six sprites avec lesquels travailler, et si on en affiche un à chaque 60ième de seconde, notre personnage va bouger beaucoup trop vite! -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}}</p> + À l'intérieur du bloc, on utilise une instruction [`if ... else`](/fr/docs/Web/JavaScript/Reference/Instructions/if...else) pour vérifier si la valeur de `sprite` vaut 5 (le dernier sprite, puisque les numéro de sprite vont de 0 à 5). Si nous sommes en train d'afficher le dernier sprite, alors on réinitialilse `sprite` à 0; sinon on l'incrémente de 1. -<div class="note"> -<p><strong>Note :</strong> Le code final est disponible sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html">7_canvas_walking_animation.html</a>.</p> -</div> +9. Ensuite, nous devons déterminer comment modifier la valeur de `posX` sur chaque image — ajoutez le bloc de code à la suite: -<h3 id="Une_application_simple_de_dessin">Une application simple de dessin</h3> + ```js + if(posX > width/2) { + newStartPos = -((width/2) + 102); + posX = Math.ceil(newStartPos / 13) * 13; + console.log(posX); + } else { + posX += 2; + } + ``` -<p>Comme exemple final d'animation, nous aimerions vous montrer une application très simple de dessin, pour illustrer comment la boucle d'animation peut être combinée avec les entrées de l'utilisateur (comme le mouvement de la souris en l'occurence). Nous n'allons pas expliquer la procédure pas à pas pour construire cette application, nous allons juste explorer les parties les plus intéressantes du code.</p> + Nous utilisons une autre instruction `if ... else` pour voir si la valeur de `posX` est plus grande que `width/2`, ce qui signifie que notre personnage est sortit du bord droit de l'écran. Si c'est le cas, on calcule la position qui met le personnage à gauche du bord gauche de l'écran, et on définit `posX` au multiple de 13 le plus proche de ce nombre. Il faut obligatoirement un multiple de 13 pour que le bloc de code précédent puisse toujours fonctionner! -<p>L'exemple peut être trouvé sur GitHub, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/8_canvas_drawing_app.html">8_canvas_drawing_app.html</a>, et vous pouvez jouer avec en direct ci-dessous:</p> + Si notre personnage n'a pas atteint le bord de l'écran, on incrémente `posX` de 2. Cela le fera bouger un peu vers la droite la prochaine fois qu'on le dessinera. -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/8_canvas_drawing_app.html", '100%', 600)}}</p> +10. Finalement, nous devons boucler sur l'animation en appelannt {{domxref("window.requestAnimationFrame", "requestAnimationFrame()")}} en bas de la fonction `draw()`: -<p>Regardons les parties les plus intéressantes. Tout d'abord, nous gardons une trace des coordonnées X et Y de la souris et si elle est pressée ou non grâce à trois variables: <code>curX</code>, <code>curY</code>, et <code>pressed</code>. Quand la souris bouge, nous déclenchons une fonction via le gestionnaire d'événement <code>onmousemove</code>, lequel capture les valeurs X et Y actuelles. Nous utilisons également les gestionnaires d'événement <code>onmousedown</code> et <code>onmouseup</code> pour changer la valeur de <code>pressed</code> à <code>true</code> quand le bouton de la souris est pressé, et de nouveau à <code>false</code> quand il est relaché.</p> + ```js + window.requestAnimationFrame(draw); + ``` -<pre class="brush: js">var curX; +Et voilà! L'exemple final devrait ressembler à ça: + +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}} + +> **Note :** Le code final est disponible sur GitHub, [7_canvas_walking_animation.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html). + +### Une application simple de dessin + +Comme exemple final d'animation, nous aimerions vous montrer une application très simple de dessin, pour illustrer comment la boucle d'animation peut être combinée avec les entrées de l'utilisateur (comme le mouvement de la souris en l'occurence). Nous n'allons pas expliquer la procédure pas à pas pour construire cette application, nous allons juste explorer les parties les plus intéressantes du code. + +L'exemple peut être trouvé sur GitHub, [8_canvas_drawing_app.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/loops_animation/8_canvas_drawing_app.html), et vous pouvez jouer avec en direct ci-dessous: + +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/8_canvas_drawing_app.html", '100%', 600)}} + +Regardons les parties les plus intéressantes. Tout d'abord, nous gardons une trace des coordonnées X et Y de la souris et si elle est pressée ou non grâce à trois variables: `curX`, `curY`, et `pressed`. Quand la souris bouge, nous déclenchons une fonction via le gestionnaire d'événement `onmousemove`, lequel capture les valeurs X et Y actuelles. Nous utilisons également les gestionnaires d'événement `onmousedown` et `onmouseup` pour changer la valeur de `pressed` à `true` quand le bouton de la souris est pressé, et de nouveau à `false` quand il est relaché. + +```js +var curX; var curY; var pressed = false; @@ -728,18 +690,22 @@ canvas.onmousedown = function() { canvas.onmouseup = function() { pressed = false; -}</pre> +} +``` -<p>Quand le bouton "Clear canvas" (effacer le canvas) est cliqué, nous exécutons une simple fonction qui efface entièrement le canvas grâce à un rectangle noir, de la même manière que nous avons vu précédemment:</p> +Quand le bouton "Clear canvas" (effacer le canvas) est cliqué, nous exécutons une simple fonction qui efface entièrement le canvas grâce à un rectangle noir, de la même manière que nous avons vu précédemment: -<pre class="brush: js">clearBtn.onclick = function() { +```js +clearBtn.onclick = function() { ctx.fillStyle = 'rgb(0, 0, 0)'; ctx.fillRect(0, 0, width, height); -}</pre> +} +``` -<p>La boucle du dessin est relativement simple cette fois-ci — si <code>pressed</code> est à <code>true</code>, nous dessinons un cercle rempli avec la couleur du color picker (sélecteur de couleur), et d'un rayon égal à la valeur définit dans le champs de sélection dans un intervalle.</p> +La boucle du dessin est relativement simple cette fois-ci — si `pressed` est à `true`, nous dessinons un cercle rempli avec la couleur du color picker (sélecteur de couleur), et d'un rayon égal à la valeur définit dans le champs de sélection dans un intervalle. -<pre class="brush: js">function draw() { +```js +function draw() { if(pressed) { ctx.fillStyle = colorPicker.value; ctx.beginPath(); @@ -750,174 +716,157 @@ canvas.onmouseup = function() { requestAnimationFrame(draw); } -draw();</pre> +draw(); +``` -<div class="note"> -<p><strong>Note :</strong> Les types d'{{htmlelement("input")}} <code>range</code> et <code>color</code> sont relativement bien pris en charge parmi les différents navigateurs, à l'exception des versions d'Internet Explorer inférieures à 10; et Safari ne prend pas en charge le type <code>color</code>. Si votre navigateur ne prend pas en charge ces types, il affichera simplement un champ texte et vous n'aurez qu'à entrer des valeurs de couleur et numéro valides vous-mêmes.</p> -</div> +> **Note :** Les types d'{{htmlelement("input")}} `range` et `color` sont relativement bien pris en charge parmi les différents navigateurs, à l'exception des versions d'Internet Explorer inférieures à 10; et Safari ne prend pas en charge le type `color`. Si votre navigateur ne prend pas en charge ces types, il affichera simplement un champ texte et vous n'aurez qu'à entrer des valeurs de couleur et numéro valides vous-mêmes. -<h2 id="WebGL">WebGL</h2> +## WebGL -<p>Il est maintenant temps de laisser la 2D derrière, et de jeter un coup d'oeil au canvas 3D. Le contenu 3D d'un canvas est spécifié en utilisant l'<a href="/fr/Apprendre/WebGL">API WebGL</a>, qui est une API complètement séparée de l'API des canvas 2D, même si ls deux sont affichés sur des éléments {{htmlelement("canvas")}}.</p> +Il est maintenant temps de laisser la 2D derrière, et de jeter un coup d'oeil au canvas 3D. Le contenu 3D d'un canvas est spécifié en utilisant l'[API WebGL](/fr/Apprendre/WebGL), qui est une API complètement séparée de l'API des canvas 2D, même si ls deux sont affichés sur des éléments {{htmlelement("canvas")}}. -<p>WebGL est basé sur le langage de programmation graphique <a href="/fr/docs/Glossaire/OpenGL">OpenGL</a>, et permet de communiquer directement avec le <a href="/fr/docs/Glossaire/GPU">GPU</a> de l'ordinateur. En soi, l'écriture WebGL est plus proche des langages de bas niveau tel que C++ que du JavaScript usuel; c'est assez complexe mais incroyablement puissant.</p> +WebGL est basé sur le langage de programmation graphique [OpenGL](/fr/docs/Glossaire/OpenGL), et permet de communiquer directement avec le [GPU](/fr/docs/Glossaire/GPU) de l'ordinateur. En soi, l'écriture WebGL est plus proche des langages de bas niveau tel que C++ que du JavaScript usuel; c'est assez complexe mais incroyablement puissant. -<h3 id="Utiliser_une_bibliothèque">Utiliser une bibliothèque</h3> +### Utiliser une bibliothèque -<p>De par sa complexité, la plupart des gens écrivent du code de graphique 3D en utilisant une bibliothèque JavaScript tierce telle que <a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js">Three.js</a>, <a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas">PlayCanvas</a> ou <a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Babylon.js">Babylon.js</a>. La plupart d'entre elles fonctionnent d'une manière similaire, offrant des fonctionnalités pour créer des formes primitives et personnalisées, positionner des caméras et des éclairages, recouvrir des surfaces avec des textures et plus encore. Elles se chargent de WebGL pour vous, vous permettant de travailler à un niveau plus haut.</p> +De par sa complexité, la plupart des gens écrivent du code de graphique 3D en utilisant une bibliothèque JavaScript tierce telle que [Three.js](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js), [PlayCanvas](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas) ou [Babylon.js](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Babylon.js). La plupart d'entre elles fonctionnent d'une manière similaire, offrant des fonctionnalités pour créer des formes primitives et personnalisées, positionner des caméras et des éclairages, recouvrir des surfaces avec des textures et plus encore. Elles se chargent de WebGL pour vous, vous permettant de travailler à un niveau plus haut. -<p>Oui, en utiliser une signifie apprendre une autre nouvelle API (une API tierce en l'occurence), mais elles sont beaucoup plus simples que de coder du WebGL brut.</p> +Oui, en utiliser une signifie apprendre une autre nouvelle API (une API tierce en l'occurence), mais elles sont beaucoup plus simples que de coder du WebGL brut. -<h3 id="Recréer_notre_cube">Recréer notre cube</h3> +### Recréer notre cube -<p>Regardons un exemple simple pour créer quelque chose avec une bibliothèque WebGL. Nous allons choisir <a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js">Three.js</a>, puisque c'est l'une des plus populaires. Dans ce tutoriel, nous allons créer le cube 3D qui tourne que nous avons plus tôt.</p> +Regardons un exemple simple pour créer quelque chose avec une bibliothèque WebGL. Nous allons choisir [Three.js](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js), puisque c'est l'une des plus populaires. Dans ce tutoriel, nous allons créer le cube 3D qui tourne que nous avons plus tôt. -<ol> - <li> - <p>Pour commencer, créez une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/threejs-cube/index.html">index.html</a> dans un nouveau répertoire, et sauvegardez <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/threejs-cube/metal003.png">metal003.png</a> dans ce même répertoire. C'est l'image que nous allons utiliser comme texture de surface du cube plus tard.</p> - </li> - <li> - <p>Ensuite, créez un nouveau fichier <code>main.js</code>, toujours dans le même répertoire.</p> - </li> - <li> - <p>Si vous ouvrez <code>index.html</code> dans votre éditeur de texte, vous verrez qu'il y a deux éléments {{htmlelement("script")}} — le premier ajoute <code>three.min.js</code> à la page, et le second ajoute notre fichier <code>main.js</code> à la page. Vous devez <a href="https://raw.githubusercontent.com/mrdoob/three.js/dev/build/three.min.js">télécharger la bibliothèque three.min.js</a> et la sauvegarder dans le même répertoire que précédemment.</p> - </li> - <li> - <p>Maintenant que nous avons inclus <code>three.js</code> dans notre page, nous pouvons commencer à écrire du code JavaScript qui l'utilise dans <code>main.js</code>. Commençons par créer une nouvelle scène — ajoutez ce qui suit dans le fichier <code>main.js</code>:</p> +1. Pour commencer, créez une copie locale de [index.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/threejs-cube/index.html) dans un nouveau répertoire, et sauvegardez [metal003.png](https://github.com/mdn/learning-area/blob/master/javascript/apis/drawing-graphics/threejs-cube/metal003.png) dans ce même répertoire. C'est l'image que nous allons utiliser comme texture de surface du cube plus tard. +2. Ensuite, créez un nouveau fichier `main.js`, toujours dans le même répertoire. +3. Si vous ouvrez `index.html` dans votre éditeur de texte, vous verrez qu'il y a deux éléments {{htmlelement("script")}} — le premier ajoute `three.min.js` à la page, et le second ajoute notre fichier `main.js` à la page. Vous devez [télécharger la bibliothèque three.min.js](https://raw.githubusercontent.com/mrdoob/three.js/dev/build/three.min.js) et la sauvegarder dans le même répertoire que précédemment. +4. Maintenant que nous avons inclus `three.js` dans notre page, nous pouvons commencer à écrire du code JavaScript qui l'utilise dans `main.js`. Commençons par créer une nouvelle scène — ajoutez ce qui suit dans le fichier `main.js`: - <pre class="brush: js">var scene = new THREE.Scene();</pre> + ```js + var scene = new THREE.Scene(); + ``` - <p>Le constructeur <code><a href="https://threejs.org/docs/index.html#api/scenes/Scene">Scene()</a></code> crée une nouvelle scène, qui représente l'ensemble du monde 3D que nous essayons d'afficher.</p> - </li> - <li> - <p>Ensuite, nous avons besoin d'une <strong>caméra</strong> pour voir la scène. En terme d'imagerie 3D, la caméra représente la position du spectateur dans le monde. Pour ajouter une caméra, ajoutez les lignes suivantes à la suite:</p> + Le constructeur [`Scene()`](https://threejs.org/docs/index.html#api/scenes/Scene) crée une nouvelle scène, qui représente l'ensemble du monde 3D que nous essayons d'afficher. - <pre class="brush: js">var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); -camera.position.z = 5; -</pre> +5. Ensuite, nous avons besoin d'une **caméra** pour voir la scène. En terme d'imagerie 3D, la caméra représente la position du spectateur dans le monde. Pour ajouter une caméra, ajoutez les lignes suivantes à la suite: - <p>Le constructeur <code><a href="https://threejs.org/docs/index.html#api/cameras/PerspectiveCamera">PerspectiveCamera()</a></code> prend quatre arguments:</p> + ```js + var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); + camera.position.z = 5; + ``` - <ul> - <li>Le champ de vision: Quelle est la largeur de la zone devant la caméra qui doit être visible à l'écran, en degrés.</li> - <li>Le rapport d'aspect (aspect ratio): Habituellement, c'est le rapport entre la largeur de la scène divisé par la hauteur de la scène. Utiliser une autre valeur va déformer la scène (ce qui pourrait être ce que vous voulez, mais ce n'est généralement pas le cas).</li> - <li>Le plan proche (near plane): Jusqu'où les objets peuvent être proches de la caméra avant que nous arrêtions de les afficher à l'écran. Pensez-y comme quand vous approchez votre doigt de plus en plus près de l'espace entre vos yeux, vous finissez par ne plus le voir.</li> - <li>Le plan éloigné (far plane): Jusqu'à quelle distance de la caméra doit-on afficher les objets.</li> - </ul> + Le constructeur [`PerspectiveCamera()`](https://threejs.org/docs/index.html#api/cameras/PerspectiveCamera) prend quatre arguments: - <p>Nous définissons également la position de la caméra à 5 unités de distance de l'axe Z, qui, comme en CSS, est hors de l'écran vers vous, le spectateur.</p> - </li> - <li> - <p>Le troisième ingrédient essentiel est un moteur de rendu. C'est un objet qui restitue une scène donnée, vu à travers une caméra donnée. Nous allons en créer dès à présent en utilisant le constructeur <code><a href="https://threejs.org/docs/index.html#api/renderers/WebGLRenderer">WebGLRenderer()</a></code> — mais nous ne l'utiliserons que plus tard. Ajoutez les lignes suivantes à la suite de votre JavaScript:</p> + - Le champ de vision: Quelle est la largeur de la zone devant la caméra qui doit être visible à l'écran, en degrés. + - Le rapport d'aspect (aspect ratio): Habituellement, c'est le rapport entre la largeur de la scène divisé par la hauteur de la scène. Utiliser une autre valeur va déformer la scène (ce qui pourrait être ce que vous voulez, mais ce n'est généralement pas le cas). + - Le plan proche (near plane): Jusqu'où les objets peuvent être proches de la caméra avant que nous arrêtions de les afficher à l'écran. Pensez-y comme quand vous approchez votre doigt de plus en plus près de l'espace entre vos yeux, vous finissez par ne plus le voir. + - Le plan éloigné (far plane): Jusqu'à quelle distance de la caméra doit-on afficher les objets. - <pre class="brush: js">var renderer = new THREE.WebGLRenderer(); -renderer.setSize(window.innerWidth, window.innerHeight); -document.body.appendChild(renderer.domElement);</pre> + Nous définissons également la position de la caméra à 5 unités de distance de l'axe Z, qui, comme en CSS, est hors de l'écran vers vous, le spectateur. - <p>La première ligne crée un nouveau moteur de rendu, la deuxième ligne définit la taille à laquelle le moteur de rendu va dessiner la vue de la caméra, et la troisième ligne ajoute l'élément {{htmlelement("canvas")}} crée par le moteur de rendu au {{htmlelement("body")}} du document. Désormais, tout ce que dessine le moteur de rendu sera affiché dans notre fenêtre.</p> - </li> - <li> - <p>Ensuite, nous voulons créer le cube que nous afficherons sur le canvas. Ajoutez le morceau de code suivant au bas de votre JavaScript:</p> +6. Le troisième ingrédient essentiel est un moteur de rendu. C'est un objet qui restitue une scène donnée, vu à travers une caméra donnée. Nous allons en créer dès à présent en utilisant le constructeur [`WebGLRenderer()`](https://threejs.org/docs/index.html#api/renderers/WebGLRenderer) — mais nous ne l'utiliserons que plus tard. Ajoutez les lignes suivantes à la suite de votre JavaScript: - <pre class="brush: js">var cube; + ```js + var renderer = new THREE.WebGLRenderer(); + renderer.setSize(window.innerWidth, window.innerHeight); + document.body.appendChild(renderer.domElement); + ``` -var loader = new THREE.TextureLoader(); + La première ligne crée un nouveau moteur de rendu, la deuxième ligne définit la taille à laquelle le moteur de rendu va dessiner la vue de la caméra, et la troisième ligne ajoute l'élément {{htmlelement("canvas")}} crée par le moteur de rendu au {{htmlelement("body")}} du document. Désormais, tout ce que dessine le moteur de rendu sera affiché dans notre fenêtre. -loader.load( 'metal003.png', function (texture) { - texture.wrapS = THREE.RepeatWrapping; - texture.wrapT = THREE.RepeatWrapping; - texture.repeat.set(2, 2); +7. Ensuite, nous voulons créer le cube que nous afficherons sur le canvas. Ajoutez le morceau de code suivant au bas de votre JavaScript: - var geometry = new THREE.BoxGeometry(2.4, 2.4, 2.4); - var material = new THREE.MeshLambertMaterial( { map: texture, shading: THREE.FlatShading } ); - cube = new THREE.Mesh(geometry, material); - scene.add(cube); + ```js + var cube; - draw(); -});</pre> + var loader = new THREE.TextureLoader(); - <p>Il y a un peu plus à encaisser ici, alors allons-ici par étapes:</p> + loader.load( 'metal003.png', function (texture) { + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + texture.repeat.set(2, 2); - <ul> - <li>Nous créons d'abord une variable globale <code>cube</code> pour pouvoir accéder à notre cube de n'importe où dans notre code.</li> - <li>Ensuite, nous créons un nouvel objet <code><a href="https://threejs.org/docs/index.html#api/loaders/TextureLoader">TextureLoader</a></code>, et appellons <code>load()</code> dessus. La fonction <code>load()</code> prend deux paramètres dans notre exemple (bien qu'elle puisse en prendre plus): la texture que nous voulons charger (notre PNG), et la fonction qui sera exécutée lorsque la texture sera chargée.</li> - <li>À l'intérieur de cette fonction, nous utilisons les propriétés de l'objet <code><a href="https://threejs.org/docs/index.html#api/textures/Texture">texture</a></code> pour spécifier que nous voulons une répétition 2 x 2 de l'image sur tous les côtés du cube.</li> - <li>Ensuite, nous créons un nouvel objet <code><a href="https://threejs.org/docs/index.html#api/geometries/BoxGeometry">BoxGeometry</a></code> et <code><a href="https://threejs.org/docs/index.html#api/materials/MeshLambertMaterial">MeshLambertMaterial</a></code>, que nous passons à un <code><a href="https://threejs.org/docs/index.html#api/objects/Mesh">Mesh</a></code> pour créer notre cube. Typiquement, un objet requiert une géométrie (quelle est sa forme) et un matériau (à quoi ressemble sa surface).</li> - <li>Pour finir, nous ajoutons notre cube à la scène, puis appellons la fonction <code>draw()</code> pour commencer l'animation.</li> - </ul> - </li> - <li> - <p>Avant de définir la fonction <code>draw()</code>, nous allons ajouter quelques lumières à la scène, pour égayer un peu les choses; ajoutez le bloc suivant à la suite de votre code:</p> + var geometry = new THREE.BoxGeometry(2.4, 2.4, 2.4); + var material = new THREE.MeshLambertMaterial( { map: texture, shading: THREE.FlatShading } ); + cube = new THREE.Mesh(geometry, material); + scene.add(cube); - <pre class="brush: js">var light = new THREE.AmbientLight('rgb(255, 255, 255)'); // soft white light -scene.add(light); + draw(); + }); + ``` -var spotLight = new THREE.SpotLight('rgb(255, 255, 255)'); -spotLight.position.set( 100, 1000, 1000 ); -spotLight.castShadow = true; -scene.add(spotLight);</pre> + Il y a un peu plus à encaisser ici, alors allons-ici par étapes: - <p>Un objet <code><a href="https://threejs.org/docs/index.html#api/lights/AmbientLight">AmbientLight</a></code> est une lumière douce qui illumine la scène entière, un peu comme le soleil comme vous êtes dehors. Un objet <code><a href="https://threejs.org/docs/index.html#api/lights/AmbientLight">SpotLight</a></code>, d'autre part, est un faisceau de lumière, plutôt comme une lampe de poche/torche (ou un spotlight - projecteur - en fait).</p> - </li> - <li> - <p>Pour finir, ajoutons notre fonction <code>draw()</code> au bas du code:</p> + - Nous créons d'abord une variable globale `cube` pour pouvoir accéder à notre cube de n'importe où dans notre code. + - Ensuite, nous créons un nouvel objet [`TextureLoader`](https://threejs.org/docs/index.html#api/loaders/TextureLoader), et appellons `load()` dessus. La fonction `load()` prend deux paramètres dans notre exemple (bien qu'elle puisse en prendre plus): la texture que nous voulons charger (notre PNG), et la fonction qui sera exécutée lorsque la texture sera chargée. + - À l'intérieur de cette fonction, nous utilisons les propriétés de l'objet [`texture`](https://threejs.org/docs/index.html#api/textures/Texture) pour spécifier que nous voulons une répétition 2 x 2 de l'image sur tous les côtés du cube. + - Ensuite, nous créons un nouvel objet [`BoxGeometry`](https://threejs.org/docs/index.html#api/geometries/BoxGeometry) et [`MeshLambertMaterial`](https://threejs.org/docs/index.html#api/materials/MeshLambertMaterial), que nous passons à un [`Mesh`](https://threejs.org/docs/index.html#api/objects/Mesh) pour créer notre cube. Typiquement, un objet requiert une géométrie (quelle est sa forme) et un matériau (à quoi ressemble sa surface). + - Pour finir, nous ajoutons notre cube à la scène, puis appellons la fonction `draw()` pour commencer l'animation. - <pre class="brush: js">function draw() { - cube.rotation.x += 0.01; - cube.rotation.y += 0.01; - renderer.render(scene, camera); +8. Avant de définir la fonction `draw()`, nous allons ajouter quelques lumières à la scène, pour égayer un peu les choses; ajoutez le bloc suivant à la suite de votre code: - requestAnimationFrame(draw); -}</pre> + ```js + var light = new THREE.AmbientLight('rgb(255, 255, 255)'); // soft white light + scene.add(light); + + var spotLight = new THREE.SpotLight('rgb(255, 255, 255)'); + spotLight.position.set( 100, 1000, 1000 ); + spotLight.castShadow = true; + scene.add(spotLight); + ``` + + Un objet [`AmbientLight`](https://threejs.org/docs/index.html#api/lights/AmbientLight) est une lumière douce qui illumine la scène entière, un peu comme le soleil comme vous êtes dehors. Un objet [`SpotLight`](https://threejs.org/docs/index.html#api/lights/AmbientLight), d'autre part, est un faisceau de lumière, plutôt comme une lampe de poche/torche (ou un spotlight - projecteur - en fait). + +9. Pour finir, ajoutons notre fonction `draw()` au bas du code: + + ```js + function draw() { + cube.rotation.x += 0.01; + cube.rotation.y += 0.01; + renderer.render(scene, camera); + + requestAnimationFrame(draw); + } + ``` + + C'est assez intuittif: sur chaque image, on fait légèrement tourner notre cube sur ses axes X et Y, affichons la scène telle qu'elle vue par notre caméra, puis appellons `requestAnimationFrame()` pour planifier le dessin de notre prochaine image. - <p>C'est assez intuittif: sur chaque image, on fait légèrement tourner notre cube sur ses axes X et Y, affichons la scène telle qu'elle vue par notre caméra, puis appellons <code>requestAnimationFrame()</code> pour planifier le dessin de notre prochaine image.</p> - </li> -</ol> +Jetons un coup d'oeil rapide au produit fini: -<p>Jetons un coup d'oeil rapide au produit fini:</p> +{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}} -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/threejs-cube/index.html", '100%', 500)}}</p> +Vous pouvez [trouver le code terminé sur GitHub](https://github.com/mdn/learning-area/tree/master/javascript/apis/drawing-graphics/threejs-cube). -<p>Vous pouvez <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/drawing-graphics/threejs-cube">trouver le code terminé sur GitHub</a>.</p> +> **Note :** Dans notre repo GitHub vous pouvez également trouver d'autres exemples 3D intéressants — [Three.js Video Cube](https://github.com/mdn/learning-area/tree/master/javascript/apis/drawing-graphics/threejs-video-cube) ([le voir en direct](https://mdn.github.io/learning-area/javascript/apis/drawing-graphics/threejs-video-cube/)). On utilise {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} pour prendre un flux vidéo à partir d'une webcam de l'ordinateur et le projetons sur le côté du cube comme texture! -<div class="note"> -<p><strong>Note :</strong> Dans notre repo GitHub vous pouvez également trouver d'autres exemples 3D intéressants — <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/drawing-graphics/threejs-video-cube">Three.js Video Cube</a> (<a href="https://mdn.github.io/learning-area/javascript/apis/drawing-graphics/threejs-video-cube/">le voir en direct</a>). On utilise {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} pour prendre un flux vidéo à partir d'une webcam de l'ordinateur et le projetons sur le côté du cube comme texture!</p> -</div> +## Sommaire -<h2 id="Sommaire">Sommaire</h2> +À ce stade, vous devriez avoir une idée utile des bases de la programmation graphique en utilisant Canvas et WebGL et de ce que vous pouvez faire avec ces APIs. Vous pouvez trouver des endroits où aller pour trouver plus d'informations dans la section suivante. Amusez-vous! -<p>À ce stade, vous devriez avoir une idée utile des bases de la programmation graphique en utilisant Canvas et WebGL et de ce que vous pouvez faire avec ces APIs. Vous pouvez trouver des endroits où aller pour trouver plus d'informations dans la section suivante. Amusez-vous!</p> +## Voir aussi -<h2 id="Voir_aussi">Voir aussi</h2> +Nous n'avons couverts dans cet article que les vraies bases du canvas — il y a tellement plus à apprendre! Les articles suivants vous mèneront plus loin. -<p>Nous n'avons couverts dans cet article que les vraies bases du canvas — il y a tellement plus à apprendre! Les articles suivants vous mèneront plus loin.</p> +- [Tutoriel canvas](/fr/docs/Tutoriel_canvas) — Une série de tutoriels très détaillés qui explique ce que vous devriez savoir à propos du canvas 2D de manière beaucoup plus poussée qu'ici. Lecture indispensable. +- [Tutoriel WebGL](/fr/docs/Web/API/WebGL_API/Tutorial) — Une série de tutoriels qui enseigne les bases de la programmation WebGL brute. +- [Construire une démo basique avec Three.js](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js) — tutoriel Three.js basique. Nous avons également les guides équivalents pour [PlayCanvas](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas) et [Babylon.js](/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Babylon.js). +- [Développement de jeux vidéos](/fr/docs/Jeux) — La page d'atterrisage sur MDN pour le développement de jeux web. Il y a quelques tutoriels et techniques disponibles liés au canvas 2D et 3D — voir les options du menu Techniques et Tutoriels. -<ul> - <li><a href="/fr/docs/Tutoriel_canvas">Tutoriel canvas</a> — Une série de tutoriels très détaillés qui explique ce que vous devriez savoir à propos du canvas 2D de manière beaucoup plus poussée qu'ici. Lecture indispensable.</li> - <li><a href="/fr/docs/Web/API/WebGL_API/Tutorial">Tutoriel WebGL</a> — Une série de tutoriels qui enseigne les bases de la programmation WebGL brute.</li> - <li><a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js">Construire une démo basique avec Three.js</a> — tutoriel Three.js basique. Nous avons également les guides équivalents pour <a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas">PlayCanvas</a> et <a href="/fr/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Babylon.js">Babylon.js</a>.</li> - <li><a href="/fr/docs/Jeux">Développement de jeux vidéos</a> — La page d'atterrisage sur MDN pour le développement de jeux web. Il y a quelques tutoriels et techniques disponibles liés au canvas 2D et 3D — voir les options du menu Techniques et Tutoriels.</li> -</ul> +## Exemples -<h2 id="Exemples">Exemples</h2> +- [Violent theramin](https://github.com/mdn/violent-theremin) — Utilise l'API Web Audio pour générer des sons, et Canvas pour générer une visualisation. +- [Voice change-o-matic](https://github.com/mdn/voice-change-o-matic) — Utilise un canvas pour visualiser en temps réel les données audio de l'API Web Audio. -<ul> - <li><a href="https://github.com/mdn/violent-theremin">Violent theramin</a> — Utilise l'API Web Audio pour générer des sons, et Canvas pour générer une visualisation.</li> - <li><a href="https://github.com/mdn/voice-change-o-matic">Voice change-o-matic</a> — Utilise un canvas pour visualiser en temps réel les données audio de l'API Web Audio.</li> -</ul> +{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}} -<p>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</p> -<p> </p> -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul> +- [Introduction aux API du Web](/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler des documents](/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data) +- [APIs tierces](/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des éléments graphiques](/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [APIs vidéo et audio](/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/client-side_web_apis/fetching_data/index.md b/files/fr/learn/javascript/client-side_web_apis/fetching_data/index.md index 9fe8ea07d5..4cc4cf072c 100644 --- a/files/fr/learn/javascript/client-side_web_apis/fetching_data/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/fetching_data/index.md @@ -14,288 +14,303 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Fetching_data original_slug: Apprendre/JavaScript/Client-side_web_APIs/Fetching_data --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> - -<p>Une autre tâche courante dans les sites et applications web modernes est de récupérer des données à partir du serveur pour mettre à jour des sections de la page web sans la recharger entièrement. Ce qui pourrait paraître comme un petit détail a, en vérité, eu un impact énorme sur les performances et le comportement des sites. Dans cet article, nous allons expliquer le concept et les technologies qui rendent cela possible, tels que XMLHttpRequest et l'API Fetch.</p> +Une autre tâche courante dans les sites et applications web modernes est de récupérer des données à partir du serveur pour mettre à jour des sections de la page web sans la recharger entièrement. Ce qui pourrait paraître comme un petit détail a, en vérité, eu un impact énorme sur les performances et le comportement des sites. Dans cet article, nous allons expliquer le concept et les technologies qui rendent cela possible, tels que XMLHttpRequest et l'API Fetch. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Notions de base de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, <a href="/fr/Apprendre/JavaScript/Building_blocks">les briques JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), les <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">notions de bases des APIs côté client</a></td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Apprendre à récupérer des données du serveur web et les utiliser pour mettre à jour le contenu de la page.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Notions de base de JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, + <a href="/fr/Apprendre/JavaScript/Building_blocks" + >les briques JavaScript</a + >, + <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), + les + <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction" + >notions de bases des APIs côté client</a + > + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Apprendre à récupérer des données du serveur web et les utiliser pour + mettre à jour le contenu de la page. + </td> + </tr> + </tbody> </table> -<h2 id="Quel_est_le_problème">Quel est le problème?</h2> +## Quel est le problème? -<p>À la base, le chargement d'une page web est simple — vous envoyez une requête à un serveur et, tant qu'il n'y a pas eu de problème, les ressources de la page web sont téléchargées et affichées sur votre ordinateur.</p> +À la base, le chargement d'une page web est simple — vous envoyez une requête à un serveur et, tant qu'il n'y a pas eu de problème, les ressources de la page web sont téléchargées et affichées sur votre ordinateur. -<p><img alt="A basic representation of a web site architecture" src="web-site-architechture@2x.png"></p> + -<p>Le problème avec ce modèle c'est qu'à chaque fois que vous voulez mettre à jour une partie de la page, par exemple pour afficher la page suivante d'une liste de produits, vous devez recharger toute la page. Ce surcoût est tout à fait inutile et résulte en une mauvaise expérience utilisateur, particulièrement pour les pages qui sont lourdes, complexes et du coup longues à charger.</p> +Le problème avec ce modèle c'est qu'à chaque fois que vous voulez mettre à jour une partie de la page, par exemple pour afficher la page suivante d'une liste de produits, vous devez recharger toute la page. Ce surcoût est tout à fait inutile et résulte en une mauvaise expérience utilisateur, particulièrement pour les pages qui sont lourdes, complexes et du coup longues à charger. -<h3 id="Larrivée_dAjax">L'arrivée d'Ajax</h3> +### L'arrivée d'Ajax -<p>Pour traiter ce problème, des technologies ont été élaborées qui permettent de récupérer à la demande de petites portions de données (comme du <a href="/fr/docs/Web/HTML">HTML</a>, {{glossary("XML")}}, <a href="/fr/docs/Learn/JavaScript/Objects/JSON">JSON</a>, ou texte brut) et de les afficher dans la page web.</p> +Pour traiter ce problème, des technologies ont été élaborées qui permettent de récupérer à la demande de petites portions de données (comme du [HTML](/fr/docs/Web/HTML), {{glossary("XML")}}, [JSON](/fr/docs/Learn/JavaScript/Objects/JSON), ou texte brut) et de les afficher dans la page web. -<p>Nous avons pour cela l'API {{domxref("XMLHttpRequest")}} à notre disposition ou — plus récemment — l'<a href="/fr/docs/Web/API/Fetch_API">API Fetch</a>. Elles permettent de réaliser des requêtes <a href="/fr/docs/Web/HTTP">HTTP</a> pour récupérer des ressources spécifiques disponibles sur un serveur et de formater les données retournées selon les besoins avant l'affichage dans la page.</p> +Nous avons pour cela l'API {{domxref("XMLHttpRequest")}} à notre disposition ou — plus récemment — l'[API Fetch](/fr/docs/Web/API/Fetch_API). Elles permettent de réaliser des requêtes [HTTP](/fr/docs/Web/HTTP) pour récupérer des ressources spécifiques disponibles sur un serveur et de formater les données retournées selon les besoins avant l'affichage dans la page. -<div class="note"> -<p><strong>Note :</strong> Dans les premiers temps, cette technique était appelée "Asynchronous JavaScript and XML" (JavaScript asychrone et XML), dit AJAX, parce qu'elle utilisait {{domxref("XMLHttpRequest")}} pour requêter des données XML. De nos jours, c'est rarement le cas; la plupart du temps, on utilise <code>XMLHttpRequest</code> ou Fetch pour requêter des données JSON. Quoi qu'il en soit, le procédé reste le même et le terme "Ajax" est resté pour décrire cette technique.</p> -</div> +> **Note :** Dans les premiers temps, cette technique était appelée "Asynchronous JavaScript and XML" (JavaScript asychrone et XML), dit AJAX, parce qu'elle utilisait {{domxref("XMLHttpRequest")}} pour requêter des données XML. De nos jours, c'est rarement le cas; la plupart du temps, on utilise `XMLHttpRequest` ou Fetch pour requêter des données JSON. Quoi qu'il en soit, le procédé reste le même et le terme "Ajax" est resté pour décrire cette technique. -<p><img alt="A simple modern architecture for web sites" src="moderne-web-site-architechture@2x.png"></p> + -<p>Le modèle Ajax implique une API web comme proxy pour requêter les données plus intelligemment que simplement rafraîchir la page à chaque fois. Voyons plutôt l'impact que cela a :</p> +Le modèle Ajax implique une API web comme proxy pour requêter les données plus intelligemment que simplement rafraîchir la page à chaque fois. Voyons plutôt l'impact que cela a : -<ol> - <li>Allez sur un site riche en information de votre choix, comme Amazon, YouTube, CNN...</li> - <li>Cherchez quelque chose dans la barre de recherche, comme un nouveau produit. Le contenu principal va changer, mais la plupart de ce qui l'entoure reste statique, comme l'entête, le pied de page, le menu de navigation, etc.</li> -</ol> +1. Allez sur un site riche en information de votre choix, comme Amazon, YouTube, CNN... +2. Cherchez quelque chose dans la barre de recherche, comme un nouveau produit. Le contenu principal va changer, mais la plupart de ce qui l'entoure reste statique, comme l'entête, le pied de page, le menu de navigation, etc. -<p>C'est une bonne chose puisque :</p> +C'est une bonne chose puisque : -<ul> - <li>La mise à jour de la page est beaucoup plus rapide et vous n'avez pas à attendre que la page se rafraîchisse, si bien que le site paraît être plus rapide et plus réactif.</li> - <li>Moins de données doivent être téléchargées pour mettre à jour la page, et donc moins de bande passante est utilisée. Cela ne fait peut-être pas une grande différence sur un ordinateur de bureau, mais cela peut devenir un problème majeur sur mobile ou dans les pays en développement, qui n'ont pas partout un service Internet ultra-rapide.</li> -</ul> +- La mise à jour de la page est beaucoup plus rapide et vous n'avez pas à attendre que la page se rafraîchisse, si bien que le site paraît être plus rapide et plus réactif. +- Moins de données doivent être téléchargées pour mettre à jour la page, et donc moins de bande passante est utilisée. Cela ne fait peut-être pas une grande différence sur un ordinateur de bureau, mais cela peut devenir un problème majeur sur mobile ou dans les pays en développement, qui n'ont pas partout un service Internet ultra-rapide. -<p>Notez que pour accélerer les choses encore davantage, certains sites stockent les ressources et données chez le client lors de sa première visite, si bien que les visites suivantes, les fichiers locaux sont utilisés et non re-téléchargés du serveur. Le contenu n'est rechargé que lorsqu'il a été mis à jour sur le serveur.</p> +Notez que pour accélerer les choses encore davantage, certains sites stockent les ressources et données chez le client lors de sa première visite, si bien que les visites suivantes, les fichiers locaux sont utilisés et non re-téléchargés du serveur. Le contenu n'est rechargé que lorsqu'il a été mis à jour sur le serveur. -<p><img alt="A basic web app data flow architecture" src="web-app-architecture@2x.png"></p> + -<h2 id="Une_requête_Ajax_basique">Une requête Ajax basique</h2> +## Une requête Ajax basique -<p>Voyons maintenant comment ces requêtes sont gérées, en utilisant soit {{domxref("XMLHttpRequest")}} soit <a href="/fr/docs/Web/API/Fetch_API">Fetch</a>. Pour ces exemples, nous allons requêter les données de différents fichiers texte et les utiliserons pour remplir une zone de contenu.</p> +Voyons maintenant comment ces requêtes sont gérées, en utilisant soit {{domxref("XMLHttpRequest")}} soit [Fetch](/fr/docs/Web/API/Fetch_API). Pour ces exemples, nous allons requêter les données de différents fichiers texte et les utiliserons pour remplir une zone de contenu. -<p>Ces fichiers agiront comme une fausse base de données ; dans une vraie application, il est plus probable que vous utiliseriez un langage côté serveur comme PHP, Python, ou Node pour récupérer les données à partir d'une véritable base de données. En revanche, nous voulons ici garder les choses simples ; nous allons donc nous concentrer sur le côté client.</p> +Ces fichiers agiront comme une fausse base de données ; dans une vraie application, il est plus probable que vous utiliseriez un langage côté serveur comme PHP, Python, ou Node pour récupérer les données à partir d'une véritable base de données. En revanche, nous voulons ici garder les choses simples ; nous allons donc nous concentrer sur le côté client. -<h3 id="XMLHttpRequest">XMLHttpRequest</h3> +### XMLHttpRequest -<p><code>XMLHttpRequest</code> (qui est fréquemment abrégé XHR) est une technologie assez vieille maintenant — elle a été inventée par Microsoft dans les années 90 et a été standardisée dans les autres navigateurs il y a longtemps.</p> +`XMLHttpRequest` (qui est fréquemment abrégé XHR) est une technologie assez vieille maintenant — elle a été inventée par Microsoft dans les années 90 et a été standardisée dans les autres navigateurs il y a longtemps. -<ol> - <li> - <p>Pour commencer cet exemple, faites une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/ajax-start.html">ajax-start.html</a> et des quatre fichiers texte — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt">verse1.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt">verse2.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt">verse3.txt</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt">verse4.txt</a> — dans un nouveau répertoire sur votre ordinateur. Dans cet exemple, nous allons charger le verset d'un poème (que vous pourriez bien reconnaître), quand il est sélectionné dans le menu déroulant, en utilisant XHR.</p> - </li> - <li> - <p>À l'intérieur de l'élément {{htmlelement("script")}}, ajoutez le code qui suit. Il stocke une référence aux éléments {{htmlelement("select")}} et {{htmlelement("pre")}} dans des variables et définit un gestionnaire d'événement {{domxref("GlobalEventHandlers.onchange","onchange")}}, pour que, quand la valeur du menu déroulant est changée, la valeur sélectionnée soit passée comme paramètre à la fonction <code>updateDisplay()</code>.</p> +1. Pour commencer cet exemple, faites une copie locale de [ajax-start.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/ajax-start.html) et des quatre fichiers texte — [verse1.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt), [verse2.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt), [verse3.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt), et [verse4.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt) — dans un nouveau répertoire sur votre ordinateur. Dans cet exemple, nous allons charger le verset d'un poème (que vous pourriez bien reconnaître), quand il est sélectionné dans le menu déroulant, en utilisant XHR. +2. À l'intérieur de l'élément {{htmlelement("script")}}, ajoutez le code qui suit. Il stocke une référence aux éléments {{htmlelement("select")}} et {{htmlelement("pre")}} dans des variables et définit un gestionnaire d'événement {{domxref("GlobalEventHandlers.onchange","onchange")}}, pour que, quand la valeur du menu déroulant est changée, la valeur sélectionnée soit passée comme paramètre à la fonction `updateDisplay()`. - <pre class="brush: js">var verseChoose = document.querySelector('select'); -var poemDisplay = document.querySelector('pre'); + ```js + var verseChoose = document.querySelector('select'); + var poemDisplay = document.querySelector('pre'); -verseChoose.onchange = function() { - var verse = verseChoose.value; - updateDisplay(verse); -};</pre> - </li> - <li> - <p>Définissons maintenant la fonction <code>updateDisplay()</code>. Tout d'abord, mettez ce qui suit au bas de votre JavaScript — c'est la structure vide de la fonction :</p> + verseChoose.onchange = function() { + var verse = verseChoose.value; + updateDisplay(verse); + }; + ``` - <pre class="brush: js">function updateDisplay(verse) { +3. Définissons maintenant la fonction `updateDisplay()`. Tout d'abord, mettez ce qui suit au bas de votre JavaScript — c'est la structure vide de la fonction : -};</pre> - </li> - <li> - <p>Nous allons commencer notre fonction en construisant une URL relative qui pointe vers le fichier texte que nous voulons charger, nous en aurons besoin plus tard. La valeur de l'élément {{htmlelement("select")}} à tout instant est la même que l'élément {{htmlelement("option")}} sélectionné (c'est à dire le texte de l'élément sélectionné, ou son attribut <code>value</code> s'il est spécifié) — par exemple "Verse 1". Le fichier correspondant est "verse1.txt" et il est situé dans le même répertoire que le fichier HTML, le nom du fichier seul suffira donc.</p> + ```js + function updateDisplay(verse) { - <p>Les serveurs web sont généralement sensibles à la casse, le nom de fichier n'a pas d'espace et a une extension de fichier. Pour convertir "Verse 1" en "verse1.txt" nous allons convertir le "V" en minuscles avec {{jsxref("String.toLowerCase", "toLowerCase()")}}, supprimer l'espace avec {{jsxref("String.replace", "replace()")}} et ajouter ".txt" à la fin avec une simple <a href="/fr/docs/Learn/JavaScript/First_steps/Strings#Concaténation_de_chaînes">concaténation de chaînes</a>. Ajoutez les lignes suivantes à l'intérieur de la fonction <code>updateDisplay()</code> :</p> + }; + ``` - <pre class="brush: js">verse = verse.replace(" ", ""); -verse = verse.toLowerCase(); -var url = verse + '.txt';</pre> - </li> - <li> - <p>Pour commencer à créer une requête XHR, vous allez devoir créer un nouvel objet avec le constructeur {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}}. Vous pouvez appeler cet objet comme vous le voulez, mais nous l'appellerons <code>request</code> pour plus de clarté. Ajoutez ce qui suit à vos lignes précédentes :</p> +4. Nous allons commencer notre fonction en construisant une URL relative qui pointe vers le fichier texte que nous voulons charger, nous en aurons besoin plus tard. La valeur de l'élément {{htmlelement("select")}} à tout instant est la même que l'élément {{htmlelement("option")}} sélectionné (c'est à dire le texte de l'élément sélectionné, ou son attribut `value` s'il est spécifié) — par exemple "Verse 1". Le fichier correspondant est "verse1.txt" et il est situé dans le même répertoire que le fichier HTML, le nom du fichier seul suffira donc. - <pre class="brush: js">var request = new XMLHttpRequest();</pre> - </li> - <li> - <p>Ensuite, vous allez devoir utiliser la méthode {{domxref("XMLHttpRequest.open","open()")}} pour spécifier la <a href="/fr/docs/Web/HTTP/Méthode">méthode HTTP</a> et l'URL à utiliser pour récupérer la ressource. Nous allons ici utiliser la méthode <code><a href="/fr/docs/Web/HTTP/Méthode/GET">GET</a></code> et passer notre variable <code>url</code> pour URL. Ajoutez ceci à la suite de la ligne précédente :</p> + Les serveurs web sont généralement sensibles à la casse, le nom de fichier n'a pas d'espace et a une extension de fichier. Pour convertir "Verse 1" en "verse1.txt" nous allons convertir le "V" en minuscles avec {{jsxref("String.toLowerCase", "toLowerCase()")}}, supprimer l'espace avec {{jsxref("String.replace", "replace()")}} et ajouter ".txt" à la fin avec une simple [concaténation de chaînes](/fr/docs/Learn/JavaScript/First_steps/Strings#Concaténation_de_chaînes). Ajoutez les lignes suivantes à l'intérieur de la fonction `updateDisplay()` : - <pre class="brush: js">request.open('GET', url);</pre> - </li> - <li> - <p>Nous allons définir le type de réponse que nous attendons — définit par la propriété {{domxref("XMLHttpRequest.responseType", "responseType")}} de la requête — comme <code>text</code>. Ce n'est pas strictement nécessaire ici — XHR retourne du texte par défaut — mais c'est une bonne idée d'en prendre l'habitude pour les cas où vous aurez besoin de définir un type différent. Ajoutez ceci à la suite :</p> + ```js + verse = verse.replace(" ", ""); + verse = verse.toLowerCase(); + var url = verse + '.txt'; + ``` - <pre class="brush: js">request.responseType = 'text';</pre> - </li> - <li> - <p>Récupérer une ressource sur le réseau est une opération {{glossary("asynchronous","asynchrone")}}, ce qui signifie que vous devez attendre que cette opération se termine (par exemple, que la ressource soit renvoyée) avant de pouvoir récupérer la réponse — sans quoi une erreur est levée. XHR permet d'exécuter du code lorsque la réponse est reçue grâce au gestionnaire d'événement {{domxref("XMLHttpRequest.onload", "onload")}} — quand l'événement {{event("load")}} est déclenché. Une fois que la réponse a été reçue, alors la réponse est accessible via la propriété <code>response</code> de l'objet XHR utilisé.</p> +5. Pour commencer à créer une requête XHR, vous allez devoir créer un nouvel objet avec le constructeur {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}}. Vous pouvez appeler cet objet comme vous le voulez, mais nous l'appellerons `request` pour plus de clarté. Ajoutez ce qui suit à vos lignes précédentes : - <p>Ajoutez le bloc de code qui suit toujours au bas de la fonction <code>updateDisplay()</code>. Vous verrez qu'à l'intérieur du gestionnaire d'événément <code>onload</code>, nous assignons la propriété <code><a href="/fr/docs/Web/API/Node/textContent">textContent</a></code> de <code>poemDisplay</code> (l'élément {{htmlelement("pre")}}) à la valeur de la propriété {{domxref("XMLHttpRequest.response", "request.response")}}.</p> + ```js + var request = new XMLHttpRequest(); + ``` - <pre class="brush: js">request.onload = function() { - poemDisplay.textContent = request.response; -};</pre> - </li> - <li> - <p>Les étapes précédentes nous ont permis de configurer la requête XHR, mais celle-ci n'est exécutée que lorsqu'on le demande explicitement. Pour ce faire, il faut appeler la méthode {{domxref("XMLHttpRequest.send","send()")}}. Ajoutez la ligne suivante à la suite du code déjà écrit :</p> +6. Ensuite, vous allez devoir utiliser la méthode {{domxref("XMLHttpRequest.open","open()")}} pour spécifier la [méthode HTTP](/fr/docs/Web/HTTP/Méthode) et l'URL à utiliser pour récupérer la ressource. Nous allons ici utiliser la méthode [`GET`](/fr/docs/Web/HTTP/Méthode/GET) et passer notre variable `url` pour URL. Ajoutez ceci à la suite de la ligne précédente : - <pre class="brush: js">request.send();</pre> + ```js + request.open('GET', url); + ``` - <p>Voyez la section {{anch("Serving your example from a server", "Servir votre exemple depuis un serveur")}} pour pouvoir tester.</p> - </li> - <li> - <p>Un dernier problème avec cet exemple est qu'il ne montre rien au chargement de la page (mais uniquement à la sélection d'un verset). Pour corriger cela, ajoutez ce qui suit au bas de votre code (juste au-dessus de la balise fermante <code></script></code>), pour charger le verset 1 par défaut, et s'assurer que l'élément {{htmlelement("select")}} montre toujours la bonne valeur :</p> +7. Nous allons définir le type de réponse que nous attendons — définit par la propriété {{domxref("XMLHttpRequest.responseType", "responseType")}} de la requête — comme `text`. Ce n'est pas strictement nécessaire ici — XHR retourne du texte par défaut — mais c'est une bonne idée d'en prendre l'habitude pour les cas où vous aurez besoin de définir un type différent. Ajoutez ceci à la suite : - <pre class="brush: js">updateDisplay('Verse 1'); -verseChoose.value = 'Verse 1';</pre> - </li> -</ol> + ```js + request.responseType = 'text'; + ``` -<h3 id="Servir_votre_exemple_depuis_un_serveur">Servir votre exemple depuis un serveur</h3> +8. Récupérer une ressource sur le réseau est une opération {{glossary("asynchronous","asynchrone")}}, ce qui signifie que vous devez attendre que cette opération se termine (par exemple, que la ressource soit renvoyée) avant de pouvoir récupérer la réponse — sans quoi une erreur est levée. XHR permet d'exécuter du code lorsque la réponse est reçue grâce au gestionnaire d'événement {{domxref("XMLHttpRequest.onload", "onload")}} — quand l'événement {{event("load")}} est déclenché. Une fois que la réponse a été reçue, alors la réponse est accessible via la propriété `response` de l'objet XHR utilisé. -<p>Certains navigateurs (dont Chrome) n'exécuteront pas de requêtes XHR si vous exécutez votre script simplement à partir d'un fichier local. Cela est dû à des restrictions de sécurité (pour plus d'infos sur la sécurité web, consultez l'article <a href="/fr/docs/Learn/Server-side/First_steps/Website_security">La sécurité d'un site web</a>).</p> + Ajoutez le bloc de code qui suit toujours au bas de la fonction `updateDisplay()`. Vous verrez qu'à l'intérieur du gestionnaire d'événément `onload`, nous assignons la propriété [`textContent`](/fr/docs/Web/API/Node/textContent) de `poemDisplay` (l'élément {{htmlelement("pre")}}) à la valeur de la propriété {{domxref("XMLHttpRequest.response", "request.response")}}. -<p>Pour règler ce problème, vous devez tester l'exemple à travers un serveur web local. Pour savoir comment procéder, lisez <a href="/fr/Apprendre/Common_questions/configurer_un_serveur_de_test_local">Comment configurer un serveur de test local?</a></p> + ```js + request.onload = function() { + poemDisplay.textContent = request.response; + }; + ``` -<h3 id="Fetch">Fetch</h3> +9. Les étapes précédentes nous ont permis de configurer la requête XHR, mais celle-ci n'est exécutée que lorsqu'on le demande explicitement. Pour ce faire, il faut appeler la méthode {{domxref("XMLHttpRequest.send","send()")}}. Ajoutez la ligne suivante à la suite du code déjà écrit : -<p>L'API Fetch est une solution moderne qui vient remplacer XHR — elle a été introduite récemment dans les navigateurs pour rendre les requêtes HTTP asynchrones plus simples en JavaScript, à la fois pour les développeurs et pour les autres APIs qui utilisent cette technologie.</p> + ```js + request.send(); + ``` -<p>Voyons comment convertir le dernier exemple, en remplaçant XHR par Fetch.</p> + Voyez la section {{anch("Serving your example from a server", "Servir votre exemple depuis un serveur")}} pour pouvoir tester. -<ol> - <li> - <p>Faites une copie du répertoire de votre dernier exemple. (Ou si vous ne l'avez pas fait, créez un nouveau répertoire et copiez le fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html">xhr-basic.html</a> et les quatre fichiers texte — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt">verse1.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt">verse2.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt">verse3.txt</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt">verse4.txt</a> — à l'intérieur).</p> - </li> - <li> - <p>À l'intérieur de la fonction <code>updateDisplay()</code>, vous avez le code XHR suivant :</p> +10. Un dernier problème avec cet exemple est qu'il ne montre rien au chargement de la page (mais uniquement à la sélection d'un verset). Pour corriger cela, ajoutez ce qui suit au bas de votre code (juste au-dessus de la balise fermante `</script>`), pour charger le verset 1 par défaut, et s'assurer que l'élément {{htmlelement("select")}} montre toujours la bonne valeur : - <pre class="brush: js">var request = new XMLHttpRequest(); -request.open('GET', url); -request.responseType = 'text'; + ```js + updateDisplay('Verse 1'); + verseChoose.value = 'Verse 1'; + ``` -request.onload = function() { - poemDisplay.textContent = request.response; -}; +### Servir votre exemple depuis un serveur -request.send();</pre> - </li> - <li> - <p>Remplacez-le avec ce qui suit :</p> +Certains navigateurs (dont Chrome) n'exécuteront pas de requêtes XHR si vous exécutez votre script simplement à partir d'un fichier local. Cela est dû à des restrictions de sécurité (pour plus d'infos sur la sécurité web, consultez l'article [La sécurité d'un site web](/fr/docs/Learn/Server-side/First_steps/Website_security)). - <pre class="brush: js">fetch(url).then(function(response) { - response.text().then(function(text) { - poemDisplay.textContent = text; - }); -});</pre> - </li> - <li> - <p>Chargez l'exemple dans votre navigateur (en l'exécutant à travers un serveur web) et il devrait produire le même résultat que la version XHR — pourvu que vous utilisiez un navigateur moderne.</p> - </li> -</ol> +Pour règler ce problème, vous devez tester l'exemple à travers un serveur web local. Pour savoir comment procéder, lisez [Comment configurer un serveur de test local?](/fr/Apprendre/Common_questions/configurer_un_serveur_de_test_local) + +### Fetch + +L'API Fetch est une solution moderne qui vient remplacer XHR — elle a été introduite récemment dans les navigateurs pour rendre les requêtes HTTP asynchrones plus simples en JavaScript, à la fois pour les développeurs et pour les autres APIs qui utilisent cette technologie. + +Voyons comment convertir le dernier exemple, en remplaçant XHR par Fetch. + +1. Faites une copie du répertoire de votre dernier exemple. (Ou si vous ne l'avez pas fait, créez un nouveau répertoire et copiez le fichier [xhr-basic.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html) et les quatre fichiers texte — [verse1.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt), [verse2.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt), [verse3.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt), and [verse4.txt](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt) — à l'intérieur). +2. À l'intérieur de la fonction `updateDisplay()`, vous avez le code XHR suivant : -<h4 id="Que_se_passe-t-il_dans_le_code_Fetch">Que se passe-t-il dans le code Fetch?</h4> + ```js + var request = new XMLHttpRequest(); + request.open('GET', url); + request.responseType = 'text'; -<p>Tout d'abord, nous invoquons la méthode {{domxref("WindowOrWorkerGlobalScope.fetch()","fetch()")}}, en lui passant l'URL de la ressource que nous voulons récupérer. C'est la version moderne équivalente à {{domxref("XMLHttpRequest.open","request.open()")}} de XHR, et n'avez pas à appeler <code>.send()</code> — la requête est exécutée directemment.</p> + request.onload = function() { + poemDisplay.textContent = request.response; + }; -<p>Ensuite, la méthode {{jsxref("Promise.then",".then()")}} est chaînée à la suite de <code>fetch()</code> — cette méthode fait partie des {{jsxref("Promise","Promesses")}}, une fonctionnalité JavaScript moderne qui permet d'effectuer des opérations asynchrones. <code>fetch()</code> retourne une promesse, qui est résolue lorsque la réponse est reçue du serveur — et nous utilisons <code>.then()</code> pour exécuter du code à ce moment là. C'est l'équivalent du gestionnaire d'événément <code>onload</code> dans la version XHR.</p> + request.send(); + ``` -<p>La fonction définie dans le <code>.then()</code> reçoit la réponse du serveur comme paramètre, une fois que la promesse retournée par <code>fetch()</code> est résolue. À l'intérieur de cette fonction, nous utilisons la méthode {{domxref("Body.text","text()")}} pour récupérer le contenu de la réponse en texte brut. C'est l'équivalent de <code>request.responseType = 'text'</code> dans la version XHR.</p> +3. Remplacez-le avec ce qui suit : -<p>Vous verrez que <code>text()</code> retourne également une promesse, nous y chaînons donc un nouveau <code>.then()</code>, à l'intérieur de quoi nous définissons une fonction. Cette dernière récupère quant à elle le texte brut que la promesse précédente résout.</p> + ```js + fetch(url).then(function(response) { + response.text().then(function(text) { + poemDisplay.textContent = text; + }); + }); + ``` + +4. Chargez l'exemple dans votre navigateur (en l'exécutant à travers un serveur web) et il devrait produire le même résultat que la version XHR — pourvu que vous utilisiez un navigateur moderne. + +#### Que se passe-t-il dans le code Fetch? + +Tout d'abord, nous invoquons la méthode {{domxref("WindowOrWorkerGlobalScope.fetch()","fetch()")}}, en lui passant l'URL de la ressource que nous voulons récupérer. C'est la version moderne équivalente à {{domxref("XMLHttpRequest.open","request.open()")}} de XHR, et n'avez pas à appeler `.send()` — la requête est exécutée directemment. -<p>Enfin, dans le corps de la fonction, nous faisons la même chose que nous faisions dans la version XHR — définir le contenu texte de l'élément {{htmlelement("pre")}} au texte récupéré.</p> +Ensuite, la méthode {{jsxref("Promise.then",".then()")}} est chaînée à la suite de `fetch()` — cette méthode fait partie des {{jsxref("Promise","Promesses")}}, une fonctionnalité JavaScript moderne qui permet d'effectuer des opérations asynchrones. `fetch()` retourne une promesse, qui est résolue lorsque la réponse est reçue du serveur — et nous utilisons `.then()` pour exécuter du code à ce moment là. C'est l'équivalent du gestionnaire d'événément `onload` dans la version XHR. -<h3 id="À_propos_des_promesses">À propos des promesses</h3> +La fonction définie dans le `.then()` reçoit la réponse du serveur comme paramètre, une fois que la promesse retournée par `fetch()` est résolue. À l'intérieur de cette fonction, nous utilisons la méthode {{domxref("Body.text","text()")}} pour récupérer le contenu de la réponse en texte brut. C'est l'équivalent de `request.responseType = 'text'` dans la version XHR. -<p>Les promesses peuvent être un peu déroutantes au premier abord, ne vous en souciez pas trop pour l'instant. Vous vous y ferez après un certain temps, d'autant plus après en avoir appris davantage sur les APIs JavaScript modernes — la plupart des APIs récentes utilisent beaucoup les promesses.</p> +Vous verrez que `text()` retourne également une promesse, nous y chaînons donc un nouveau `.then()`, à l'intérieur de quoi nous définissons une fonction. Cette dernière récupère quant à elle le texte brut que la promesse précédente résout. -<p>Regardons à nouveau la structure d'une promesse pour voir si nous pouvons en donner plus de sens.</p> +Enfin, dans le corps de la fonction, nous faisons la même chose que nous faisions dans la version XHR — définir le contenu texte de l'élément {{htmlelement("pre")}} au texte récupéré. -<h4 id="Promesse_1">Promesse 1</h4> +### À propos des promesses -<pre class="brush: js">fetch(url).then(function(response) { +Les promesses peuvent être un peu déroutantes au premier abord, ne vous en souciez pas trop pour l'instant. Vous vous y ferez après un certain temps, d'autant plus après en avoir appris davantage sur les APIs JavaScript modernes — la plupart des APIs récentes utilisent beaucoup les promesses. + +Regardons à nouveau la structure d'une promesse pour voir si nous pouvons en donner plus de sens. + +#### Promesse 1 + +```js +fetch(url).then(function(response) { //... -});</pre> +}); +``` -<p>Si l'on traduit en bon français les instructions JavaScript, on pourrait dire</p> +Si l'on traduit en bon français les instructions JavaScript, on pourrait dire -<ul> - <li><code>fetch(url)</code> : récupérer la ressource située à l'adresse <code>url</code></li> - <li><code>.then(function() { ... })</code>: quand c'est fait, exécuter la fonction spécifiée</li> -</ul> +- `fetch(url)` : récupérer la ressource située à l'adresse `url` +- `.then(function() { ... })`: quand c'est fait, exécuter la fonction spécifiée -<p>On dit qu'une promesse est "résolue" (resolved) lorsque l'opération spécifiée à un moment donné est terminée. En l'occurence, l'opération spécifiée est de récupérer une ressource à une URL donnée (en utilisant une requête HTTP) et de retourner la réponse reçue du serveur.</p> +On dit qu'une promesse est "résolue" (resolved) lorsque l'opération spécifiée à un moment donné est terminée. En l'occurence, l'opération spécifiée est de récupérer une ressource à une URL donnée (en utilisant une requête HTTP) et de retourner la réponse reçue du serveur. -<p>La fonction passée à <code>then()</code> n'est pas exécutée immédiatement — elle est exécutée à un moment dans le futur, dès que la promesse est résolue (c'est à dire qu'elle a retourné la réponse du serveur).</p> +La fonction passée à `then()` n'est pas exécutée immédiatement — elle est exécutée à un moment dans le futur, dès que la promesse est résolue (c'est à dire qu'elle a retourné la réponse du serveur). -<p>Notez que vous pouvez également choisir de stocker votre promesse dans une variable, et de chaîner le {{jsxref("Promise.then",".then()")}} sur cette variable. L'exemple suivant fait la même chose que le précédent :</p> +Notez que vous pouvez également choisir de stocker votre promesse dans une variable, et de chaîner le {{jsxref("Promise.then",".then()")}} sur cette variable. L'exemple suivant fait la même chose que le précédent : -<pre class="brush: js">var myFetch = fetch(url); +```js +var myFetch = fetch(url); myFetch.then(function(response) { //... -});</pre> +}); +``` -<p>Parce que la méthode <code>fetch()</code> retourne une promesse qui résout une réponse HTTP, la fonction définie à l'intérieur du <code>.then()</code> reçoit la réponse en tant que paramètre. Vous pouvez appeler le paramètre comme vous souhaitez — l'exemple ci-dessous fait toujours la même chose :</p> +Parce que la méthode `fetch()` retourne une promesse qui résout une réponse HTTP, la fonction définie à l'intérieur du `.then()` reçoit la réponse en tant que paramètre. Vous pouvez appeler le paramètre comme vous souhaitez — l'exemple ci-dessous fait toujours la même chose : -<pre class="brush: js">fetch(url).then(function(dogBiscuits) { +```js +fetch(url).then(function(dogBiscuits) { //... -});</pre> +}); +``` -<p>Mais il est plus logique de donner un nom de paramètre qui décrit son contenu !</p> +Mais il est plus logique de donner un nom de paramètre qui décrit son contenu ! -<h4 id="Promesse_2">Promesse 2</h4> +#### Promesse 2 -<p>Voyons maintenant la fonction appelé dans <code>.then()</code>:</p> +Voyons maintenant la fonction appelé dans `.then()`: -<pre class="brush: js">function(response) { +```js +function(response) { response.text().then(function(text) { poemDisplay.textContent = text; }); -}</pre> +} +``` -<p>L'objet <code>response</code> a une méthode {{domxref("Body.text","text()")}}, qui convertit les données brutes contenues dans la réponse en texte brut — c'est le format que nous voulons. Cette méthode retourne également une promesse, qui se résout lorsque la réponse est convertie en texte, nous utilisons donc un deuxième {{jsxref("Promise.then",".then()")}} pour cette deuxième promesse.</p> +L'objet `response` a une méthode {{domxref("Body.text","text()")}}, qui convertit les données brutes contenues dans la réponse en texte brut — c'est le format que nous voulons. Cette méthode retourne également une promesse, qui se résout lorsque la réponse est convertie en texte, nous utilisons donc un deuxième {{jsxref("Promise.then",".then()")}} pour cette deuxième promesse. -<p>À l'intérieur de ce dernier <code>.then()</code>, nous définissons une nouvelle fonction, qui décide de ce que nous faisons avec le texte récupéré. Nous nous contentons de définir la propriété <code><a href="/fr/docs/Web/API/Node/textContent">textContent</a></code> de l'élément {{htmlelement("pre")}} à la valeur du texte.</p> +À l'intérieur de ce dernier `.then()`, nous définissons une nouvelle fonction, qui décide de ce que nous faisons avec le texte récupéré. Nous nous contentons de définir la propriété [`textContent`](/fr/docs/Web/API/Node/textContent) de l'élément {{htmlelement("pre")}} à la valeur du texte. -<h4 id="Chaîner_les_then">Chaîner les then()</h4> +#### Chaîner les then() -<p>Notez que le résultat de la fonction appelée par le <code>.then()</code> est également retourné par ce dernier, nous pouvons donc mettre les <code>.then()</code> bout à bout, en passant le résultat du bloc précédent au prochain.</p> +Notez que le résultat de la fonction appelée par le `.then()` est également retourné par ce dernier, nous pouvons donc mettre les `.then()` bout à bout, en passant le résultat du bloc précédent au prochain. -<p>Ainsi, le bloc de code suivant fait la même chose que notre exemple original, mais écrit dans un style différent :</p> +Ainsi, le bloc de code suivant fait la même chose que notre exemple original, mais écrit dans un style différent : -<pre class="brush: js">fetch(url).then(function(response) { +```js +fetch(url).then(function(response) { return response.text() }).then(function(text) { poemDisplay.textContent = text; -});</pre> +}); +``` -<p>Beaucoup de développeurs préfèrent ce style, plus "plat" : il évite de définir des fonctions à l'intérieur de fonctions et est plus facile à lire lorsqu'il y a beaucoup de promesses qui s'enchaînent. La seule différence ici est que nous avons une instruction <code><a href="/fr/Apprendre/JavaScript/Building_blocks/Return_values">return</a></code> pour retourner <code>response.text()</code>, et ce résultat est passé au prochain <code>.then()</code>.</p> +Beaucoup de développeurs préfèrent ce style, plus "plat" : il évite de définir des fonctions à l'intérieur de fonctions et est plus facile à lire lorsqu'il y a beaucoup de promesses qui s'enchaînent. La seule différence ici est que nous avons une instruction [`return`](/fr/Apprendre/JavaScript/Building_blocks/Return_values) pour retourner `response.text()`, et ce résultat est passé au prochain `.then()`. -<h3 id="Quel_mécanisme_devriez-vous_utiliser">Quel mécanisme devriez-vous utiliser?</h3> +### Quel mécanisme devriez-vous utiliser? -<p>Cela dépend du projet sur lequel vous travaillez. XHR existe depuis longtemps maintenant et bénéficie d'un très bon support sur les différents navigateurs. Fetch et les promesses, en revanche, sont un ajout plus récent à la plateforme web, bien qu'ils soient pris en charge par la plupart des navigateurs, Internet Explorer et Safari font exception.</p> +Cela dépend du projet sur lequel vous travaillez. XHR existe depuis longtemps maintenant et bénéficie d'un très bon support sur les différents navigateurs. Fetch et les promesses, en revanche, sont un ajout plus récent à la plateforme web, bien qu'ils soient pris en charge par la plupart des navigateurs, Internet Explorer et Safari font exception. -<p>Si vous voulez un support des anciens navigateurs, alors XHR est probablement la solution préférable. En revanche, si vous travaillez sur un projet plus progressif, et que vous n'êtes pas tant préoccupé par les anciens navigateurs, alors Fetch peut être un bon choix.</p> +Si vous voulez un support des anciens navigateurs, alors XHR est probablement la solution préférable. En revanche, si vous travaillez sur un projet plus progressif, et que vous n'êtes pas tant préoccupé par les anciens navigateurs, alors Fetch peut être un bon choix. -<p>Vous devriez apprendre les deux alternatives — Fetch deviendra plus populaire au fur et à mesure que l'utilisation d'Internet Explorer diminue (IE n'est plus développé, en faveur du nouveau navigateur de Microsoft, Edge), mais vous allez avoir besoin de XHR pendant un moment encore.</p> +Vous devriez apprendre les deux alternatives — Fetch deviendra plus populaire au fur et à mesure que l'utilisation d'Internet Explorer diminue (IE n'est plus développé, en faveur du nouveau navigateur de Microsoft, Edge), mais vous allez avoir besoin de XHR pendant un moment encore. -<h2 id="Un_exemple_plus_complexe">Un exemple plus complexe</h2> +## Un exemple plus complexe -<p>Pour clore l'article, nous allons regarder un exemple un peu plus complexe, qui montre des utilisations plus intéressantes de Fetch. Nous avons créé un site d'exemple appelé The Can Store (le magasin de conserves) — c'est un supermarché fictif qui ne vend que des boites de conserves. Vous pouvez trouver cet <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/">exemple en direct sur GitHub</a>, et <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/fetching-data/can-store">voir le code source</a>.</p> +Pour clore l'article, nous allons regarder un exemple un peu plus complexe, qui montre des utilisations plus intéressantes de Fetch. Nous avons créé un site d'exemple appelé The Can Store (le magasin de conserves) — c'est un supermarché fictif qui ne vend que des boites de conserves. Vous pouvez trouver cet [exemple en direct sur GitHub](https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/), et [voir le code source](https://github.com/mdn/learning-area/tree/master/javascript/apis/fetching-data/can-store). -<p><img alt="A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column." src="can-store.png"></p> + -<p>Par défaut, le site affiche tous les produits ; mais vous pouvez utiliser le formulaire dans la colonne de gauche pour les filtrer par catégorie, ou chercher un terme, ou les deux.</p> +Par défaut, le site affiche tous les produits ; mais vous pouvez utiliser le formulaire dans la colonne de gauche pour les filtrer par catégorie, ou chercher un terme, ou les deux. -<p>Il y a du code plutôt complexe pour traiter le filtrage des produits par catégorie et par terme de recherche, manipulant les chaînes de caractères pour afficher les données correctement dans l'interface utilisateur, etc. Nous n'allons pas en discuter dans cet article, mais vous pouvez trouver des commentaires très complets dans le code (voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js">can-script.js</a>). Nous allons expliquer le code Fetch.</p> +Il y a du code plutôt complexe pour traiter le filtrage des produits par catégorie et par terme de recherche, manipulant les chaînes de caractères pour afficher les données correctement dans l'interface utilisateur, etc. Nous n'allons pas en discuter dans cet article, mais vous pouvez trouver des commentaires très complets dans le code (voir [can-script.js](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js)). Nous allons expliquer le code Fetch. -<h4 id="Premier_Fetch">Premier Fetch</h4> +#### Premier Fetch -<p>Le premier bloc qui utilise Fetch se trouve au début du JavaScript :</p> +Le premier bloc qui utilise Fetch se trouve au début du JavaScript : -<pre class="brush: js">fetch('products.json').then(function(response) { +```js +fetch('products.json').then(function(response) { if(response.ok) { response.json().then(function(json) { products = json; @@ -304,28 +319,28 @@ myFetch.then(function(response) { } else { console.log('Network request for products.json failed with response ' + response.status + ': ' + response.statusText); } -});</pre> +}); +``` -<p>Cela ressemble à ce que vous avons vu précédemment, sauf que la deuxième promesse est à l'intérieur d'une condition. Cette condition vérifie si la réponse retournée est un succès ou non — la propriété {{domxref("response.ok")}} contient un booléen qui vaut <code>true</code> si le statut de la réponse était OK (<a href="/fr/docs/Web/HTTP/Status/200">statut HTTP 200, "OK"</a>), ou <code>false</code> sinon.</p> +Cela ressemble à ce que vous avons vu précédemment, sauf que la deuxième promesse est à l'intérieur d'une condition. Cette condition vérifie si la réponse retournée est un succès ou non — la propriété {{domxref("response.ok")}} contient un booléen qui vaut `true` si le statut de la réponse était OK ([statut HTTP 200, "OK"](/fr/docs/Web/HTTP/Status/200)), ou `false` sinon. -<p>Si la réponse était un succès, nous déclenchons la deuxième promesse — cette fois-ci en utilisant {{domxref("Body.json","json()")}} et non {{domxref("Body.text","text()")}}, puisque nous voulons récupérer la réponse sous forme de données structurées JSON et non de texte brut.</p> +Si la réponse était un succès, nous déclenchons la deuxième promesse — cette fois-ci en utilisant {{domxref("Body.json","json()")}} et non {{domxref("Body.text","text()")}}, puisque nous voulons récupérer la réponse sous forme de données structurées JSON et non de texte brut. -<p>Si la réponse n'est pas un succès, nous affichons une erreur dans la console indiquant que la requête réseau a échoué, avec le statut et le message obtenus (contenus dans les propriétés {{domxref("response.status")}} et {{domxref("response.statusText")}} respectivement). Bien sûr, un véritable site web traiterait cette erreur plus gracieusement, en affichant un message à l'écran en offrant peut-être des options pour remédier à la situation.</p> +Si la réponse n'est pas un succès, nous affichons une erreur dans la console indiquant que la requête réseau a échoué, avec le statut et le message obtenus (contenus dans les propriétés {{domxref("response.status")}} et {{domxref("response.statusText")}} respectivement). Bien sûr, un véritable site web traiterait cette erreur plus gracieusement, en affichant un message à l'écran en offrant peut-être des options pour remédier à la situation. -<p>Vous pouvez tester le cas d'échec vous-même :</p> +Vous pouvez tester le cas d'échec vous-même : -<ol> - <li>Faites une copie locale des fichiers d'exemple (téléchargez et dézippez le <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true">fichier ZIP can-store</a>)</li> - <li>Éxecutez le code via un serveur web (comme vu précédemment dans {{anch("Serving your example from a server", "Servir votre exemple depuis un serveur")}})</li> - <li>Modifiez le chemin du fichier à récupérer, mettez un nom de fichier qui n'existe pas, comme 'produc.json'.</li> - <li>Maintenant, chargez le fichier index dans votre navigateur (via <code>localhost:8000</code>) et regardez dans la console de développement. Vous verrez un message parmi les lignes "Network request for products.json failed with response 404: File not found" (la requête réseau pour products.json a échoué avec la réponse 404: Fichier non trouvé).</li> -</ol> +1. Faites une copie locale des fichiers d'exemple (téléchargez et dézippez le [fichier ZIP can-store](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true)) +2. Éxecutez le code via un serveur web (comme vu précédemment dans {{anch("Serving your example from a server", "Servir votre exemple depuis un serveur")}}) +3. Modifiez le chemin du fichier à récupérer, mettez un nom de fichier qui n'existe pas, comme 'produc.json'. +4. Maintenant, chargez le fichier index dans votre navigateur (via `localhost:8000`) et regardez dans la console de développement. Vous verrez un message parmi les lignes "Network request for products.json failed with response 404: File not found" (la requête réseau pour products.json a échoué avec la réponse 404: Fichier non trouvé). -<h4 id="Deuxième_Fetch">Deuxième Fetch</h4> +#### Deuxième Fetch -<p>Le deuxième bloc Fetch se trouve dans la fonction <code>fetchBlob()</code>:</p> +Le deuxième bloc Fetch se trouve dans la fonction `fetchBlob()`: -<pre class="brush: js">fetch(url).then(function(response) { +```js +fetch(url).then(function(response) { if(response.ok) { response.blob().then(function(blob) { objectURL = URL.createObjectURL(blob); @@ -334,65 +349,54 @@ myFetch.then(function(response) { } else { console.log('Network request for "' + product.name + '" image failed with response ' + response.status + ': ' + response.statusText); } -});</pre> +}); +``` + +Cela fonctionne à peu près de la même manière que le précédent, sauf qu'au lieu d'utiliser {{domxref("Body.json","json()")}}, on utilise {{domxref("Body.blob","blob()")}} — en l'occurence, nous voulons récupérer la réponse sous la forme d'un fichier image, et le format de données que nous utilisons est [Blob](/fr/docs/Web/API/Blob) — ce terme est une abbréviation de "Binary Large Object" (large objet binaire) et peut être utilisé pour représenter de gros objets fichier — tels que des fichiers images ou vidéo. -<p>Cela fonctionne à peu près de la même manière que le précédent, sauf qu'au lieu d'utiliser {{domxref("Body.json","json()")}}, on utilise {{domxref("Body.blob","blob()")}} — en l'occurence, nous voulons récupérer la réponse sous la forme d'un fichier image, et le format de données que nous utilisons est <a href="/fr/docs/Web/API/Blob">Blob</a> — ce terme est une abbréviation de "Binary Large Object" (large objet binaire) et peut être utilisé pour représenter de gros objets fichier — tels que des fichiers images ou vidéo.</p> +Une fois que nous avons reçu notre blob avec succès, nous créons un objet URL, en utilisant {{domxref("URL.createObjectURL()", "createObjectURL()")}}. Cela renvoie une URL interne temporaire qui pointe vers un blob en mémoire dans le navigateur. Cet objet n'est pas très lisible, mais vous pouvez voir à quoi il ressemble en ouvrant l'application Can Store, Ctrl + Clic droit sur l'image, et sélectionner l'option "Afficher l'image" (peut légèrement varier selon le navigateur que vous utilisez). L'URL créée sera visible à l'intérieur de la barre d'adresse et devrait ressembler à quelque chose comme ça : -<p>Une fois que nous avons reçu notre blob avec succès, nous créons un objet URL, en utilisant {{domxref("URL.createObjectURL()", "createObjectURL()")}}. Cela renvoie une URL interne temporaire qui pointe vers un blob en mémoire dans le navigateur. Cet objet n'est pas très lisible, mais vous pouvez voir à quoi il ressemble en ouvrant l'application Can Store, Ctrl + Clic droit sur l'image, et sélectionner l'option "Afficher l'image" (peut légèrement varier selon le navigateur que vous utilisez). L'URL créée sera visible à l'intérieur de la barre d'adresse et devrait ressembler à quelque chose comme ça :</p> + blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4 -<pre>blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4</pre> +### Challenge : une version XHR de Can Store -<h3 id="Challenge_une_version_XHR_de_Can_Store">Challenge : une version XHR de Can Store</h3> +Comme exercice pratique, nous aimerions que vous essayiez de convertir la version Fetch de l'application en une version XHR. Faites une [copie du fichier ZIP](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true) et essayiez de modifier le JavaScript en conséquence. -<p>Comme exercice pratique, nous aimerions que vous essayiez de convertir la version Fetch de l'application en une version XHR. Faites une <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true">copie du fichier ZIP</a> et essayiez de modifier le JavaScript en conséquence.</p> +Quelques conseils qui pourraient s'avérer utiles : -<p>Quelques conseils qui pourraient s'avérer utiles :</p> +- Vous pourriez trouver la référence {{domxref("XMLHttpRequest")}} utile. +- Vous allez devoir utiliser le même modèle que vous avez vu plus tôt dans l'exemple [XHR-basic.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html). +- Vous devrez ajouter la gestion des erreurs que nous vous avons montré dans la version Fetch de Can Store : -<ul> - <li>Vous pourriez trouver la référence {{domxref("XMLHttpRequest")}} utile.</li> - <li>Vous allez devoir utiliser le même modèle que vous avez vu plus tôt dans l'exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html">XHR-basic.html</a>.</li> - <li>Vous devrez ajouter la gestion des erreurs que nous vous avons montré dans la version Fetch de Can Store : - <ul> - <li>La réponse se situe dans <code>request.response</code> une fois que l'événement <code>load</code> a été déclenché et non dans une promesse.</li> - <li>Le meilleur équivalent à <code>response.ok</code> en XHR est de vérifier si {{domxref("XMLHttpRequest.status","request.status")}} vaut 200 ou si {{domxref("XMLHttpRequest.readyState","request.readyState")}} est égal à 4.</li> - <li>Les propriétés permettant d'obtenir le status et le message en cas d'erreur sont toujours <code>status</code> et <code>statusText</code> mais elles se situent sur l'objet <code>request</code> (XHR) et non sur l'objet <code>response</code>.</li> - </ul> - </li> -</ul> + - La réponse se situe dans `request.response` une fois que l'événement `load` a été déclenché et non dans une promesse. + - Le meilleur équivalent à `response.ok` en XHR est de vérifier si {{domxref("XMLHttpRequest.status","request.status")}} vaut 200 ou si {{domxref("XMLHttpRequest.readyState","request.readyState")}} est égal à 4. + - Les propriétés permettant d'obtenir le status et le message en cas d'erreur sont toujours `status` et `statusText` mais elles se situent sur l'objet `request` (XHR) et non sur l'objet `response`. -<div class="note"> -<p><strong>Note :</strong> Si vous avez des difficultés à le faire, vous pouvez comparer votre code à la version finale sur GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js">voir le code source</a>, ou <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/">voir en direct</a>).</p> -</div> +> **Note :** Si vous avez des difficultés à le faire, vous pouvez comparer votre code à la version finale sur GitHub ([voir le code source](https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js), ou [voir en direct](https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/)). -<h2 id="Sommaire">Sommaire</h2> +## Sommaire -<p>Voilà qui clôt notre article sur la récupération de données à partir du serveur. À ce stade, vous devriez savoir comment travailler avec XHR et Fetch.</p> +Voilà qui clôt notre article sur la récupération de données à partir du serveur. À ce stade, vous devriez savoir comment travailler avec XHR et Fetch. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<p>Il y a beaucoup de sujets abordés dans cet article, dont nous n'avons qu'égratigné la surface. Pour plus de détails sur ces sujets, essayez les articles suivants:</p> +Il y a beaucoup de sujets abordés dans cet article, dont nous n'avons qu'égratigné la surface. Pour plus de détails sur ces sujets, essayez les articles suivants: -<ul> - <li><a href="/fr/docs/Web/Guide/AJAX/Premiers_pas">Ajax — Premiers pas</a></li> - <li><a href="/fr/docs/Web/API/Fetch_API/Using_Fetch">Utiliser Fetch</a></li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise">Promesses</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/JSON">Manipuler des données JSON</a></li> - <li><a href="/fr/docs/Web/HTTP/Aperçu">Un aperçu de HTTP</a></li> - <li><a href="/fr/docs/Learn/Server-side">Programmation de sites web, côté serveur</a></li> -</ul> +- [Ajax — Premiers pas](/fr/docs/Web/Guide/AJAX/Premiers_pas) +- [Utiliser Fetch](/fr/docs/Web/API/Fetch_API/Using_Fetch) +- [Promesses](/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise) +- [Manipuler des données JSON](/fr/docs/Learn/JavaScript/Objects/JSON) +- [Un aperçu de HTTP](/fr/docs/Web/HTTP/Aperçu) +- [Programmation de sites web, côté serveur](/fr/docs/Learn/Server-side) -<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> +{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}} -<div> -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul> -</div> +- [Introduction aux API du Web](/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler des documents](/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data) +- [APIs tierces](/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des éléments graphiques](/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [APIs vidéo et audio](/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/client-side_web_apis/index.md b/files/fr/learn/javascript/client-side_web_apis/index.md index b7ce9e7171..82e3f87488 100644 --- a/files/fr/learn/javascript/client-side_web_apis/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/index.md @@ -18,35 +18,31 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs original_slug: Apprendre/JavaScript/Client-side_web_APIs --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}} -<p>Lorsque vous écrivez du JavaScript côté client pour des sites Web ou des applications, vous n'irez pas très loin avant d'utiliser des API - des interfaces pour manipuler différents aspects du navigateur et du système d'exploitation sur lesquels le site opère, ou même des données provenant d'autres sites web ou services. Dans ce module, nous allons explorer ce que sont les API, et comment utiliser certaines API les plus courantes que vous rencontrerez souvent dans votre travail de développement.</p> +Lorsque vous écrivez du JavaScript côté client pour des sites Web ou des applications, vous n'irez pas très loin avant d'utiliser des API - des interfaces pour manipuler différents aspects du navigateur et du système d'exploitation sur lesquels le site opère, ou même des données provenant d'autres sites web ou services. Dans ce module, nous allons explorer ce que sont les API, et comment utiliser certaines API les plus courantes que vous rencontrerez souvent dans votre travail de développement. -<h2 id="Prérequis">Prérequis</h2> +## Prérequis -<p>Pour tirer le meilleur parti de ce module, vous devriez avoir parcouru les précédents modules JavaScript de la série (<a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a>, <a href="/fr/docs/Learn/JavaScript/Building_blocks">Building blocks</a> et <a href="/fr/docs/Learn/JavaScript/Objects">objets JavaScript</a>). Ces modules impliquent tout de même un bon nombre d'utilisations simples de l'API, car il est difficile d'écrire des exemples JavaScript côté client faisant quelque chose d'utile sans eux! Ici, nous passons à un niveau supérieur, en supposant que vous connaissiez le langage JavaScript de base et explorant les APIs Web courantes de manière un peu plus détaillée.</p> +Pour tirer le meilleur parti de ce module, vous devriez avoir parcouru les précédents modules JavaScript de la série ([Premiers pas](/fr/docs/Learn/JavaScript/First_steps), [Building blocks](/fr/docs/Learn/JavaScript/Building_blocks) et [objets JavaScript](/fr/docs/Learn/JavaScript/Objects)). Ces modules impliquent tout de même un bon nombre d'utilisations simples de l'API, car il est difficile d'écrire des exemples JavaScript côté client faisant quelque chose d'utile sans eux! Ici, nous passons à un niveau supérieur, en supposant que vous connaissiez le langage JavaScript de base et explorant les APIs Web courantes de manière un peu plus détaillée. -<p>Une connaissance basique de <a href="/fr/docs/Learn/HTML">HTML</a> et <a href="/fr/docs/Learn/CSS">CSS</a> serait aussi utile.</p> +Une connaissance basique de [HTML](/fr/docs/Learn/HTML) et [CSS](/fr/docs/Learn/CSS) serait aussi utile. -<div class="note"> -<p><strong>Note :</strong> Si vous travaillez sur un ordinateur/tablette/autre périphérique où vous n'avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer (la plupart) des exemples de code dans un programme de code en ligne tel que <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> -</div> +> **Note :** Si vous travaillez sur un ordinateur/tablette/autre périphérique où vous n'avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer (la plupart) des exemples de code dans un programme de code en ligne tel que [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/). -<h2 id="Guides">Guides</h2> +## Guides -<dl> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></dt> - <dd>Tout d'abord, nous survolerons du concept d'API — qu'est-ce que c'est, comment ça fonctionne, comment les utiliser dans votre code, et comment sont-elles structurées. Nous verrons également quelles sont les principales API et leur utilisation.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></dt> - <dd>Quand on écrit des pages web et des applications, une des choses les plus courantes que l'on veut faire est de manipuler la structure du document d'une manière ou d'une autre. On le fait généralement en utilisant le Document Object Model (DOM), un ensemble d'APIs qui permettent de contrôler le HTML et le style — et qui utilisent massivement l'objet {{domxref("Document")}}. Dans cet article, nous allons voir comment utiliser le DOM en détail, ainsi que quelques APIs intéressantes qui peuvent modifier votre environnement.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></dt> - <dd>Une autre tâche courante dans les sites et applications web modernes est de récupérer des données à partir du serveur pour mettre à jour des sections de la page web sans la recharger entièrement. Ce qui pourrait paraître comme un petit détail, a en vérité eu un impact énorme sur les performances et le comportement des sites. Dans cet article, nous allons expliquer le concept et les technologies qui rendent cela possible, tels que {{domxref("XMLHttpRequest")}} et l'<a href="/fr/docs/Web/API/Fetch_API">API Fetch</a>.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></dt> - <dd>Les APIs que nous avons vu jusqu'à présent sont intégrées dans le navigateur, mais ce n'est pas le cas de toutes. De nombreux gros sites web tels que Google Maps, Twitter, Facebook, PayPal, etc, fournissent des APIs permettant aux développeurs d'utiliser leurs données (par exemple pour afficher un flux twitter sur un blog) ou service (par exemple afficher une carte Google Maps sur un site, ou utiliser Facebook pour permettre aux utilisateurs de se connecter). Cet article compare les APIs du navigateur aux APIs tierces et montre quelques utilisations typiques de ces dernières.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></dt> - <dd>Le navigateur contient des outils de programmation graphique très puissants, du langage <a href="/fr/docs/Web/SVG">SVG</a> (Scalable Vector Graphics), aux APIs pour dessiner sur les éléments HTML {{htmlelement("canvas")}}, (voir <a href="/fr/docs/Web/HTML/Canvas">API Canvas</a> et <a href="/fr/docs/Web/API/WebGL_API">WebGL</a>). Cet article fournit une introduction à canvas et introduit d'autres ressources pour vous permettre d'en apprendre plus.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></dt> - <dd>HTML5 fournit des éléments pour intégrer du multimédia dans les documents — {{htmlelement("video")}} et {{htmlelement("audio")}} — et qui viennent avec leurs propres APIs pour contrôler la lecture, se déplacer dans le flux, etc<em>. </em>Cet article montre comment réaliser les tâches les plus communes, comme créer des contrôles de lectures personnalisés.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></dt> - <dd>Les navigateurs web modernes permettent aux sites web de stocker des données sur l'ordinateur de l'utilisateur — avec sa permission — puis de les récupérer au besoin. Cela permet d'enregistrer des données pour du stockage long-terme, de sauvegarder des documents ou sites hors-ligne, de conserver des préférences spécifiques à l'utilisateur, et plus encore. Cet article explique les fondamentaux pour y parvenir.</dd> -</dl> +- [Introduction aux API du Web](/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction) + - : Tout d'abord, nous survolerons du concept d'API — qu'est-ce que c'est, comment ça fonctionne, comment les utiliser dans votre code, et comment sont-elles structurées. Nous verrons également quelles sont les principales API et leur utilisation. +- [Manipuler des documents](/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents) + - : Quand on écrit des pages web et des applications, une des choses les plus courantes que l'on veut faire est de manipuler la structure du document d'une manière ou d'une autre. On le fait généralement en utilisant le Document Object Model (DOM), un ensemble d'APIs qui permettent de contrôler le HTML et le style — et qui utilisent massivement l'objet {{domxref("Document")}}. Dans cet article, nous allons voir comment utiliser le DOM en détail, ainsi que quelques APIs intéressantes qui peuvent modifier votre environnement. +- [Récupérer des données du serveur](/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data) + - : Une autre tâche courante dans les sites et applications web modernes est de récupérer des données à partir du serveur pour mettre à jour des sections de la page web sans la recharger entièrement. Ce qui pourrait paraître comme un petit détail, a en vérité eu un impact énorme sur les performances et le comportement des sites. Dans cet article, nous allons expliquer le concept et les technologies qui rendent cela possible, tels que {{domxref("XMLHttpRequest")}} et l'[API Fetch](/fr/docs/Web/API/Fetch_API). +- [APIs tierces](/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs) + - : Les APIs que nous avons vu jusqu'à présent sont intégrées dans le navigateur, mais ce n'est pas le cas de toutes. De nombreux gros sites web tels que Google Maps, Twitter, Facebook, PayPal, etc, fournissent des APIs permettant aux développeurs d'utiliser leurs données (par exemple pour afficher un flux twitter sur un blog) ou service (par exemple afficher une carte Google Maps sur un site, ou utiliser Facebook pour permettre aux utilisateurs de se connecter). Cet article compare les APIs du navigateur aux APIs tierces et montre quelques utilisations typiques de ces dernières. +- [Dessiner des éléments graphiques](/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics) + - : Le navigateur contient des outils de programmation graphique très puissants, du langage [SVG](/fr/docs/Web/SVG) (Scalable Vector Graphics), aux APIs pour dessiner sur les éléments HTML {{htmlelement("canvas")}}, (voir [API Canvas](/fr/docs/Web/HTML/Canvas) et [WebGL](/fr/docs/Web/API/WebGL_API)). Cet article fournit une introduction à canvas et introduit d'autres ressources pour vous permettre d'en apprendre plus. +- [APIs vidéo et audio](/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) + - : HTML5 fournit des éléments pour intégrer du multimédia dans les documents — {{htmlelement("video")}} et {{htmlelement("audio")}} — et qui viennent avec leurs propres APIs pour contrôler la lecture, se déplacer dans le flux, etc*.* Cet article montre comment réaliser les tâches les plus communes, comme créer des contrôles de lectures personnalisés. +- [Stockage côté client](/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage) + - : Les navigateurs web modernes permettent aux sites web de stocker des données sur l'ordinateur de l'utilisateur — avec sa permission — puis de les récupérer au besoin. Cela permet d'enregistrer des données pour du stockage long-terme, de sauvegarder des documents ou sites hors-ligne, de conserver des préférences spécifiques à l'utilisateur, et plus encore. Cet article explique les fondamentaux pour y parvenir. diff --git a/files/fr/learn/javascript/client-side_web_apis/introduction/index.md b/files/fr/learn/javascript/client-side_web_apis/introduction/index.md index ed8648ce6f..b547ca5265 100644 --- a/files/fr/learn/javascript/client-side_web_apis/introduction/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/introduction/index.md @@ -15,151 +15,151 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Introduction original_slug: Apprendre/JavaScript/Client-side_web_APIs/Introduction --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}} -<div>{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}}</div> - -<p>Tout d'abord, nous verrons dans les grandes lignes ce qu'est une API — leur fonctionnement, comment les utiliser dans votre code, leur structure. Nous verrons également quelles sont les principales API et leur utilisation.</p> +Tout d'abord, nous verrons dans les grandes lignes ce qu'est une API — leur fonctionnement, comment les utiliser dans votre code, leur structure. Nous verrons également quelles sont les principales API et leur utilisation. <table class="standard-table"> <tbody> <tr> <th scope="row">Prérequis :</th> - <td>Des connaissances de base en informatique, une compréhension de base du <a href="/fr/docs/Learn/HTML">HTML</a> et <a href="/fr/docs/Learn/CSS">CSS</a>, des notions de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, <a href="/fr/docs/Learn/JavaScript/Building_blocks">briques JavaScript</a>, <a href="/fr/docs/Learn/JavaScript/Objects">objets JavaScript</a>).</td> + <td> + Des connaissances de base en informatique, une compréhension de base du + <a href="/fr/docs/Learn/HTML">HTML</a> et + <a href="/fr/docs/Learn/CSS">CSS</a>, des notions de JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, + <a href="/fr/docs/Learn/JavaScript/Building_blocks" + >briques JavaScript</a + >, <a href="/fr/docs/Learn/JavaScript/Objects">objets JavaScript</a>). + </td> </tr> <tr> <th scope="row">Objectif :</th> - <td>Vous familiariser avec les API, ce qu'elles permettent de faire, et comment les utiliser dans votre code.</td> + <td> + Vous familiariser avec les API, ce qu'elles permettent de faire, et + comment les utiliser dans votre code. + </td> </tr> </tbody> </table> -<h2 id="what_are_apis">Qu'est-ce qu'une API ?</h2> +## Qu'est-ce qu'une API ? -<p>Les API (<i>Application Programming Interfaces</i> soit « interface de programmation d'application ») sont des constructions disponibles dans les langages de programmation pour permettre aux développeurs de créer plus facilement des fonctionnalités complexes. Elles s'occupent des parties de code plus complexes, fournissant au développeur une syntaxe plus facile à utiliser à la place.</p> +Les API (_Application Programming Interfaces_ soit « interface de programmation d'application ») sont des constructions disponibles dans les langages de programmation pour permettre aux développeurs de créer plus facilement des fonctionnalités complexes. Elles s'occupent des parties de code plus complexes, fournissant au développeur une syntaxe plus facile à utiliser à la place. -<p>En guise d'exemple concret, pensez à des branchements électriques dans une maison, appartement ou autre logement. Si vous souhaitez utiliser un appareil dans votre maison, il vous suffit de le brancher dans une prise et cela fonctionne. Vous n'essayez pas de le brancher directement à l'alimentation électrique — le faire serait réellement inefficace, et, si vous n'êtes pas électricien, difficile et dangereux à réaliser.</p> +En guise d'exemple concret, pensez à des branchements électriques dans une maison, appartement ou autre logement. Si vous souhaitez utiliser un appareil dans votre maison, il vous suffit de le brancher dans une prise et cela fonctionne. Vous n'essayez pas de le brancher directement à l'alimentation électrique — le faire serait réellement inefficace, et, si vous n'êtes pas électricien, difficile et dangereux à réaliser. -<p><img alt="" src="plug-socket.png"></p> + -<p><em>Source de l'image : <a href="https://www.flickr.com/photos/easy-pics/9518184890/in/photostream/lightbox/">Overloaded plug socket</a> par <a href="https://www.flickr.com/photos/easy-pics/">The Clear Communication People</a>, sur Flickr.</em></p> +_Source de l'image : [Overloaded plug socket](https://www.flickr.com/photos/easy-pics/9518184890/in/photostream/lightbox/) par [The Clear Communication People](https://www.flickr.com/photos/easy-pics/), sur Flickr._ -<p>De la même façon, par exemple, pour programmer des graphismes en 3D, il est beaucoup plus facile de le faire en utilisant une API écrite dans un langage de haut niveau comme JavaScript ou Python, plutôt que d'essayer d'écrire du code bas niveau (comme C ou C ++) qui contrôle directement le GPU de l'ordinateur ou d'autres fonctions graphiques.</p> +De la même façon, par exemple, pour programmer des graphismes en 3D, il est beaucoup plus facile de le faire en utilisant une API écrite dans un langage de haut niveau comme JavaScript ou Python, plutôt que d'essayer d'écrire du code bas niveau (comme C ou C ++) qui contrôle directement le GPU de l'ordinateur ou d'autres fonctions graphiques. -<div class="note"> - <p><strong>Note :</strong> Voir aussi l'<a href="/fr/docs/Glossary/API">entrée du glossaire du terme API</a> pour plus de descriptions.</p> -</div> +> **Note :** Voir aussi l'[entrée du glossaire du terme API](/fr/docs/Glossary/API) pour plus de descriptions. -<h3 id="apis_in_client-side_javascript">API JavaScript côté client</h3> +### API JavaScript côté client -<p>Le JavaScript côté client en particulier a de nombreuses API à sa disposition — elles ne font pas partie du langage JavaScript lui-même, elles sont construites par-dessus JavaScript, offrant des super-pouvoirs supplémentaires à utiliser dans votre code. Elles appartiennent généralement à une des deux catégories :</p> +Le JavaScript côté client en particulier a de nombreuses API à sa disposition — elles ne font pas partie du langage JavaScript lui-même, elles sont construites par-dessus JavaScript, offrant des super-pouvoirs supplémentaires à utiliser dans votre code. Elles appartiennent généralement à une des deux catégories : -<ul> - <li><strong>Les API du navigateur</strong> sont intégrées au navigateur web et permettent de rendre disponibles les données du navigateur et de son environnement afin de réaliser des choses complexes avec. Ainsi, <a href="/fr/docs/Web/API/Web_Audio_API">l'API Web Audio</a> fournit des constructions JavaScript pour manipuler des données audio dans le navigateur. On pourra utiliser cette API afin de récupérer une piste audio puis d'abaisser son volume, d'y appliquer des effets, etc. Sous le capot, c'est le navigateur qui s'occupe des couches plus complexes en code « bas niveau » (C++ ou Rust par exemple) afin de réaliser le traitement du signal. Là encore, cette complexité est masquée par l'abstraction offerte par l'API.</li> - <li><strong>Les API tierces</strong> ne sont pas intégrées au navigateur par défaut, et vous devez généralement récupérer le code de l'API et des informations depuis un site Web.<br> - Par exemple: l'<a href="https://dev.twitter.com/overview/documentation">API Twitter</a> vous permet d'afficher vos derniers tweets sur votre site Web. Elle fournit un ensemble de constructions que vous pouvez utiliser pour interroger le service Twitter et qui renvoie alors les informations demandées.</li> -</ul> +- **Les API du navigateur** sont intégrées au navigateur web et permettent de rendre disponibles les données du navigateur et de son environnement afin de réaliser des choses complexes avec. Ainsi, [l'API Web Audio](/fr/docs/Web/API/Web_Audio_API) fournit des constructions JavaScript pour manipuler des données audio dans le navigateur. On pourra utiliser cette API afin de récupérer une piste audio puis d'abaisser son volume, d'y appliquer des effets, etc. Sous le capot, c'est le navigateur qui s'occupe des couches plus complexes en code « bas niveau » (C++ ou Rust par exemple) afin de réaliser le traitement du signal. Là encore, cette complexité est masquée par l'abstraction offerte par l'API. +- **Les API tierces** ne sont pas intégrées au navigateur par défaut, et vous devez généralement récupérer le code de l'API et des informations depuis un site Web. + Par exemple: l'[API Twitter](https://dev.twitter.com/overview/documentation) vous permet d'afficher vos derniers tweets sur votre site Web. Elle fournit un ensemble de constructions que vous pouvez utiliser pour interroger le service Twitter et qui renvoie alors les informations demandées. -<p><img alt="" src="browser.png"></p> + -<h3 id="relationship_between_javascript_apis_and_other_javascript_tools">Relations entre JavaScript, les API et autres outils JavaScript</h3> +### Relations entre JavaScript, les API et autres outils JavaScript -<p>Ci-dessus, nous avons indiqué ce qu'est une API JavaScript côté client et sa relation avec le langage JavaScript. Pour récapituler, clarifier, et apporter plus de précisions sur d'autres outils JavaScript qui existent:</p> +Ci-dessus, nous avons indiqué ce qu'est une API JavaScript côté client et sa relation avec le langage JavaScript. Pour récapituler, clarifier, et apporter plus de précisions sur d'autres outils JavaScript qui existent: -<ul> - <li>JavaScript — Un langage de programmation de haut niveau intégré aux navigateurs, qui permet de mettre en œuvre des fonctionnalités sur les pages et applications Web. Notez que JavaScript est également disponible dans d'autres environnements de programmation, tels que <a href="/fr/docs/Learn/Server-side/Express_Nodejs/Introduction">Node</a>. Mais ne vous en préoccupez pas pour l'instant.</li> - <li>Les API du navigateur — Constructions intégrées dans le navigateur, situées au‑dessus du langage JavaScript, permettant une mise en œuvre plus facile de fonctionnalités.</li> - <li>Les API tierces — Constructions intégrées à des plateformes tierces (par exemple Twitter, Facebook) qui permettent d'utiliser certaines fonctionnalités de ces plateformes dans vos propres pages Web (par exemple: afficher vos derniers Tweets sur votre page Web).</li> - <li>Les bibliothèques JavaScript — Habituellement, un ou plusieurs fichiers JavaScript contenant des <a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions#custom_functions">fonctions personnalisées</a> que vous pouvez attacher à votre page Web pour accélérer ou activer l'écriture de fonctionnalités courantes. Des exemples incluent jQuery, Mootools et React.</li> - <li>Les <i>frameworks</i> JavaScript — Au‑dessus des bibliothèques, les <i>frameworks</i> JavaScript (par exemple Angular et Ember) sont plutôt des packages de HTML, CSS, JavaScript et autres technologies, que vous installez puis utilisez pour écrire une application web entière.<br> - La différence essentielle entre une bibliothèque et un <i>framework</i> est « l'Inversion du Contrôle ». Avec une bibliothèque, c'est le développeur qui appelle les méthodes de la bibliothèque — il exerce le contrôle. Avec un <i>framework</i>, le contrôle est inversé : c'est le <i>framework</i> qui appelle le code du développeur.</li> -</ul> +- JavaScript — Un langage de programmation de haut niveau intégré aux navigateurs, qui permet de mettre en œuvre des fonctionnalités sur les pages et applications Web. Notez que JavaScript est également disponible dans d'autres environnements de programmation, tels que [Node](/fr/docs/Learn/Server-side/Express_Nodejs/Introduction). Mais ne vous en préoccupez pas pour l'instant. +- Les API du navigateur — Constructions intégrées dans le navigateur, situées au‑dessus du langage JavaScript, permettant une mise en œuvre plus facile de fonctionnalités. +- Les API tierces — Constructions intégrées à des plateformes tierces (par exemple Twitter, Facebook) qui permettent d'utiliser certaines fonctionnalités de ces plateformes dans vos propres pages Web (par exemple: afficher vos derniers Tweets sur votre page Web). +- Les bibliothèques JavaScript — Habituellement, un ou plusieurs fichiers JavaScript contenant des [fonctions personnalisées](/fr/docs/Learn/JavaScript/Building_blocks/Functions#custom_functions) que vous pouvez attacher à votre page Web pour accélérer ou activer l'écriture de fonctionnalités courantes. Des exemples incluent jQuery, Mootools et React. +- Les _frameworks_ JavaScript — Au‑dessus des bibliothèques, les _frameworks_ JavaScript (par exemple Angular et Ember) sont plutôt des packages de HTML, CSS, JavaScript et autres technologies, que vous installez puis utilisez pour écrire une application web entière. + La différence essentielle entre une bibliothèque et un _framework_ est « l'Inversion du Contrôle ». Avec une bibliothèque, c'est le développeur qui appelle les méthodes de la bibliothèque — il exerce le contrôle. Avec un _framework_, le contrôle est inversé : c'est le _framework_ qui appelle le code du développeur. -<h2 id="what_can_apis_do">Que peuvent faire les API ?</h2> +## Que peuvent faire les API ? -<p>Il y a un beaucoup d'API disponibles dans les navigateurs modernes. Elles permettent de faire un large éventail de choses. Vous pouvez vous en faire une petite idée en jetant un coup d'œil à la <a href="/fr/docs/Web/API">page de l'index des API MDN</a>.</p> +Il y a un beaucoup d'API disponibles dans les navigateurs modernes. Elles permettent de faire un large éventail de choses. Vous pouvez vous en faire une petite idée en jetant un coup d'œil à la [page de l'index des API MDN](/fr/docs/Web/API). -<h3 id="common_browser_apis">API de navigateur courantes</h3> +### API de navigateur courantes -<p>En particulier, voici les catégories d'API de navigateur les plus courantes que vous utiliserez (et que nous allons voir dans ce module plus en détail) :</p> +En particulier, voici les catégories d'API de navigateur les plus courantes que vous utiliserez (et que nous allons voir dans ce module plus en détail) : -<ul> - <li><strong>Les API pour manipuler des documents</strong> chargés dans le navigateur. L'exemple le plus évident est l'<a href="/fr/docs/Web/API/Document_Object_Model">API DOM (<i>Document Object Model</i>)</a>. Elle permet de manipuler le HTML et CSS — créer, supprimer et modifier du code HTML, appliquer de nouveaux styles à votre page dynamiquement, etc. Par exemple, chaque fois que vous voyez une fenêtre pop-up apparaître sur une page, ou qu'un nouveau contenu affiché, c'est que le DOM est en action. Découvrez-en plus sur ces types d'API dans la rubrique <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a>.</li> - <li><strong>Les API pour récupérer des données du serveur</strong>, afin de mettre à jour des sections d'une page Web, sont couramment utilisées. Ce détail apparemment anodin a eu un impact énorme sur les performances et le comportement des sites — si vous avez juste besoin de mettre à jour une liste de produits ou afficher de nouveaux articles disponibles, le faire instantanément sans avoir à recharger toute la page du serveur peut rendre le site ou l'application beaucoup plus réactif et « accrocheur ». <a href="/fr/docs/Web/API/XMLHttpRequest">XMLHttpRequest </a>et l'<a href="/fr/docs/Web/API/Fetch_API">API Fetch</a> sont les API qui rendent ça possible. Vous verrez aussi peut-être le terme <strong>Ajax</strong> pour qualifier cette technique. Pour en savoir plus sur ces API, voir <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur.</a></li> - <li><strong>Les API pour dessiner et manipuler des graphiques</strong> sont maintenant couramment prises en charge dans les navigateurs — les plus populaires sont <a href="/fr/docs/Web/API/Canvas_API">Canvas </a>et <a href="/fr/docs/Web/API/WebGL_API">WebGL</a>. Elles permettent la mise à jour, par programmation, des pixels contenus dans un élément HTML <a href="/fr/docs/Web/HTML/Element/canvas"><code><canvas></code></a> pour créer des scènes 2D et 3D. Par exemple, vous pouvez dessiner des formes comme des rectangles ou des cercles, importer une image sur le canevas, et lui appliquer un filtre sépia ou niveau de gris à l'aide de l'API Canvas ou encore créer une scène 3D complexe avec éclairage et textures en utilisant WebGL. De telles API sont souvent combinées avec d'autres API, par exemple <a href="/fr/docs/Web/API/Window/requestAnimationFrame"><code>window.requestAnimationFrame()</code></a>, pour créer des boucles d'animation (faire des mises à jour continues de scènes) et ainsi créer des dessins animés et des jeux. Pour en savoir plus sur ces API, voir <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a>.</li> - <li><strong>Les API audio et vidéo</strong> comme <a href="/fr/docs/Web/API/HTMLMediaElement"><code>HTMLMediaElement</code></a>, <a href="/fr/docs/Web/API/Web_Audio_API">Web Audio API</a> ou <a href="/fr/docs/Web/API/WebRTC_API">WebRTC</a>, permettent de faire des choses vraiment intéressantes avec du multimédia, telles que la création de contrôles UI personnalisées pour jouer de l'audio et vidéo, l'affichage de textes comme des légendes et des sous-titres, la récupération de vidéos depuis votre webcam pour l'afficher sur l'ordinateur d'une autre personne dans une visio‑conférence ou encore l'ajout d'effets sur des pistes audio (tels que le gain, la distorsion, la balance, etc.). Pour en savoir plus sur ces API, voir <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">API audio et vidéo</a>.</li> - <li><strong>Les API de périphérique</strong> permettent essentiellement de manier et récupérer des données à partir de périphériques modernes, de manière utile pour les applications Web. Nous avons déjà parlé de l'API de géolocalisation accédant aux données d'emplacement de l'appareil afin que vous puissiez repérer votre position sur une carte. Autres exemples : indiquer à l'utilisateur qu'une mise à jour est disponible pour une application Web via des notifications système (voir l'<a href="/fr/docs/Web/API/Notifications_API">API Notifications</a>) ou des vibrations (voir l'<a href="/fr/docs/Web/API/Vibration_API">API Vibration</a>).</li> - <li><strong>Les API de stockage côté client</strong> deviennent de plus en plus répandues dans les navigateurs Web — la possibilité de stocker des données côté client est très utile si vous souhaitez créer une application qui enregistre son état entre les chargements de page, et peut-être même fonctionner lorsque le périphérique est hors ligne. Il existe un certain nombre d'options disponibles, par exemple le simple stockage nom/valeur avec l'<a href="/fr/docs/Web/API/Web_Storage_API">API Web Storage</a>, et le stockage plus complexe de données tabulaires avec l'<a href="/fr/docs/Web/API/IndexedDB_API">API IndexedDB</a>. Pour en savoir plus sur ces API, voir <a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a>.</li> -</ul> +- **Les API pour manipuler des documents** chargés dans le navigateur. L'exemple le plus évident est l'[API DOM (_Document Object Model_)](/fr/docs/Web/API/Document_Object_Model). Elle permet de manipuler le HTML et CSS — créer, supprimer et modifier du code HTML, appliquer de nouveaux styles à votre page dynamiquement, etc. Par exemple, chaque fois que vous voyez une fenêtre pop-up apparaître sur une page, ou qu'un nouveau contenu affiché, c'est que le DOM est en action. Découvrez-en plus sur ces types d'API dans la rubrique [Manipuler des documents](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents). +- **Les API pour récupérer des données du serveur**, afin de mettre à jour des sections d'une page Web, sont couramment utilisées. Ce détail apparemment anodin a eu un impact énorme sur les performances et le comportement des sites — si vous avez juste besoin de mettre à jour une liste de produits ou afficher de nouveaux articles disponibles, le faire instantanément sans avoir à recharger toute la page du serveur peut rendre le site ou l'application beaucoup plus réactif et « accrocheur ». [XMLHttpRequest ](/fr/docs/Web/API/XMLHttpRequest)et l'[API Fetch](/fr/docs/Web/API/Fetch_API) sont les API qui rendent ça possible. Vous verrez aussi peut-être le terme **Ajax** pour qualifier cette technique. Pour en savoir plus sur ces API, voir [Récupérer des données du serveur.](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data) +- **Les API pour dessiner et manipuler des graphiques** sont maintenant couramment prises en charge dans les navigateurs — les plus populaires sont [Canvas ](/fr/docs/Web/API/Canvas_API)et [WebGL](/fr/docs/Web/API/WebGL_API). Elles permettent la mise à jour, par programmation, des pixels contenus dans un élément HTML [`<canvas>`](/fr/docs/Web/HTML/Element/canvas) pour créer des scènes 2D et 3D. Par exemple, vous pouvez dessiner des formes comme des rectangles ou des cercles, importer une image sur le canevas, et lui appliquer un filtre sépia ou niveau de gris à l'aide de l'API Canvas ou encore créer une scène 3D complexe avec éclairage et textures en utilisant WebGL. De telles API sont souvent combinées avec d'autres API, par exemple [`window.requestAnimationFrame()`](/fr/docs/Web/API/Window/requestAnimationFrame), pour créer des boucles d'animation (faire des mises à jour continues de scènes) et ainsi créer des dessins animés et des jeux. Pour en savoir plus sur ces API, voir [Dessiner des éléments graphiques](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics). +- **Les API audio et vidéo** comme [`HTMLMediaElement`](/fr/docs/Web/API/HTMLMediaElement), [Web Audio API](/fr/docs/Web/API/Web_Audio_API) ou [WebRTC](/fr/docs/Web/API/WebRTC_API), permettent de faire des choses vraiment intéressantes avec du multimédia, telles que la création de contrôles UI personnalisées pour jouer de l'audio et vidéo, l'affichage de textes comme des légendes et des sous-titres, la récupération de vidéos depuis votre webcam pour l'afficher sur l'ordinateur d'une autre personne dans une visio‑conférence ou encore l'ajout d'effets sur des pistes audio (tels que le gain, la distorsion, la balance, etc.). Pour en savoir plus sur ces API, voir [API audio et vidéo](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs). +- **Les API de périphérique** permettent essentiellement de manier et récupérer des données à partir de périphériques modernes, de manière utile pour les applications Web. Nous avons déjà parlé de l'API de géolocalisation accédant aux données d'emplacement de l'appareil afin que vous puissiez repérer votre position sur une carte. Autres exemples : indiquer à l'utilisateur qu'une mise à jour est disponible pour une application Web via des notifications système (voir l'[API Notifications](/fr/docs/Web/API/Notifications_API)) ou des vibrations (voir l'[API Vibration](/fr/docs/Web/API/Vibration_API)). +- **Les API de stockage côté client** deviennent de plus en plus répandues dans les navigateurs Web — la possibilité de stocker des données côté client est très utile si vous souhaitez créer une application qui enregistre son état entre les chargements de page, et peut-être même fonctionner lorsque le périphérique est hors ligne. Il existe un certain nombre d'options disponibles, par exemple le simple stockage nom/valeur avec l'[API Web Storage](/fr/docs/Web/API/Web_Storage_API), et le stockage plus complexe de données tabulaires avec l'[API IndexedDB](/fr/docs/Web/API/IndexedDB_API). Pour en savoir plus sur ces API, voir [Stockage côté client](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage). -<h3 id="common_third-party_apis">API tierces courantes</h3> +### API tierces courantes -<p>Il y a une grande variété d'API tierces ; en voici quelques-unes des plus populaires que vous allez probablement utiliser tôt ou tard :</p> +Il y a une grande variété d'API tierces ; en voici quelques-unes des plus populaires que vous allez probablement utiliser tôt ou tard : -<ul> - <li><a href="https://dev.twitter.com/overview/documentation">L'API Twitter</a> vous permet d'afficher vos derniers tweets sur un site web.</li> - <li>Les API de cartographie comme <a href="https://developer.mapquest.com/">Mapquest</a> et <a href="https://developers.google.com/maps/">Google Maps API</a> vous permettent de réaliser toute sorte de cartes dans des pages web.</li> - <li><a href="https://developers.facebook.com/docs/">L'ensemble d'API de Facebook</a> permet d'utiliser différentes parties de l'écosystème de Facebook dans votre application (par exemple pour la connexion avec un compte Facebook, la gestion des paiements ou de publicité, etc.).</li> - <li><a href="https://core.telegram.org/api">Les API Telegram</a> permettent d'intégrer le contenu de canaux Telegram sur un site web et de prendre en charge les bots.</li> - <li><a href="https://developers.google.com/youtube/">L'API YouTube</a> vous permet d'intégrer des vidéos YouTube sur votre site, de faire des recherches sur YouTube, de construire des listes de lecture, etc.</li> - <li><a href="https://developers.pinterest.com/">L'API Pinterest</a> fournit des outils pour gérer des tableaux et épingles Pinterest et de les inclures à votre site web.</li> - <li><a href="https://www.twilio.com/">L'API Twilio</a> fournit un ensemble d'outil pour intégrer des fonctionnalités d'appels audio et vidéo à une application et/ou d'envoyer des SMS/MMS.</li> - <li><a href="https://docs.joinmastodon.org/api/">L'API Mastodon</a> permet de manipuler les fonctionnalités du réseau social Mastodon grâce à des programmes.</li> - </ul> +- [L'API Twitter](https://dev.twitter.com/overview/documentation) vous permet d'afficher vos derniers tweets sur un site web. +- Les API de cartographie comme [Mapquest](https://developer.mapquest.com/) et [Google Maps API](https://developers.google.com/maps/) vous permettent de réaliser toute sorte de cartes dans des pages web. +- [L'ensemble d'API de Facebook](https://developers.facebook.com/docs/) permet d'utiliser différentes parties de l'écosystème de Facebook dans votre application (par exemple pour la connexion avec un compte Facebook, la gestion des paiements ou de publicité, etc.). +- [Les API Telegram](https://core.telegram.org/api) permettent d'intégrer le contenu de canaux Telegram sur un site web et de prendre en charge les bots. +- [L'API YouTube](https://developers.google.com/youtube/) vous permet d'intégrer des vidéos YouTube sur votre site, de faire des recherches sur YouTube, de construire des listes de lecture, etc. +- [L'API Pinterest](https://developers.pinterest.com/) fournit des outils pour gérer des tableaux et épingles Pinterest et de les inclures à votre site web. +- [L'API Twilio](https://www.twilio.com/) fournit un ensemble d'outil pour intégrer des fonctionnalités d'appels audio et vidéo à une application et/ou d'envoyer des SMS/MMS. +- [L'API Mastodon](https://docs.joinmastodon.org/api/) permet de manipuler les fonctionnalités du réseau social Mastodon grâce à des programmes. -<div class="note"> - <p><strong>Note :</strong> Vous pouvez trouver des informations sur beaucoup plus d'API tierces dans le <a href="http://www.programmableweb.com/category/all/apis">répertoire Programmable Web API.</a></p> -</div> +> **Note :** Vous pouvez trouver des informations sur beaucoup plus d'API tierces dans le [répertoire Programmable Web API.](http://www.programmableweb.com/category/all/apis) -<h2 id="how_do_apis_work">Comment les API fonctionnent-elles ?</h2> +## Comment les API fonctionnent-elles ? -<p>Chaque API JavaScript fonctionne de manière légèrement différente d'une autre, mais de manière générale, elles ont des fonctionnalités communes et des thèmes similaires.</p> +Chaque API JavaScript fonctionne de manière légèrement différente d'une autre, mais de manière générale, elles ont des fonctionnalités communes et des thèmes similaires. -<h3 id="they_are_based_on_objects">Elles sont fondées sur des objets</h3> +### Elles sont fondées sur des objets -<p>Les API interagissent avec le code en utilisant un ou plusieurs <a href="/fr/docs/Learn/JavaScript/Objects">objets JavaScript</a>, qui servent de conteneurs pour les données utilisées par l'API (contenues dans les propriétés d'objet), et la fonctionnalité rendue disponible par l'API (contenue dans des méthodes d'objet).</p> +Les API interagissent avec le code en utilisant un ou plusieurs [objets JavaScript](/fr/docs/Learn/JavaScript/Objects), qui servent de conteneurs pour les données utilisées par l'API (contenues dans les propriétés d'objet), et la fonctionnalité rendue disponible par l'API (contenue dans des méthodes d'objet). -<div class="note"> - <p><strong>Note :</strong> Si vous n'êtes pas déjà familier avec le fonctionnement des objets, vous devriez revenir en arrière et parcourir le module <a href="/fr/docs/Learn/JavaScript/Objects">objets JavaScript</a> avant de continuer.</p> -</div> +> **Note :** Si vous n'êtes pas déjà familier avec le fonctionnement des objets, vous devriez revenir en arrière et parcourir le module [objets JavaScript](/fr/docs/Learn/JavaScript/Objects) avant de continuer. -<p>Prenons comme exemple l'API Web Audio. Il s'agit d'une API assez complexe avec plusieurs objets. Voici les objets principaux :</p> +Prenons comme exemple l'API Web Audio. Il s'agit d'une API assez complexe avec plusieurs objets. Voici les objets principaux : -<ul> - <li><a href="/fr/docs/Web/API/AudioContext"><code>AudioContext</code></a>, qui représente un <a href="/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API#audio_graphs">graphe audio</a> qui peut être utilisé afin de manipuler la lecture audio dans le navigateur et qui possède différentes méthodes et propriétés qui sont disponibles pour manipuler ce signal audio.</li> - <li><li><a href="/fr/docs/Web/API/MediaElementAudioSourceNode"><code>MediaElementAudioSourceNode</code></a>, qui représente un élément <a href="/fr/docs/Web/HTML/Element/audio"><code><audio></code></a> contenant du son qu'on veut jouer et manipuler dans le contexte.</li> - <li><a href="/fr/docs/Web/API/AudioDestinationNode"><code>AudioDestinationNode</code></a>, qui représente la destination de l'audio, c'est-à-dire le composant physique qui sera utilisé pour produire le son (il s'agit généralement des hauts-parleurs ou des écouteurs).</li> -</ul> +- [`AudioContext`](/fr/docs/Web/API/AudioContext), qui représente un [graphe audio](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API#audio_graphs) qui peut être utilisé afin de manipuler la lecture audio dans le navigateur et qui possède différentes méthodes et propriétés qui sont disponibles pour manipuler ce signal audio. +- +- [`MediaElementAudioSourceNode`](/fr/docs/Web/API/MediaElementAudioSourceNode), qui représente un élément [`<audio>`](/fr/docs/Web/HTML/Element/audio) contenant du son qu'on veut jouer et manipuler dans le contexte. +- [`AudioDestinationNode`](/fr/docs/Web/API/AudioDestinationNode), qui représente la destination de l'audio, c'est-à-dire le composant physique qui sera utilisé pour produire le son (il s'agit généralement des hauts-parleurs ou des écouteurs). +Alors comment ces objets interagissent-ils ? Si vous regardez notre exemple [d'élément audio](https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/web-audio/index.html) (regardez‑le [aussi en direct](https://mdn.github.io/learning-area/javascript/apis/introduction/web-audio/)), vous verrez le code suivant : -<p>Alors comment ces objets interagissent-ils ? Si vous regardez notre exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/web-audio/index.html">d'élément audio</a> (regardez‑le <a href="https://mdn.github.io/learning-area/javascript/apis/introduction/web-audio/">aussi en direct</a>), vous verrez le code suivant : </p> +```html +<audio src="outfoxing.mp3"></audio> -<pre class="brush: html"><audio src="outfoxing.mp3"></audio> +<button class="paused">Play</button> +<br> +<input type="range" min="0" max="1" step="0.01" value="1" class="volume"> +``` -<button class="paused">Play</button> -<br> -<input type="range" min="0" max="1" step="0.01" value="1" class="volume"></pre> - -<p>Nous incluons, tout d'abord, un élément <code><audio></code> avec lequel nous intégrons un MP3 dans la page. Nous n'incluons pas de contrôles par défaut du navigateur. Ensuite, nous incluons un <a href="/fr/docs/Web/HTML/Element/Button"><code><button></code></a> que nous utiliserons pour lire et arrêter la musique, et un élément <a href="/fr/docs/Web/HTML/Element/Input"><code><input></code></a> de type range, que nous utiliserons pour ajuster le volume de la piste en cours de lecture.</p> +Nous incluons, tout d'abord, un élément `<audio>` avec lequel nous intégrons un MP3 dans la page. Nous n'incluons pas de contrôles par défaut du navigateur. Ensuite, nous incluons un [`<button>`](/fr/docs/Web/HTML/Element/Button) que nous utiliserons pour lire et arrêter la musique, et un élément [`<input>`](/fr/docs/Web/HTML/Element/Input) de type range, que nous utiliserons pour ajuster le volume de la piste en cours de lecture. -<p>Ensuite, examinons le JavaScript de cet exemple.</p> +Ensuite, examinons le JavaScript de cet exemple. -<p>Nous commençons par créer une instance <code>AudioContext</code> à l'intérieur de laquelle nous allons manipuler notre piste :</p> +Nous commençons par créer une instance `AudioContext` à l'intérieur de laquelle nous allons manipuler notre piste : -<pre class="brush: js">const AudioContext = window.AudioContext || window.webkitAudioContext; -const audioCtx = new AudioContext();</pre> +```js +const AudioContext = window.AudioContext || window.webkitAudioContext; +const audioCtx = new AudioContext(); +``` -<p>Ensuite, nous créons des constantes qui stockent les références à nos éléments <code><audio></code>, <code><button></code> et <code><input></code>, et nous utilisons la méthode <a href="/fr/docs/Web/API/AudioContext/createMediaElementSource"><code>AudioContext.createMediaElementSource()</code></a> pour créer un <code>MediaElementAudioSourceNode</code> représentant la source de notre audio — l'élément <code><audio></code> sera joué à partir de :</p> +Ensuite, nous créons des constantes qui stockent les références à nos éléments `<audio>`, `<button>` et `<input>`, et nous utilisons la méthode [`AudioContext.createMediaElementSource()`](/fr/docs/Web/API/AudioContext/createMediaElementSource) pour créer un `MediaElementAudioSourceNode` représentant la source de notre audio — l'élément `<audio>` sera joué à partir de : -<pre class="brush: js">const audioElement = document.querySelector('audio'); +```js +const audioElement = document.querySelector('audio'); const playBtn = document.querySelector('button'); const volumeSlider = document.querySelector('.volume'); -const audioSource = audioCtx.createMediaElementSource(audioElement);</pre> +const audioSource = audioCtx.createMediaElementSource(audioElement); +``` -<p>Ensuite, nous incluons deux gestionnaires d'événements qui servent à basculer entre la lecture et la pause lorsque le bouton est pressé et à réinitialiser l'affichage au début lorsque la chanson est terminée :</p> +Ensuite, nous incluons deux gestionnaires d'événements qui servent à basculer entre la lecture et la pause lorsque le bouton est pressé et à réinitialiser l'affichage au début lorsque la chanson est terminée : -<pre class="brush: js">// lecture/pause de l'audio +```js +// lecture/pause de l'audio playBtn.addEventListener('click', function() { // vérifier si le contexte est en état de suspension (politique de lecture automatique) if (audioCtx.state === 'suspended') { @@ -183,68 +183,76 @@ playBtn.addEventListener('click', function() { audioElement.addEventListener('ended', function() { playBtn.setAttribute('class', 'paused'); playBtn.textContent = 'Lire'; -});</pre> +}); +``` -<div class="note"> - <p><strong>Note :</strong> Certains d'entre vous ont peut-être remarqué que les méthodes <code>play()</code> et <code>pause()</code> utilisées pour lire et mettre en pause la piste ne font pas partie de l'API audio Web ; elles font partie de l'API <a href="/fr/docs/Web/API/HTMLMediaElement"><code>HTMLMediaElement</code></a>. qui est différente mais étroitement liée.</p> -</div> +> **Note :** Certains d'entre vous ont peut-être remarqué que les méthodes `play()` et `pause()` utilisées pour lire et mettre en pause la piste ne font pas partie de l'API audio Web ; elles font partie de l'API [`HTMLMediaElement`](/fr/docs/Web/API/HTMLMediaElement). qui est différente mais étroitement liée. -<p>Ensuite, nous créons un objet <a href="/fr/docs/Web/API/GainNode"><code>GainNode</code></a> à l'aide de la méthode <a href="/fr/docs/Web/API/BaseAudioContext/createGain"><code>AudioContext.createGain()</code></a>, qui peut être utilisé pour ajuster le volume de l'audio qui le traverse, et nous créons un autre gestionnaire d'événements qui modifie la valeur du gain (volume) du graphique audio lorsque la valeur du curseur est modifiée :</p> +Ensuite, nous créons un objet [`GainNode`](/fr/docs/Web/API/GainNode) à l'aide de la méthode [`AudioContext.createGain()`](/fr/docs/Web/API/BaseAudioContext/createGain), qui peut être utilisé pour ajuster le volume de l'audio qui le traverse, et nous créons un autre gestionnaire d'événements qui modifie la valeur du gain (volume) du graphique audio lorsque la valeur du curseur est modifiée : -<pre class="brush: js">const gainNode = audioCtx.createGain(); +```js +const gainNode = audioCtx.createGain(); volumeSlider.addEventListener('input', function() { gainNode.gain.value = this.value; -});</pre> +}); +``` -<p>La dernière chose à faire pour que cela fonctionne est de connecter les différents nœuds du graphe audio, ce qui est fait en utilisant la méthode <a href="/fr/docs/Web/API/AudioNode/connect"><code>AudioNode.connect()</code></a> disponible sur chaque type de nœud :</p> +La dernière chose à faire pour que cela fonctionne est de connecter les différents nœuds du graphe audio, ce qui est fait en utilisant la méthode [`AudioNode.connect()`](/fr/docs/Web/API/AudioNode/connect) disponible sur chaque type de nœud : -<pre class="brush: js">audioSource.connect(gainNode).connect(audioCtx.destination);</pre> +```js +audioSource.connect(gainNode).connect(audioCtx.destination); +``` -<p>L'audio commence dans la source, qui est ensuite connectée au nœud de gain afin que le volume de l'audio puisse être ajusté. Le nœud de gain est ensuite connecté au nœud de destination afin que le son puisse être lu sur votre ordinateur (la propriété <a href="/fr/docs/Web/API/BaseAudioContext/destination"><code>AudioContext.destination</code></a> représente ce qui est le <a href="/fr/docs/Web/API/AudioDestinationNode"><code>AudioDestinationNode</code></a> par défaut disponible sur le matériel de votre ordinateur, par exemple vos haut-parleurs).</p> +L'audio commence dans la source, qui est ensuite connectée au nœud de gain afin que le volume de l'audio puisse être ajusté. Le nœud de gain est ensuite connecté au nœud de destination afin que le son puisse être lu sur votre ordinateur (la propriété [`AudioContext.destination`](/fr/docs/Web/API/BaseAudioContext/destination) représente ce qui est le [`AudioDestinationNode`](/fr/docs/Web/API/AudioDestinationNode) par défaut disponible sur le matériel de votre ordinateur, par exemple vos haut-parleurs). -<h3 id="they_have_recognizable_entry_points">Elles ont des points d'entrée reconnaissables</h3> +### Elles ont des points d'entrée reconnaissables -<p>Lorsque vous utilisez une API, vous devez vous assurer que vous savez où se trouve le point d'entrée de l'API. Dans l'API Web Audio, c'est assez simple — il s'agit de l'objet <a href="/fr/docs/Web/API/AudioContext"><code>AudioContext</code></a>, qui doit être utilisé pour effectuer toute manipulation audio quelle qu'elle soit.</p> +Lorsque vous utilisez une API, vous devez vous assurer que vous savez où se trouve le point d'entrée de l'API. Dans l'API Web Audio, c'est assez simple — il s'agit de l'objet [`AudioContext`](/fr/docs/Web/API/AudioContext), qui doit être utilisé pour effectuer toute manipulation audio quelle qu'elle soit. -<p>L'API DOM (<i>Document Object Model</i>) a également un point d'entrée simple — ses fonctionnalités ont tendance à être trouvées accrochées à l'objet <a href="/fr/docs/Web/API/Document"><code>Document</code></a>, ou à une instance d'un élément HTML que vous voulez affecter d'une manière ou d'une autre, par exemple :</p> +L'API DOM (_Document Object Model_) a également un point d'entrée simple — ses fonctionnalités ont tendance à être trouvées accrochées à l'objet [`Document`](/fr/docs/Web/API/Document), ou à une instance d'un élément HTML que vous voulez affecter d'une manière ou d'une autre, par exemple : -<pre class="brush: js">const em = document.createElement('em'); // crée un nouvel élément em +```js +const em = document.createElement('em'); // crée un nouvel élément em const para = document.querySelector('p'); // référence à un élément p existant em.textContent = 'Hello there!'; // donne à em du contenu textuel -para.appendChild(em); // intégre em dans le paragraphe</pre> +para.appendChild(em); // intégre em dans le paragraphe +``` -<p>L'API <a href="/fr/docs/Web/API/Canvas_API">Canvas</a> repose également sur l'obtention d'un objet de contexte à utiliser pour manipuler les choses, bien que dans ce cas, il s'agisse d'un contexte graphique plutôt que d'un contexte audio. Son objet de contexte est créé en obtenant une référence à l'élément <a href="/fr/docs/Web/HTML/Element/canvas"><code><canvas></code></a> sur lequel vous voulez dessiner, puis en appelant sa méthode <a href="/fr/docs/Web/API/HTMLCanvasElement/getContext"><code>HTMLCanvasElement.getContext()</code></a> :</p> +L'API [Canvas](/fr/docs/Web/API/Canvas_API) repose également sur l'obtention d'un objet de contexte à utiliser pour manipuler les choses, bien que dans ce cas, il s'agisse d'un contexte graphique plutôt que d'un contexte audio. Son objet de contexte est créé en obtenant une référence à l'élément [`<canvas>`](/fr/docs/Web/HTML/Element/canvas) sur lequel vous voulez dessiner, puis en appelant sa méthode [`HTMLCanvasElement.getContext()`](/fr/docs/Web/API/HTMLCanvasElement/getContext) : -<pre class="brush: js">const canvas = document.querySelector('canvas'); -const ctx = canvas.getContext('2d');</pre> +```js +const canvas = document.querySelector('canvas'); +const ctx = canvas.getContext('2d'); +``` -<p>Tout ce que nous voulons faire au canevas est ensuite réalisé en appelant les propriétés et les méthodes de l'objet contexte (qui est une instance de <a href="/fr/docs/Web/API/CanvasRenderingContext2D"><code>CanvasRenderingContext2D</code></a>), par exemple :</p> +Tout ce que nous voulons faire au canevas est ensuite réalisé en appelant les propriétés et les méthodes de l'objet contexte (qui est une instance de [`CanvasRenderingContext2D`](/fr/docs/Web/API/CanvasRenderingContext2D)), par exemple : -<pre class="brush: js">Ball.prototype.draw = function() { +```js +Ball.prototype.draw = function() { ctx.beginPath(); ctx.fillStyle = this.color; ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); ctx.fill(); -};</pre> +}; +``` -<div class="note"> - <p><strong>Note :</strong> Vous pouvez voir ce code en action dans notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/bouncing-balls.html">démo de balles rebondissantes</a> (voyez-le fonctionner <a href="https://mdn.github.io/learning-area/javascript/apis/introduction/bouncing-balls.html">en direct</a> également).</p> -</div> +> **Note :** Vous pouvez voir ce code en action dans notre [démo de balles rebondissantes](https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/bouncing-balls.html) (voyez-le fonctionner [en direct](https://mdn.github.io/learning-area/javascript/apis/introduction/bouncing-balls.html) également). -<h3 id="they_use_events_to_handle_changes_in_state">Elles utilisent des événements pour gérer les changements d'état</h3> +### Elles utilisent des événements pour gérer les changements d'état -<p>Nous avons déjà abordé les événements plus tôt dans le cours dans notre article <a href="/fr/docs/Learn/JavaScript/Building_blocks/Events">Introduction aux événements</a>, qui examine en détail ce que sont les événements web côté client et comment ils sont utilisés dans votre code. Si vous n'êtes pas déjà familiarisé avec le fonctionnement des événements de l'API Web côté client, nous vous conseillons de lire cet article avant de poursuivre.</p> +Nous avons déjà abordé les événements plus tôt dans le cours dans notre article [Introduction aux événements](/fr/docs/Learn/JavaScript/Building_blocks/Events), qui examine en détail ce que sont les événements web côté client et comment ils sont utilisés dans votre code. Si vous n'êtes pas déjà familiarisé avec le fonctionnement des événements de l'API Web côté client, nous vous conseillons de lire cet article avant de poursuivre. -<p>Certaines API Web ne contiennent aucun événement, mais la plupart en contiennent au moins quelques-uns. Les propriétés des gestionnaires qui nous permettent d'exécuter des fonctions lorsque des événements se produisent sont généralement répertoriées dans notre matériel de référence dans des sections distinctes intitulées « Gestionnaires d'événements ».</p> +Certaines API Web ne contiennent aucun événement, mais la plupart en contiennent au moins quelques-uns. Les propriétés des gestionnaires qui nous permettent d'exécuter des fonctions lorsque des événements se produisent sont généralement répertoriées dans notre matériel de référence dans des sections distinctes intitulées « Gestionnaires d'événements ». -<p>Nous avons déjà vu un certain nombre de gestionnaires d'événements utilisés dans notre exemple d'API audio Web ci-dessus.</p> +Nous avons déjà vu un certain nombre de gestionnaires d'événements utilisés dans notre exemple d'API audio Web ci-dessus. -<p>Pour fournir un autre exemple, les instances de l'objet <a href="/fr/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a> (chacune représente une requête HTTP au serveur pour récupérer une nouvelle ressource d'un certain type) a un certain nombre d'événements disponibles sur eux, par exemple, l'événement <code>load</code> est déclenché lorsqu'une réponse a été renvoyée avec succès contenant la ressource demandée, et qu'elle est désormais disponible.</p> +Pour fournir un autre exemple, les instances de l'objet [`XMLHttpRequest`](/fr/docs/Web/API/XMLHttpRequest) (chacune représente une requête HTTP au serveur pour récupérer une nouvelle ressource d'un certain type) a un certain nombre d'événements disponibles sur eux, par exemple, l'événement `load` est déclenché lorsqu'une réponse a été renvoyée avec succès contenant la ressource demandée, et qu'elle est désormais disponible. -<p>Le code suivant fournit un exemple simple de la façon dont cela peut être utilisé :</p> +Le code suivant fournit un exemple simple de la façon dont cela peut être utilisé : -<pre class="brush: js">let requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json'; +```js +let requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json'; let request = new XMLHttpRequest(); request.open('GET', requestURL); request.responseType = 'json'; @@ -254,44 +262,39 @@ request.onload = function() { const superHeroes = request.response; populateHeader(superHeroes); showHeroes(superHeroes); -}</pre> +} +``` -<div class="note"> - <p><strong>Note :</strong> Vous pouvez voir ce code en action dans notre exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/ajax.html">ajax.html</a> (<a href="https://mdn.github.io/learning-area/javascript/apis/introduction/ajax.html">voyez-le en direct</a> également).</p> -</div> +> **Note :** Vous pouvez voir ce code en action dans notre exemple [ajax.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/ajax.html) ([voyez-le en direct](https://mdn.github.io/learning-area/javascript/apis/introduction/ajax.html) également). -<p>Les cinq premières lignes spécifient l'emplacement de la ressource que nous voulons récupérer, créent une nouvelle instance d'un objet de requête en utilisant le constructeur <code>XMLHttpRequest()</code>, ouvrent une requête HTTP <code>GET</code> pour récupérer la ressource spécifiée, spécifient que la réponse doit être envoyée au format JSON, puis envoient la requête.</p> +Les cinq premières lignes spécifient l'emplacement de la ressource que nous voulons récupérer, créent une nouvelle instance d'un objet de requête en utilisant le constructeur `XMLHttpRequest()`, ouvrent une requête HTTP `GET` pour récupérer la ressource spécifiée, spécifient que la réponse doit être envoyée au format JSON, puis envoient la requête. -<p>La fonction du gestionnaire <code>onload</code> précise ensuite ce que nous faisons de la réponse. Nous savons que la réponse sera renvoyée avec succès et disponible après le déclenchement de l'événement load (sauf si une erreur s'est produite), nous sauvegardons donc la réponse contenant le JSON renvoyé dans la variable <code>superHeroes</code>, puis nous la passons à deux fonctions différentes pour un traitement ultérieur.</p> +La fonction du gestionnaire `onload` précise ensuite ce que nous faisons de la réponse. Nous savons que la réponse sera renvoyée avec succès et disponible après le déclenchement de l'événement load (sauf si une erreur s'est produite), nous sauvegardons donc la réponse contenant le JSON renvoyé dans la variable `superHeroes`, puis nous la passons à deux fonctions différentes pour un traitement ultérieur. -<h3 id="they_have_additional_security_mechanisms_where_appropriate">Elles disposent de mécanismes de sécurité supplémentaires adéquats</h3> +### Elles disposent de mécanismes de sécurité supplémentaires adéquats -<p>Les fonctionnalités des API Web sont soumises aux mêmes considérations de sécurité que JavaScript et les autres technologies web (par exemple <a href="/fr/docs/Web/Security/Same-origin_policy">same-origin policy</a>), mais elles disposent parfois de mécanismes de sécurité supplémentaires. Par exemple, certaines des API Web les plus modernes ne fonctionneront que sur des pages servies par HTTPS, car elles transmettent des données potentiellement sensibles (par exemple <a href="/fr/docs/Web/API/Service_Worker_API">Service Workers</a> et <a href="/fr/docs/Web/API/Push_API">Push</a>).</p> +Les fonctionnalités des API Web sont soumises aux mêmes considérations de sécurité que JavaScript et les autres technologies web (par exemple [same-origin policy](/fr/docs/Web/Security/Same-origin_policy)), mais elles disposent parfois de mécanismes de sécurité supplémentaires. Par exemple, certaines des API Web les plus modernes ne fonctionneront que sur des pages servies par HTTPS, car elles transmettent des données potentiellement sensibles (par exemple [Service Workers](/fr/docs/Web/API/Service_Worker_API) et [Push](/fr/docs/Web/API/Push_API)). -<p>En outre, certaines API Web demandent la permission d'être activées à l'utilisateur une fois que les appels à ces interfaces sont effectués dans votre code. À titre d'exemple, l'API <a href="/fr/docs/Web/API/Notifications_API">Notifications API</a> demande la permission à l'aide d'une boîte de dialogue contextuelle :</p> +En outre, certaines API Web demandent la permission d'être activées à l'utilisateur une fois que les appels à ces interfaces sont effectués dans votre code. À titre d'exemple, l'API [Notifications API](/fr/docs/Web/API/Notifications_API) demande la permission à l'aide d'une boîte de dialogue contextuelle : -<p><img alt="" src="notification-permission.png"></p> + -<p>Les API Web Audio et <a href="/fr/docs/Web/API/HTMLMediaElement"><code>HTMLMediaElement</code></a> sont soumises à un mécanisme de sécurité appelé <a href="/fr/docs/Web/API/Web_Audio_API/Best_practices#autoplay_policy">autoplay policy</a> - cela signifie essentiellement que vous ne pouvez pas lire automatiquement l'audio lorsqu'une page se charge — vous devez permettre à vos utilisateurs de déclencher la lecture audio par le biais d'un contrôle comme un bouton. Cette mesure est prise parce que la lecture automatique de l'audio est généralement très ennuyeuse et que nous ne devrions pas y soumettre nos utilisateurs.</p> +Les API Web Audio et [`HTMLMediaElement`](/fr/docs/Web/API/HTMLMediaElement) sont soumises à un mécanisme de sécurité appelé [autoplay policy](/fr/docs/Web/API/Web_Audio_API/Best_practices#autoplay_policy) - cela signifie essentiellement que vous ne pouvez pas lire automatiquement l'audio lorsqu'une page se charge — vous devez permettre à vos utilisateurs de déclencher la lecture audio par le biais d'un contrôle comme un bouton. Cette mesure est prise parce que la lecture automatique de l'audio est généralement très ennuyeuse et que nous ne devrions pas y soumettre nos utilisateurs. -<div class="note"> - <p><strong>Note :</strong> Selon la rigueur du navigateur, ces mécanismes de sécurité peuvent même empêcher l'exemple de fonctionner localement, c'est-à-dire si vous chargez le fichier d'exemple local dans votre navigateur au lieu de l'exécuter à partir d'un serveur web. Au moment de la rédaction de ce document, notre exemple d'API Web Audio ne fonctionnait pas localement sur Google Chrome — nous avons dû le télécharger sur GitHub avant qu'il ne fonctionne.</p> -</div> +> **Note :** Selon la rigueur du navigateur, ces mécanismes de sécurité peuvent même empêcher l'exemple de fonctionner localement, c'est-à-dire si vous chargez le fichier d'exemple local dans votre navigateur au lieu de l'exécuter à partir d'un serveur web. Au moment de la rédaction de ce document, notre exemple d'API Web Audio ne fonctionnait pas localement sur Google Chrome — nous avons dû le télécharger sur GitHub avant qu'il ne fonctionne. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>À ce stade, vous devriez avoir une bonne idée de ce que sont les API, de leur fonctionnement et de ce que vous pouvez faire avec dans votre code JavaScript. Vous avec probablement hâte de commencer à faire des choses amusantes avec des API spécifiques, alors allons-y ! Par la suite, nous verrons comment manipuler des documents avec le <i>Document Object Model</i> (DOM).</p> +À ce stade, vous devriez avoir une bonne idée de ce que sont les API, de leur fonctionnement et de ce que vous pouvez faire avec dans votre code JavaScript. Vous avec probablement hâte de commencer à faire des choses amusantes avec des API spécifiques, alors allons-y ! Par la suite, nous verrons comment manipuler des documents avec le _Document Object Model_ (DOM). -<p>{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}}</p> +{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}} -<h2 id="in_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs">API tierces</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">API vidéo et audio</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul> +- [Introduction aux API du Web](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler des documents](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data) +- [API tierces](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des éléments graphiques](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [API vidéo et audio](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/client-side_web_apis/manipulating_documents/index.md b/files/fr/learn/javascript/client-side_web_apis/manipulating_documents/index.md index 8025213ac4..817a4b6212 100644 --- a/files/fr/learn/javascript/client-side_web_apis/manipulating_documents/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/manipulating_documents/index.md @@ -16,317 +16,330 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents original_slug: Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}}</div> - -<p>Quand on écrit des pages web et des applications, une des choses les plus courantes que l'on veut faire est de manipuler la structure du document d'une manière ou d'une autre. On le fait généralement en utilisant le Document Object Model (DOM), un ensemble d'APIs qui permettent de contrôler le HTML et le style — et qui utilisent massivement l'objet <a href="/fr/docs/Web/API/Document"><code>Document</code></a>. Dans cet article, nous allons voir comment utiliser le DOM en détail, ainsi que quelques APIs intéressantes qui peuvent modifier votre environnement.</p> +Quand on écrit des pages web et des applications, une des choses les plus courantes que l'on veut faire est de manipuler la structure du document d'une manière ou d'une autre. On le fait généralement en utilisant le Document Object Model (DOM), un ensemble d'APIs qui permettent de contrôler le HTML et le style — et qui utilisent massivement l'objet [`Document`](/fr/docs/Web/API/Document). Dans cet article, nous allons voir comment utiliser le DOM en détail, ainsi que quelques APIs intéressantes qui peuvent modifier votre environnement. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Connaissances de base en informatique, notions de base d'HTML, CSS, et JavaScript — dont les objets JavaScript.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Se familiariser avec les APIs DOM, et autres APIs souvent associées au DOM et à la manipulation de document</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Connaissances de base en informatique, notions de base d'HTML, CSS, et + JavaScript — dont les objets JavaScript. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Se familiariser avec les APIs DOM, et autres APIs souvent associées au + DOM et à la manipulation de document + </td> + </tr> + </tbody> </table> -<h2 id="the_important_parts_of_a_web_browser">Les principaux composants du navigateur</h2> +## Les principaux composants du navigateur + +Les navigateurs web sont des logiciels très complexes avec beaucoup de composants, dont beaucoup ne peuvent pas être contrôlés ou manipulés en utilisant JavaScript. Vous pourriez penser que de telles limitations sont une mauvaise chose, mais les navigateurs sont verrouillés pour de bonnes raisons, la plupart du temps pour des raisons de sécurité. Imaginez qu'un site web puisse accéder à vos mots de passe stockés ou à d'autres informations sensibles, ou se connecter à des sites web comme si c'était vous? + +Malgré les limitations, les APIs Web nous donnent accès à beaucoup de fonctionnalités, lesquelles nous permettent de faire plein de choses géniales avec les pages web. Il existe quelques éléments évidents que vous utilisez régulièrement dans votre code — jetez un coup d'œil au diagramme suivant, il représente les principaux composants du navigateur directement impliqués dans l'affichage des pages web: + + + +- La _fenêtre_ est l'onglet du navigateur dans lequel une page web est chargée. Elle est représentée en JavaScript par l'objet [`Window`](/fr/docs/Web/API/Window). Utiliser les méthodes disponibles sur cet objet nous permet par exemple de récupérer la taille de la fenêtre (voir [`Window.innerWidth`](/fr/docs/Web/API/Window/innerWidth) et [`Window.innerHeight`](/fr/docs/Web/API/Window/innerHeight)), manipuler le document chargé dans cette fenêtre, stocker des données spécifiques à ce document côté client (par exemple en utilisant une base de données locale ou autre mécanisme de stockage), attacher un [gestionnaire d'événement](/fr/docs/Learn/JavaScript/Building_blocks/Events) à la fenêtre en cours, et plus encore. +- Le _navigateur_ représente l'état et l'identité du navigateur web (le user-agent par exemple) tel qu'il existe sur le Web. En JavaScript, il est représenté par l'objet [`Navigator`](/fr/docs/Web/API/Navigator). Vous pouvez utiliser cet objet pour récupérer des informations telles que la géolocalisation, les préférences de langue de l'utilisateur, un flux vidéo en provenance de la webcam de l'utilisateur, etc. +- Le _document_ (accédé par le DOM dans les navigateurs) est la page actuellement chargée dans la fenêtre. Il est représenté en JavaScript par l'objet [`Document`](/fr/docs/Web/API/Document). Vous pouvez utiliser cet objet pour retourner et manipuler les éléments HTML et CSS qui composent le document. Par exemple: récupérer un élément dans le DOM, changer son texte, appliquer de nouveaux styles dessus, créer de nouveaux éléments et les ajouter à un élément comme enfant, ou même en supprimer. + +Dans cet article, nous allons principalement nous concentrer sur la manipulation du document, mais nous verrons également quelques autres éléments utiles. + +## Le modèle objet du document (Document Object Model) + +Le document chargé dans chaque onglet de votre navigateur, et donc son contenu, est accessible via un modèle objet du document — Document Objet Model en anglais, ou DOM. Il s'agit d'une structure arborescente créée par le navigateur et qui permet aux langages de programmation d'accéder facilement à la structure HTML — par exemple, le navigateur lui-même l'utilise pour appliquer différents styles aux éléments correspondants sur la page, tandis qu'un développeur comme vous et moi peut l'utiliser pour manipuler le DOM avec du JavaScript après que la page ait été chargée. + +Nous avons créé une simple page d'exemple, [dom-example.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dom-example.html) ([voir en direct](https://mdn.github.io/learning-area/javascript/apis/document-manipulation/dom-example.html)). Essayez de l'ouvrir dans votre navigateur — c'est une page très simple qui contient un élément [`<section>`](/fr/docs/Web/HTML/Element/section), à l'intérieur duquel se trouve une image et un paragraphe avec un lien. Le code source HTML ressemble à ça: + +```html +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Simple DOM example</title> + </head> + <body> + <section> + <img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."> + <p>Here we will add a link to the <a href="https://www.mozilla.org/">Mozilla homepage</a></p> + </section> + </body> +</html> +``` + +Le DOM, quant à lui, ressemble à ça : + + + +> **Note :** Ce diagramme du DOM a été créé en utilisant le [Live DOM viewer](https://software.hixie.ch/utilities/js/live-dom-viewer/) de Ian Hickson. + +Vous pouvez voir ici que chaque élément et morceau de texte dans le document possède sa propre entrée dans l'arbre — chacune étant appelée **nœud** (_node_). Vous rencontrerez également plusieurs termes pour décrire les différents type de nœuds ou leur position dans l'arbre les uns par rapport aux autres : + +- **Nœud élément (_element node_)** : N'importe quel élément, tel qu'il existe dans le DOM. +- **Racine (_root_)** : Le nœud de plus haut niveau dans l'arbre. Dans le cas d'un document HTML, il s'agit toujours du nœud `HTML` (d'autres langages de balisage tels que SVG et XML auront des racines différentes). +- **Enfant (_child_)** : Un nœud _directement_ à l'intérieur d'un autre nœud. Ainsi, dans l'exemple ci-dessus, `IMG` est un enfant de `SECTION`. +- **Descendant** : Un nœud _n'importe où_ à l'intérieur d'un autre nœud. Par exemple, `IMG` est un enfant de `SECTION` mais également l'un de ses descendants. En revanche `IMG` n'est pas un enfant de `BODY`, puisqu'il est deux niveaux plus bas dans l'arbre, mais il est un de ses descendants. +- **Parent** : Un nœud qui a un autre nœud _directement_ à l'intérieur. Par exemple, `BODY` est le parent de `SECTION`. +- **Ancêtre (_ancestor_)** : Un nœud qui a un autre nœud _n'importe où_ à l'intérieur. Par exemple, `BODY` est l'ancêtre d'`IMG`. +- **Frères et sœurs (_sibling_)** : Des nœuds qui ont le même parent. Par exemple, `IMG` et `P` sont frères et sœurs. +- **Nœud texte (_text node_)** : Un nœud contenant une chaîne de caractères. + +Il est utile de vous familiariser avec ces termes avant de travailler avec le DOM, puisqu'un certain nombre de documentations les utilisent. Vous les avez peut-être déjà rencontrés si vous avez étudié le CSS (ex. sélecteur descendant, sélecteur enfant). + +## Apprentissage actif : Manipulations basiques du DOM + +Pour commencer l'apprentissage de la manipulation du DOM, commençons par un exemple concret. + +1. Faites une copie locale de la page [dom-example.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dom-example.html) et de l'[image](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dinosaur.png) qui l'accompagne. +2. Ajoutez un élément `<script></script>` juste avant la balise fermante `</body>`. +3. Pour manipuler un élément dans le DOM, vous allez d'abord sélectionner cet élément et stocker une référence à cet élément dans une variable. À l'intérieur de votre élément `<script>`, ajoutez la ligne suivante: -<p>Les navigateurs web sont des logiciels très complexes avec beaucoup de composants, dont beaucoup ne peuvent pas être contrôlés ou manipulés en utilisant JavaScript. Vous pourriez penser que de telles limitations sont une mauvaise chose, mais les navigateurs sont verrouillés pour de bonnes raisons, la plupart du temps pour des raisons de sécurité. Imaginez qu'un site web puisse accéder à vos mots de passe stockés ou à d'autres informations sensibles, ou se connecter à des sites web comme si c'était vous?</p> + ```js + const link = document.querySelector('a'); + ``` -<p>Malgré les limitations, les APIs Web nous donnent accès à beaucoup de fonctionnalités, lesquelles nous permettent de faire plein de choses géniales avec les pages web. Il existe quelques éléments évidents que vous utilisez régulièrement dans votre code — jetez un coup d'œil au diagramme suivant, il représente les principaux composants du navigateur directement impliqués dans l'affichage des pages web:</p> +4. Maintenant que nous avons la référence à l'élément enregistrée dans une variable, nous pouvons commencer à le manipuler en utilisant les propriétés et les méthodes qui lui sont associées (celles-ci sont définies sur les interfaces telles que [`HTMLAnchorElement`](/fr/docs/Web/API/HTMLAnchorElement) dans le cas d'un élément [`<a>`](/fr/docs/Web/HTML/Element/a), et sur les interfaces plus génériques [`HTMLElement`](/fr/docs/Web/API/HTMLElement), et [`Node`](/fr/docs/Web/API/Node) — qui représente tous les nœuds d'un DOM). Tout d'abord, changeons le texte du lien en mettant à jour la valeur de la propriété [`Node.textContent`](/fr/docs/Web/API/Node/textContent). Ajoutez la ligne suivante à la suite de la précédente : -<p><img alt="" src="document-window-navigator.png"></p> - -<ul> - <li>La <em>fenêtre</em> est l'onglet du navigateur dans lequel une page web est chargée. Elle est représentée en JavaScript par l'objet <a href="/fr/docs/Web/API/Window"><code>Window</code></a>. Utiliser les méthodes disponibles sur cet objet nous permet par exemple de récupérer la taille de la fenêtre (voir <a href="/fr/docs/Web/API/Window/innerWidth"><code>Window.innerWidth</code></a> et <a href="/fr/docs/Web/API/Window/innerHeight"><code>Window.innerHeight</code></a>), manipuler le document chargé dans cette fenêtre, stocker des données spécifiques à ce document côté client (par exemple en utilisant une base de données locale ou autre mécanisme de stockage), attacher un <a href="/fr/docs/Learn/JavaScript/Building_blocks/Events">gestionnaire d'événement</a> à la fenêtre en cours, et plus encore.</li> - <li>Le <em>navigateur</em> représente l'état et l'identité du navigateur web (le user-agent par exemple) tel qu'il existe sur le Web. En JavaScript, il est représenté par l'objet <a href="/fr/docs/Web/API/Navigator"><code>Navigator</code></a>. Vous pouvez utiliser cet objet pour récupérer des informations telles que la géolocalisation, les préférences de langue de l'utilisateur, un flux vidéo en provenance de la webcam de l'utilisateur, etc.</li> - <li>Le <em>document</em> (accédé par le DOM dans les navigateurs) est la page actuellement chargée dans la fenêtre. Il est représenté en JavaScript par l'objet <a href="/fr/docs/Web/API/Document"><code>Document</code></a>. Vous pouvez utiliser cet objet pour retourner et manipuler les éléments HTML et CSS qui composent le document. Par exemple: récupérer un élément dans le DOM, changer son texte, appliquer de nouveaux styles dessus, créer de nouveaux éléments et les ajouter à un élément comme enfant, ou même en supprimer.</li> -</ul> - -<p>Dans cet article, nous allons principalement nous concentrer sur la manipulation du document, mais nous verrons également quelques autres éléments utiles.</p> - -<h2 id="the_document_object_model">Le modèle objet du document (Document Object Model)</h2> + ```js + link.textContent = 'Mozilla Developer Network'; + ``` -<p>Le document chargé dans chaque onglet de votre navigateur, et donc son contenu, est accessible via un modèle objet du document — Document Objet Model en anglais, ou DOM. Il s'agit d'une structure arborescente créée par le navigateur et qui permet aux langages de programmation d'accéder facilement à la structure HTML — par exemple, le navigateur lui-même l'utilise pour appliquer différents styles aux éléments correspondants sur la page, tandis qu'un développeur comme vous et moi peut l'utiliser pour manipuler le DOM avec du JavaScript après que la page ait été chargée.</p> +5. Nous devons également modifier l'URL ciblée par le lien, pour qu'il ne renvoie pas au mauvais endroit quand on clique dessus. Ajoutez la ligne suivante, en bas de votre JavaScript : -<p>Nous avons créé une simple page d'exemple, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dom-example.html">dom-example.html</a> (<a href="https://mdn.github.io/learning-area/javascript/apis/document-manipulation/dom-example.html">voir en direct</a>). Essayez de l'ouvrir dans votre navigateur — c'est une page très simple qui contient un élément <a href="/fr/docs/Web/HTML/Element/section"><code><section></code></a>, à l'intérieur duquel se trouve une image et un paragraphe avec un lien. Le code source HTML ressemble à ça:</p> + ```js + link.href = 'https://developer.mozilla.org'; + ``` -<pre class="brush: html"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Simple DOM example</title> - </head> - <body> - <section> - <img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."> - <p>Here we will add a link to the <a href="https://www.mozilla.org/">Mozilla homepage</a></p> - </section> - </body> -</html></pre> +Notez que, comme souvent en JavaScript, il y a plusieurs façons de sélectionner et d'enregistrer une référence à un élément dans une variable. [`Document.querySelector()`](/fr/docs/Web/API/Document/querySelector) est l'approche moderne recommandée — elle est pratique puisqu'elle permet de sélectionner des éléments en utilisant les sélecteurs CSS. L'appel à `querySelector()` que nous avons utilisé plus tôt récupère le premier élément [`<a>`](/fr/docs/Web/HTML/Element/a) qui apparaît dans le document. Si vous souhaitez au contraire récupérer plusieurs éléments, vous pouvez utiliser [`Document.querySelectorAll()`](/fr/docs/Web/API/Document/querySelectorAll), qui récupère tous les éléments du document correspondant au sélecteur, et retourne des références vers ces éléments dans un objet similaire à un [tableau](/fr/docs/Learn/JavaScript/First_steps/Arrays) appelé un [`NodeList`](/fr/docs/Web/API/NodeList). -<p>Le DOM, quant à lui, ressemble à ça :</p> +Il existe des méthodes plus anciennes pour récupérer des références aux éléments, telles que : -<p><img alt="" src="dom-screenshot.png"></p> +- [`Document.getElementById()`](/fr/docs/Web/API/Document/getElementById), qui sélectionne un élément grâce à son attribut `id` (par exemple : `<p id="myId">My paragraph</p>`). L'ID est passé à la fonction en paramètre, de la façon suivante : `var elementRef = document.getElementById('myId')`. +- [`Document.getElementsByTagName()`](/fr/docs/Web/API/Document/getElementsByTagName), qui retourne un tableau contenant tous les éléments de la page ayant un type donné, par exemple tous les `<p>`, `<a>`, etc. Le type de l'élément est passé comme paramètre de la fonction, c'est-à-dire : `var elementRefArray = document.getElementsByTagName('p')`. -<div class="note"> -<p><strong>Note :</strong> Ce diagramme du DOM a été créé en utilisant le <a href="https://software.hixie.ch/utilities/js/live-dom-viewer/">Live DOM viewer</a> de Ian Hickson.</p> -</div> +Ces deux dernières méthodes fonctionnent mieux dans les navigateurs plus anciens que des méthodes plus modernes comme `querySelector()`, mais elles sont beaucoup moins pratiques. Regardez autour de vous et essayez d'en trouver d'autres! -<p>Vous pouvez voir ici que chaque élément et morceau de texte dans le document possède sa propre entrée dans l'arbre — chacune étant appelée <strong>nœud</strong> (<i>node</i>). Vous rencontrerez également plusieurs termes pour décrire les différents type de nœuds ou leur position dans l'arbre les uns par rapport aux autres :</p> +### Créer et placer de nouveaux nœuds -<ul> - <li><strong>Nœud élément (<i>element node</i>)</strong> : N'importe quel élément, tel qu'il existe dans le DOM.</li> - <li><strong>Racine (<i>root</i>)</strong> : Le nœud de plus haut niveau dans l'arbre. Dans le cas d'un document HTML, il s'agit toujours du nœud <code>HTML</code> (d'autres langages de balisage tels que SVG et XML auront des racines différentes).</li> - <li><strong>Enfant (<i>child</i>)</strong> : Un nœud <em>directement</em> à l'intérieur d'un autre nœud. Ainsi, dans l'exemple ci-dessus, <code>IMG</code> est un enfant de <code>SECTION</code>.</li> - <li><strong>Descendant</strong> : Un nœud <em>n'importe où</em> à l'intérieur d'un autre nœud. Par exemple, <code>IMG</code> est un enfant de <code>SECTION</code> mais également l'un de ses descendants. En revanche <code>IMG</code> n'est pas un enfant de <code>BODY</code>, puisqu'il est deux niveaux plus bas dans l'arbre, mais il est un de ses descendants.</li> - <li><strong>Parent</strong> : Un nœud qui a un autre nœud <em>directement</em> à l'intérieur. Par exemple, <code>BODY</code> est le parent de <code>SECTION</code>.</li> - <li><strong>Ancêtre (<i>ancestor</i>)</strong> : Un nœud qui a un autre nœud <em>n'importe où</em> à l'intérieur. Par exemple, <code>BODY</code> est l'ancêtre d'<code>IMG</code>.</li> - <li><strong>Frères et sœurs (<i>sibling</i>)</strong> : Des nœuds qui ont le même parent. Par exemple, <code>IMG</code> et <code>P</code> sont frères et sœurs.</li> - <li><strong>Nœud texte (<i>text node</i>)</strong> : Un nœud contenant une chaîne de caractères.</li> -</ul> +Ce qui précède vous a donné un petit avant-goût de ce que vous pouvez faire, mais allons plus loin et regardons comment créer de nouveaux éléments. -<p>Il est utile de vous familiariser avec ces termes avant de travailler avec le DOM, puisqu'un certain nombre de documentations les utilisent. Vous les avez peut-être déjà rencontrés si vous avez étudié le CSS (ex. sélecteur descendant, sélecteur enfant).</p> +1. Pour revenir à notre exemple, commençons par récupérer une référence à notre élément [`<section>`](/fr/docs/Web/HTML/Element/section) — ajoutez le code suivant au bas de votre script existant (idem avec les lignes qui suivront) : -<h2 id="active_learning_basic_dom_manipulation">Apprentissage actif : Manipulations basiques du DOM</h2> + ```js + var sect = document.querySelector('section'); + ``` -<p>Pour commencer l'apprentissage de la manipulation du DOM, commençons par un exemple concret.</p> +2. Nous allons maintenant créer un nouveau paragraphe grâce à [`Document.createElement()`](/fr/docs/Web/API/Document/createElement), et lui donner du contenu texte de la même manière que précédemment : -<ol> - <li>Faites une copie locale de la page <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dom-example.html">dom-example.html</a> et de l'<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dinosaur.png">image</a> qui l'accompagne.</li> - <li>Ajoutez un élément <code><script></script></code> juste avant la balise fermante <code></body></code>.</li> - <li>Pour manipuler un élément dans le DOM, vous allez d'abord sélectionner cet élément et stocker une référence à cet élément dans une variable. À l'intérieur de votre élément <code><script></code>, ajoutez la ligne suivante: - <pre class="brush: js">const link = document.querySelector('a');</pre> - </li> - <li>Maintenant que nous avons la référence à l'élément enregistrée dans une variable, nous pouvons commencer à le manipuler en utilisant les propriétés et les méthodes qui lui sont associées (celles-ci sont définies sur les interfaces telles que <a href="/fr/docs/Web/API/HTMLAnchorElement"><code>HTMLAnchorElement</code></a> dans le cas d'un élément <a href="/fr/docs/Web/HTML/Element/a"><code><a></code></a>, et sur les interfaces plus génériques <a href="/fr/docs/Web/API/HTMLElement"><code>HTMLElement</code></a>, et <a href="/fr/docs/Web/API/Node"><code>Node</code></a> — qui représente tous les nœuds d'un DOM). Tout d'abord, changeons le texte du lien en mettant à jour la valeur de la propriété <a href="/fr/docs/Web/API/Node/textContent"><code>Node.textContent</code></a>. Ajoutez la ligne suivante à la suite de la précédente : - <pre class="brush: js">link.textContent = 'Mozilla Developer Network';</pre> - </li> - <li>Nous devons également modifier l'URL ciblée par le lien, pour qu'il ne renvoie pas au mauvais endroit quand on clique dessus. Ajoutez la ligne suivante, en bas de votre JavaScript : - <pre class="brush: js">link.href = 'https://developer.mozilla.org';</pre> - </li> -</ol> + ```js + var para = document.createElement('p'); + para.textContent = 'We hope you enjoyed the ride.'; + ``` -<div> -<p>Notez que, comme souvent en JavaScript, il y a plusieurs façons de sélectionner et d'enregistrer une référence à un élément dans une variable. <a href="/fr/docs/Web/API/Document/querySelector"><code>Document.querySelector()</code></a> est l'approche moderne recommandée — elle est pratique puisqu'elle permet de sélectionner des éléments en utilisant les sélecteurs CSS. L'appel à <code>querySelector()</code> que nous avons utilisé plus tôt récupère le premier élément <a href="/fr/docs/Web/HTML/Element/a"><code><a></code></a> qui apparaît dans le document. Si vous souhaitez au contraire récupérer plusieurs éléments, vous pouvez utiliser <a href="/fr/docs/Web/API/Document/querySelectorAll"><code>Document.querySelectorAll()</code></a>, qui récupère tous les éléments du document correspondant au sélecteur, et retourne des références vers ces éléments dans un objet similaire à un <a href="/fr/docs/Learn/JavaScript/First_steps/Arrays">tableau</a> appelé un <a href="/fr/docs/Web/API/NodeList"><code>NodeList</code></a>.</p> +3. Nous pouvons à présent ajouter ce paragraphe au bas de la section en utilisant [`Node.appendChild()`](/fr/docs/Web/API/Node/appendChild): -<p>Il existe des méthodes plus anciennes pour récupérer des références aux éléments, telles que :</p> + ```js + sect.appendChild(para); + ``` -<ul> - <li><a href="/fr/docs/Web/API/Document/getElementById"><code>Document.getElementById()</code></a>, qui sélectionne un élément grâce à son attribut <code>id</code> (par exemple : <code><p id="myId">My paragraph</p></code>). L'ID est passé à la fonction en paramètre, de la façon suivante : <code>var elementRef = document.getElementById('myId')</code>.</li> - <li><a href="/fr/docs/Web/API/Document/getElementsByTagName"><code>Document.getElementsByTagName()</code></a>, qui retourne un tableau contenant tous les éléments de la page ayant un type donné, par exemple tous les <code><p></code>, <code><a></code>, etc. Le type de l'élément est passé comme paramètre de la fonction, c'est-à-dire : <code>var elementRefArray = document.getElementsByTagName('p')</code>.</li> -</ul> +4. Enfin, ajoutons un nœud texte au premier paragraphe, pour finir la phrase joliment. Créons d'abord un nœud texte avec [`Document.createTextNode()`](/fr/docs/Web/API/Document/createTextNode) : -<p>Ces deux dernières méthodes fonctionnent mieux dans les navigateurs plus anciens que des méthodes plus modernes comme <code>querySelector()</code>, mais elles sont beaucoup moins pratiques. Regardez autour de vous et essayez d'en trouver d'autres!</p> -</div> + ```js + var text = document.createTextNode(' — the premier source for web development knowledge.'); + ``` -<h3 id="creating_and_placing_new_nodes">Créer et placer de nouveaux nœuds</h3> +5. Puis, après avoir récupéré une référence au premier paragraphe, ajoutons-y le nœud texte: -<p>Ce qui précède vous a donné un petit avant-goût de ce que vous pouvez faire, mais allons plus loin et regardons comment créer de nouveaux éléments.</p> + ```js + var linkPara = document.querySelector('p'); + linkPara.appendChild(text); + ``` -<ol> - <li>Pour revenir à notre exemple, commençons par récupérer une référence à notre élément <a href="/fr/docs/Web/HTML/Element/section"><code><section></code></a> — ajoutez le code suivant au bas de votre script existant (idem avec les lignes qui suivront) : - <pre class="brush: js">var sect = document.querySelector('section');</pre> - </li> - <li>Nous allons maintenant créer un nouveau paragraphe grâce à <a href="/fr/docs/Web/API/Document/createElement"><code>Document.createElement()</code></a>, et lui donner du contenu texte de la même manière que précédemment : - <pre class="brush: js">var para = document.createElement('p'); -para.textContent = 'We hope you enjoyed the ride.';</pre> - </li> - <li>Nous pouvons à présent ajouter ce paragraphe au bas de la section en utilisant <a href="/fr/docs/Web/API/Node/appendChild"><code>Node.appendChild()</code></a>: - <pre class="brush: js">sect.appendChild(para);</pre> - </li> - <li>Enfin, ajoutons un nœud texte au premier paragraphe, pour finir la phrase joliment. Créons d'abord un nœud texte avec <a href="/fr/docs/Web/API/Document/createTextNode"><code>Document.createTextNode()</code></a> : - <pre class="brush: js">var text = document.createTextNode(' — the premier source for web development knowledge.');</pre> - </li> - <li>Puis, après avoir récupéré une référence au premier paragraphe, ajoutons-y le nœud texte: - <pre class="brush: js">var linkPara = document.querySelector('p'); -linkPara.appendChild(text);</pre> - </li> -</ol> +C'est l'essentiel de ce dont vous aurez besoin pour ajouter des nœuds au DOM — vous utiliserez beaucoup ces méthodes lorsque vous construirez des interfaces dynamiques (nous en verrons quelques exemples plus tard). -<p>C'est l'essentiel de ce dont vous aurez besoin pour ajouter des nœuds au DOM — vous utiliserez beaucoup ces méthodes lorsque vous construirez des interfaces dynamiques (nous en verrons quelques exemples plus tard).</p> +### Déplacer et supprimer des éléments -<h3 id="moving_and_removing_elements">Déplacer et supprimer des éléments</h3> +Il peut arriver qu'on veuille déplacer des nœuds, ou même les supprimer du DOM. C'est tout à fait possible, et voyons comment. -<p>Il peut arriver qu'on veuille déplacer des nœuds, ou même les supprimer du DOM. C'est tout à fait possible, et voyons comment.</p> - - -<p>Par exemple, si l'on veut déplacer le premier paragraphe de notre exemple au bas de la section, on pourrait utiliser :</p> - -<pre class="brush: js">sect.appendChild(linkPara);</pre> - -<p>Cette commande va déplacer le paragraphe tout au bas de la section. On pourrait penser qu'elle va en fait ajouter une copie, mais ce n'est pas le cas : <code>linkPara</code> ne fait référence qu'à un seul et unique élément. Pour copier le paragraphe, il faudrait utiliser <a href="/fr/docs/Web/API/Node/cloneNode"><code>Node.cloneNode()</code></a> à la place.</p> - -<p>Supprimer des éléments est également plutôt simple, dès lors qu'on a une référence de l'élément à supprimer et de son parent. Dans notre cas, on peut simplement utiliser <a href="/fr/docs/Web/API/Node/removeChild"><code>Node.removeChild()</code></a>, comme ceci :</p> - -<pre>sect.removeChild(linkPara);</pre> +Par exemple, si l'on veut déplacer le premier paragraphe de notre exemple au bas de la section, on pourrait utiliser : -<p>Si vous souhaitez un élément uniquement à partir d'une référence à cet élément, comme c'est souvent le cas, vous pouvez utiliser <a href="/fr/docs/Web/API/ChildNode/remove"><code>ChildNode.remove()</code></a> :</p> +```js +sect.appendChild(linkPara); +``` -<pre class="brush: js">linkPara.remove();</pre> +Cette commande va déplacer le paragraphe tout au bas de la section. On pourrait penser qu'elle va en fait ajouter une copie, mais ce n'est pas le cas : `linkPara` ne fait référence qu'à un seul et unique élément. Pour copier le paragraphe, il faudrait utiliser [`Node.cloneNode()`](/fr/docs/Web/API/Node/cloneNode) à la place. -<p>Cette méthode ne fonctionne cependant pas dans les navigateurs plus anciens. Ils ne possèdent en effet pas de méthodes pour dire à un nœud de se supprimer, et il faut donc procéder comme suit :</p> +Supprimer des éléments est également plutôt simple, dès lors qu'on a une référence de l'élément à supprimer et de son parent. Dans notre cas, on peut simplement utiliser [`Node.removeChild()`](/fr/docs/Web/API/Node/removeChild), comme ceci : -<pre class="brush: js">linkPara.parentNode.removeChild(linkPara);</pre> + sect.removeChild(linkPara); -<p>À votre tour : essayez les lignes ci-dessus en les ajoutant à votre code.</p> - -<h3 id="manipulating_styles">Manipuler le style</h3> +Si vous souhaitez un élément uniquement à partir d'une référence à cet élément, comme c'est souvent le cas, vous pouvez utiliser [`ChildNode.remove()`](/fr/docs/Web/API/ChildNode/remove) : -<p>Il est possible de manipuler des styles CSS grâce à du JavaScript de plusieurs manières.</p> - -<p> Pour commencer, vous pouvez obtenir une liste de toutes les feuilles de style associées à un document en utilisant <a href="/fr/docs/Web/API/Document/styleSheets"><code>Document.stylesheets</code></a>, qui retourne un objet, ressemblant à un tableau composé d'objets <a href="/fr/docs/Web/API/CSSStyleSheet"><code>CSSStyleSheet</code></a>. Vous pouvez alors ajouter/supprimer des styles comme vous le souhaitez. Cependant, nous n'allons pas nous étendre sur ces fonctionnalités, car elles sont archaïques et il est difficile de manipuler le style avec. Il y a des techniques beaucoup plus simples.</p> - -<p>La première d'entre elles consiste à ajouter des styles en ligne (<i>inline styles</i>), directement sur les éléments que vous voulez styliser de façon dynamique. Pour ce faire, on utilise la propriété <a href="/fr/docs/Web/API/ElementCSSInlineStyle/style"><code>HTMLElement.style</code></a>, qui contient les informations de style en ligne de chaque élément du document. Vous pouvez définir des propriétés de cet objet de façon à pouvoir mettre à jour directement le style des éléments.</p> - -<ol> - <li>À titre d'exemple, essayez d'ajouter les lignes suivantes à notre exemple : - <pre class="brush: js">para.style.color = 'white'; -para.style.backgroundColor = 'black'; -para.style.padding = '10px'; -para.style.width = '250px'; -para.style.textAlign = 'center';</pre> - </li> - <li>Rafraichissez la page, et vous verrez que les styles ont été appliqués au paragraphe. Si vous regardez ce paragraphe dans l'<a href="/fr/docs/Tools/Page_Inspector">Inspecteur</a> du navigateur, vous verrez que ces lignes sont en effet ajoutées comme du style en ligne au document: - <pre class="brush: html"><p style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">We hope you enjoyed the ride.</p></pre> - </li> -</ol> +```js +linkPara.remove(); +``` -<div class="note"> -<p><strong>Note :</strong> Vous remarquerez que les propriétés JavaScript qui représentent les propriétés CSS sont écrites en <a href="https://fr.wikipedia.org/wiki/Camel_case">lower camel case</a> tandis que les versions CSS sont reliées par des tirets (par exemple <code>backgroundColor</code> au lieu de <code>background-color</code>). Prenez garde à ne pas les mélanger, sans quoi ça ne fonctionnera pas.</p> -</div> +Cette méthode ne fonctionne cependant pas dans les navigateurs plus anciens. Ils ne possèdent en effet pas de méthodes pour dire à un nœud de se supprimer, et il faut donc procéder comme suit : -<p>Il y a un autre moyen de manipuler dynamiquement des styles sur votre document, que nous allons étudier maintenant.</p> +```js +linkPara.parentNode.removeChild(linkPara); +``` -<ol> - <li>Supprimez les cinq lignes précédentes que nous avons ajoutées à notre code JavaScript.</li> - <li>Ajoutez ce qui suit au sein de la balise <a href="/fr/docs/Web/HTML/Element/head"><code><head></code></a> de votre HTML: - <pre><style> -.highlight { - color: white; - background-color: black; - padding: 10px; - width: 250px; - text-align: center; -} -</style></pre> - </li> - <li>Nous allons maintenant utiliser une méthode très utile pour la manipulation HTML de manière générale : <a href="/fr/docs/Web/API/Element/setAttribute"><code>Element.setAttribute()</code></a>. Cette fonction prend deux paramètres : le nom de l'attribut que vous voulez définir sur l'élément, et la valeur que vous voulez lui attribuer. Ici nous allons ajouter une classe <code>highlight</code> à notre élément : - <pre class="brush: js">para.setAttribute('class', 'highlight');</pre> - </li> - <li>Rafraîchissez votre page, et vous constaterez qu'il n'y a aucun changement par rapport au dernier exemple. Le CSS est toujours appliqué au paragraphe, mais la seule différence c'est qu'on a utilisé une classe pour le faire et non des styles en ligne.</li> -</ol> +À votre tour : essayez les lignes ci-dessus en les ajoutant à votre code. -<p>A vous de choisir la méthode que vous souhaitez utiliser : chacune a ses avantages et ses inconvénients. Les styles en ligne demandent moins de préparation et sont utiles pour un usage simple, tandis que l'usage des classes est une méthode plus pure (on ne mélange pas le CSS et le JavaScript, on évite donc les styles en ligne, car c'est considéré comme une mauvaise pratique). Au fur et à mesure que vous construirez des applications plus volumineuses et complexes, vous allez probablement utiliser la deuxième méthode plus souvent, mais c'est à vous de décider.</p> +### Manipuler le style -<p>À ce stade, nous n'avons pas vraiment fait quoi que soit d'utile! Il n'y a pas d'intérêt à générer du contenu statique avec du JavaScript — autant l'écrire directement en HTML sans passer par du JavaScript. Le JavaScript est plus complexe que du HTML, et comporte son propre lot de problèmes (comme le fait qu'il ne puisse pas être lu par les moteurs de recherche).</p> +Il est possible de manipuler des styles CSS grâce à du JavaScript de plusieurs manières. -<p>Dans les deux prochaines sections, nous verrons des exemples d'utilisation plus pratiques des APIs du DOM.</p> +Pour commencer, vous pouvez obtenir une liste de toutes les feuilles de style associées à un document en utilisant [`Document.stylesheets`](/fr/docs/Web/API/Document/styleSheets), qui retourne un objet, ressemblant à un tableau composé d'objets [`CSSStyleSheet`](/fr/docs/Web/API/CSSStyleSheet). Vous pouvez alors ajouter/supprimer des styles comme vous le souhaitez. Cependant, nous n'allons pas nous étendre sur ces fonctionnalités, car elles sont archaïques et il est difficile de manipuler le style avec. Il y a des techniques beaucoup plus simples. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez trouver la <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dom-example-manipulated.html">version finale de dom-example.html</a> sur GitHub (<a href="https://mdn.github.io/learning-area/javascript/apis/document-manipulation/dom-example-manipulated.html">le voir en direct aussi</a>).</p> -</div> +La première d'entre elles consiste à ajouter des styles en ligne (_inline styles_), directement sur les éléments que vous voulez styliser de façon dynamique. Pour ce faire, on utilise la propriété [`HTMLElement.style`](/fr/docs/Web/API/ElementCSSInlineStyle/style), qui contient les informations de style en ligne de chaque élément du document. Vous pouvez définir des propriétés de cet objet de façon à pouvoir mettre à jour directement le style des éléments. -<h2 id="active_learning_getting_useful_information_from_the_window_object">Apprentissage actif : Récupérer des informations utiles depuis l'objet Window</h2> +1. À titre d'exemple, essayez d'ajouter les lignes suivantes à notre exemple : -<p>Jusqu'à présent nous avons seulement utilisé les fonctionnalités de <a href="/fr/docs/Web/API/Node"><code>Node</code></a> et <a href="/fr/docs/Web/API/Document"><code>Document</code></a> (le DOM) pour manipuler les documents, mais vous pouvez obtenir des données d'autres sources pour les intégrer à votre interface utilisateur (UI). Il faut simplement s'assurer que les données sont au bon format ; c'est plus simple avec JavaScript qu'avec d'autres langages, puisqu'on utilise un typage faible — les nombres par exemple sont automatiquement convertis en texte lorsqu'on les affiche à l'écran.</p> + ```js + para.style.color = 'white'; + para.style.backgroundColor = 'black'; + para.style.padding = '10px'; + para.style.width = '250px'; + para.style.textAlign = 'center'; + ``` -<p>Dans cet exemple, nous allons résoudre un problème très courant — s'assurer que votre application est de la même taille que la fenêtre, quelle que soit la taille de la fenêtre. C'est souvent utile pour des jeux par exemple, où l'on veut utiliser autant d'espace d'écran que possible pour jouer.</p> +2. Rafraichissez la page, et vous verrez que les styles ont été appliqués au paragraphe. Si vous regardez ce paragraphe dans l'[Inspecteur](/fr/docs/Tools/Page_Inspector) du navigateur, vous verrez que ces lignes sont en effet ajoutées comme du style en ligne au document: -<p>Pour commencer, faites une copie en local des fichiers de démonstration <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/window-resize-example.html">window-resize-example.html</a> et <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/bgtile.png">bgtile.png</a>. Ouvrez-les : vous y trouverez un élément <a href="/fr/docs/Web/HTML/Element/div"><code><div></code></a> qui couvre une petite partie de l'écran avec un motif en mosaïque. Nous utiliserons cet élément pour représenter la surface de notre interface utilisateur.</p> + ```html + <p style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">We hope you enjoyed the ride.</p> + ``` -<ol> - <li>Tout d'abord, nous allons récupérer : une référence au <code><div></code>, la largeur de la fenêtre d'affichage ("viewport", celle où notre document est affiché) et sa hauteur, avant de les stocker dans des variables — ces deux dernières valeurs sont faciles à obtenir via les propriétés <a href="/fr/docs/Web/API/Window/innerWidth"><code>Window.innerWidth</code></a> et <a href="/fr/docs/Web/API/Window/innerHeight"><code>Window.innerHeight</code></a>. Ajoutez les lignes qui suivent à l'intérieur de l'élément <a href="/fr/docs/Web/HTML/Element/script"><code><script></code></a> : - <pre class="brush: js">const div = document.querySelector('div'); - let winWidth = window.innerWidth; - let winHeight = window.innerHeight;</pre> - </li> - <li>Ensuite, nous allons modifier dynamiquement la largeur et la hauteur de notre <code><div></code> pour qu'elles soient égales à celles de la fenêtre d'affichage. Ajoutez les lignes suivantes à la suite des précédentes : - <pre class="brush: js">div.style.width = winWidth + 'px'; - div.style.height = winHeight + 'px';</pre> - </li> - <li>Sauvegardez vos modifications et rafraîchissez votre page : vous devriez désormais constater que la <code><div></code> est aussi grande que la fenêtre, quelle que soit la taille de la fenêtre. Si maintenant vous essayez d'agrandir votre fenêtre, vous pouvez constater que la div ne change pas de taille — nous ne définissons la taille qu'une seule fois.</li> - <li>Nous pouvons utiliser un gestionnaire d'événement pour que la <code><div></code> soit redimensionnée à chaque fois que la fenêtre l'est. L'objet <a href="/fr/docs/Web/API/Window"><code>Window</code></a> dispose d'un événement dédié appelé <code>resize</code>, qui est déclenché à chaque fois que la fenêtre est redimensionnée — nous pouvons utiliser le gestionnaire d'événement {{domxref("GlobalEventHandlers/onresize", "Window.onresize")}} pour ré-exécuter notre code de dimensionnement à chaque fois. Ajoutez ce qui suit au bas de votre code: - <pre class="brush: js">window.onresize = function() { - winWidth = window.innerWidth; - winHeight = window.innerHeight; +> **Note :** Vous remarquerez que les propriétés JavaScript qui représentent les propriétés CSS sont écrites en [lower camel case](https://fr.wikipedia.org/wiki/Camel_case) tandis que les versions CSS sont reliées par des tirets (par exemple `backgroundColor` au lieu de `background-color`). Prenez garde à ne pas les mélanger, sans quoi ça ne fonctionnera pas. + +Il y a un autre moyen de manipuler dynamiquement des styles sur votre document, que nous allons étudier maintenant. + +1. Supprimez les cinq lignes précédentes que nous avons ajoutées à notre code JavaScript. +2. Ajoutez ce qui suit au sein de la balise [`<head>`](/fr/docs/Web/HTML/Element/head) de votre HTML: + + <style> + .highlight { + color: white; + background-color: black; + padding: 10px; + width: 250px; + text-align: center; + } + </style> + +3. Nous allons maintenant utiliser une méthode très utile pour la manipulation HTML de manière générale : [`Element.setAttribute()`](/fr/docs/Web/API/Element/setAttribute). Cette fonction prend deux paramètres : le nom de l'attribut que vous voulez définir sur l'élément, et la valeur que vous voulez lui attribuer. Ici nous allons ajouter une classe `highlight` à notre élément : + + ```js + para.setAttribute('class', 'highlight'); + ``` + +4. Rafraîchissez votre page, et vous constaterez qu'il n'y a aucun changement par rapport au dernier exemple. Le CSS est toujours appliqué au paragraphe, mais la seule différence c'est qu'on a utilisé une classe pour le faire et non des styles en ligne. + +A vous de choisir la méthode que vous souhaitez utiliser : chacune a ses avantages et ses inconvénients. Les styles en ligne demandent moins de préparation et sont utiles pour un usage simple, tandis que l'usage des classes est une méthode plus pure (on ne mélange pas le CSS et le JavaScript, on évite donc les styles en ligne, car c'est considéré comme une mauvaise pratique). Au fur et à mesure que vous construirez des applications plus volumineuses et complexes, vous allez probablement utiliser la deuxième méthode plus souvent, mais c'est à vous de décider. + +À ce stade, nous n'avons pas vraiment fait quoi que soit d'utile! Il n'y a pas d'intérêt à générer du contenu statique avec du JavaScript — autant l'écrire directement en HTML sans passer par du JavaScript. Le JavaScript est plus complexe que du HTML, et comporte son propre lot de problèmes (comme le fait qu'il ne puisse pas être lu par les moteurs de recherche). + +Dans les deux prochaines sections, nous verrons des exemples d'utilisation plus pratiques des APIs du DOM. + +> **Note :** Vous pouvez trouver la [version finale de dom-example.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/dom-example-manipulated.html) sur GitHub ([le voir en direct aussi](https://mdn.github.io/learning-area/javascript/apis/document-manipulation/dom-example-manipulated.html)). + +## Apprentissage actif : Récupérer des informations utiles depuis l'objet Window + +Jusqu'à présent nous avons seulement utilisé les fonctionnalités de [`Node`](/fr/docs/Web/API/Node) et [`Document`](/fr/docs/Web/API/Document) (le DOM) pour manipuler les documents, mais vous pouvez obtenir des données d'autres sources pour les intégrer à votre interface utilisateur (UI). Il faut simplement s'assurer que les données sont au bon format ; c'est plus simple avec JavaScript qu'avec d'autres langages, puisqu'on utilise un typage faible — les nombres par exemple sont automatiquement convertis en texte lorsqu'on les affiche à l'écran. + +Dans cet exemple, nous allons résoudre un problème très courant — s'assurer que votre application est de la même taille que la fenêtre, quelle que soit la taille de la fenêtre. C'est souvent utile pour des jeux par exemple, où l'on veut utiliser autant d'espace d'écran que possible pour jouer. + +Pour commencer, faites une copie en local des fichiers de démonstration [window-resize-example.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/window-resize-example.html) et [bgtile.png](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/bgtile.png). Ouvrez-les : vous y trouverez un élément [`<div>`](/fr/docs/Web/HTML/Element/div) qui couvre une petite partie de l'écran avec un motif en mosaïque. Nous utiliserons cet élément pour représenter la surface de notre interface utilisateur. + +1. Tout d'abord, nous allons récupérer : une référence au `<div>`, la largeur de la fenêtre d'affichage ("viewport", celle où notre document est affiché) et sa hauteur, avant de les stocker dans des variables — ces deux dernières valeurs sont faciles à obtenir via les propriétés [`Window.innerWidth`](/fr/docs/Web/API/Window/innerWidth) et [`Window.innerHeight`](/fr/docs/Web/API/Window/innerHeight). Ajoutez les lignes qui suivent à l'intérieur de l'élément [`<script>`](/fr/docs/Web/HTML/Element/script) : + + ```js + const div = document.querySelector('div'); + let winWidth = window.innerWidth; + let winHeight = window.innerHeight; + ``` + +2. Ensuite, nous allons modifier dynamiquement la largeur et la hauteur de notre `<div>` pour qu'elles soient égales à celles de la fenêtre d'affichage. Ajoutez les lignes suivantes à la suite des précédentes : + + ```js div.style.width = winWidth + 'px'; - div.style.height = winHeight + 'px'; - }</pre> - </li> - </ol> + div.style.height = winHeight + 'px'; + ``` + +3. Sauvegardez vos modifications et rafraîchissez votre page : vous devriez désormais constater que la `<div>` est aussi grande que la fenêtre, quelle que soit la taille de la fenêtre. Si maintenant vous essayez d'agrandir votre fenêtre, vous pouvez constater que la div ne change pas de taille — nous ne définissons la taille qu'une seule fois. +4. Nous pouvons utiliser un gestionnaire d'événement pour que la `<div>` soit redimensionnée à chaque fois que la fenêtre l'est. L'objet [`Window`](/fr/docs/Web/API/Window) dispose d'un événement dédié appelé `resize`, qui est déclenché à chaque fois que la fenêtre est redimensionnée — nous pouvons utiliser le gestionnaire d'événement {{domxref("GlobalEventHandlers/onresize", "Window.onresize")}} pour ré-exécuter notre code de dimensionnement à chaque fois. Ajoutez ce qui suit au bas de votre code: -<div class="note"> -<p><strong>Note :</strong> En cas de blocage, jetez un œil à notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/window-resize-example-finished.html">exemple de redimensionnement de la fenêtre terminé</a> sur GitHub (<a href="https://mdn.github.io/learning-area/javascript/apis/document-manipulation/window-resize-example-finished.html">voir en direct aussi</a>).</p> -</div> + ```js + window.onresize = function() { + winWidth = window.innerWidth; + winHeight = window.innerHeight; + div.style.width = winWidth + 'px'; + div.style.height = winHeight + 'px'; + } + ``` -<h2 id="active_learning_a_dynamic_shopping_list">Apprentissage actif : Une liste de courses dynamique</h2> +> **Note :** En cas de blocage, jetez un œil à notre [exemple de redimensionnement de la fenêtre terminé](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/window-resize-example-finished.html) sur GitHub ([voir en direct aussi](https://mdn.github.io/learning-area/javascript/apis/document-manipulation/window-resize-example-finished.html)). -<p>Pour clore cet article, nous aimerions vous proposer un petit challenge : nous voulons créer une liste de courses simple qui nous permette d'ajouter des articles à la liste de façon dynamique, le tout grâce à un champ de formulaire et un bouton. Quand vous ajoutez une valeur au champ et appuyez sur le bouton :</p> +## Apprentissage actif : Une liste de courses dynamique -<ul> - <li>L'article doit être ajouté à la liste.</li> - <li>Chaque article de la liste doit avoir un bouton qui, quand on le presse, supprime cet élément de la liste.</li> - <li>Le champ doit être vidé et reprendre le focus pour que vous puissiez entrer directement un nouvel article.</li> -</ul> +Pour clore cet article, nous aimerions vous proposer un petit challenge : nous voulons créer une liste de courses simple qui nous permette d'ajouter des articles à la liste de façon dynamique, le tout grâce à un champ de formulaire et un bouton. Quand vous ajoutez une valeur au champ et appuyez sur le bouton : -<p>La démo terminée doit ressembler à ça:</p> +- L'article doit être ajouté à la liste. +- Chaque article de la liste doit avoir un bouton qui, quand on le presse, supprime cet élément de la liste. +- Le champ doit être vidé et reprendre le focus pour que vous puissiez entrer directement un nouvel article. -<p><img alt="" src="shopping-list.png"></p> +La démo terminée doit ressembler à ça: -<p>Pour compléter l'exercice, suivez les étapes ci-dessous, et assurez-vous que votre exemple se comporte comme décrit ci-dessus.</p> + -<ol> - <li>Tout d'abord, téléchargez une copie du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/shopping-list.html">shopping-list.html</a>. Vous verrez qu'il contient : un peu de CSS, une liste avec un titre, un champ, un bouton, une liste vide et un élément <a href="/fr/docs/Web/HTML/Element/script"><code><script></code></a>. Vous apporterez toutes vos modifications à l'intérieur du script.</li> - <li>Créez trois variables, contenant des références aux éléments de liste <a href="/fr/docs/Web/HTML/Element/ul"><code><ul></code></a>, de champ <a href="/fr/docs/Web/HTML/Element/Input"><code><input></code></a> et de bouton <a href="/fr/docs/Web/HTML/Element/Button"><code><button></code></a>.</li> - <li>Créez une <a href="/fr/docs/Learn/JavaScript/Building_blocks/Functions">fonction</a> qui sera déclenchée lorsqu'on clique sur le bouton.</li> - <li>À l'intérieur du corps de la fonction, commencez par stocker la <a href="/fr/docs/Web/API/HTMLInputElement#properties">valeur actuelle</a> (propriété <code>value</code>) du champ dans une variable.</li> - <li>Ensuite, videz le champ en définissant sa valeur comme une chaîne vide — <code>''</code>.</li> - <li>Créez trois nouveaux éléments : un élément de liste <a href="/fr/docs/Web/HTML/Element/li"><code><li></code></a>, un <a href="/fr/docs/Web/HTML/Element/span"><code><span></code></a> et un bouton <a href="/fr/docs/Web/HTML/Element/Button"><code><button></code></a>, et stockez-les chacun dans des variables.</li> - <li>Attachez le <code><span></code> et le <code><button></code> comme enfants de <code><li></code>.</li> - <li>Définissez le contenu texte du <code><span></code> comme égal à la valeur du champ que vous avez récupéré précédemment, et le contenu du bouton à "Supprimer".</li> - <li>Attachez l'article <code><li></code> comme enfant de la liste.</li> - <li>Ajoutez un gestionnaire d'événement au bouton "Supprimer", de façon à ce que lorsqu'on le clique le <code><li></code> dans lequel il se situe soit supprimé.</li> - <li>Enfin, utilisez la méthode <a href="/fr/docs/Web/API/HTMLOrForeignElement/focus"><code>HTMLElement.focus</code></a> pour donner le focus au champ, qu'il soit prêt à recevoir la valeur du prochain article de la liste de courses.</li> -</ol> +Pour compléter l'exercice, suivez les étapes ci-dessous, et assurez-vous que votre exemple se comporte comme décrit ci-dessus. -<div class="note"> -<p><strong>Note :</strong> Si vous bloquez vraiment, jetez un œil à notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/shopping-list-finished.html">liste de courses terminée</a> (<a href="https://mdn.github.io/learning-area/javascript/apis/document-manipulation/shopping-list-finished.html">voir en direct</a>.)</p> -</div> +1. Tout d'abord, téléchargez une copie du fichier [shopping-list.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/shopping-list.html). Vous verrez qu'il contient : un peu de CSS, une liste avec un titre, un champ, un bouton, une liste vide et un élément [`<script>`](/fr/docs/Web/HTML/Element/script). Vous apporterez toutes vos modifications à l'intérieur du script. +2. Créez trois variables, contenant des références aux éléments de liste [`<ul>`](/fr/docs/Web/HTML/Element/ul), de champ [`<input>`](/fr/docs/Web/HTML/Element/Input) et de bouton [`<button>`](/fr/docs/Web/HTML/Element/Button). +3. Créez une [fonction](/fr/docs/Learn/JavaScript/Building_blocks/Functions) qui sera déclenchée lorsqu'on clique sur le bouton. +4. À l'intérieur du corps de la fonction, commencez par stocker la [valeur actuelle](/fr/docs/Web/API/HTMLInputElement#properties) (propriété `value`) du champ dans une variable. +5. Ensuite, videz le champ en définissant sa valeur comme une chaîne vide — `''`. +6. Créez trois nouveaux éléments : un élément de liste [`<li>`](/fr/docs/Web/HTML/Element/li), un [`<span>`](/fr/docs/Web/HTML/Element/span) et un bouton [`<button>`](/fr/docs/Web/HTML/Element/Button), et stockez-les chacun dans des variables. +7. Attachez le `<span>` et le `<button>` comme enfants de `<li>`. +8. Définissez le contenu texte du `<span>` comme égal à la valeur du champ que vous avez récupéré précédemment, et le contenu du bouton à "Supprimer". +9. Attachez l'article `<li>` comme enfant de la liste. +10. Ajoutez un gestionnaire d'événement au bouton "Supprimer", de façon à ce que lorsqu'on le clique le `<li>` dans lequel il se situe soit supprimé. +11. Enfin, utilisez la méthode [`HTMLElement.focus`](/fr/docs/Web/API/HTMLOrForeignElement/focus) pour donner le focus au champ, qu'il soit prêt à recevoir la valeur du prochain article de la liste de courses. -<h2 id="summary">Résumé</h2> +> **Note :** Si vous bloquez vraiment, jetez un œil à notre [liste de courses terminée](https://github.com/mdn/learning-area/blob/master/javascript/apis/document-manipulation/shopping-list-finished.html) ([voir en direct](https://mdn.github.io/learning-area/javascript/apis/document-manipulation/shopping-list-finished.html).) -<p>Nous avons fini notre étude de la manipulation de document et du DOM. À ce stade, vous devriez comprendre quels sont les composants importants d'un navigateur web en matière de contrôle de documents et certains aspects de l'expérience utilisateur sur le Web. Plus important encore, vous devriez comprendre ce qu'est le Document Object Model, et comment l'utiliser pour créer des fonctionnalités utiles.</p> +## Résumé -<h2 id="see_also">Voir aussi</h2> +Nous avons fini notre étude de la manipulation de document et du DOM. À ce stade, vous devriez comprendre quels sont les composants importants d'un navigateur web en matière de contrôle de documents et certains aspects de l'expérience utilisateur sur le Web. Plus important encore, vous devriez comprendre ce qu'est le Document Object Model, et comment l'utiliser pour créer des fonctionnalités utiles. -<p>Il y a bien d'autres fonctionnalités que vous pouvez utiliser pour manipuler vos documents. Jetez un coup d'œil à quelques-unes de nos notices pour en découvrir davantage :</p> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/API/Document"><code>Document</code></a></li> - <li><a href="/fr/docs/Web/API/Window"><code>Window</code></a></li> - <li><a href="/fr/docs/Web/API/Node"><code>Node</code></a></li> - <li><a href="/fr/docs/Web/API/HTMLElement"><code>HTMLElement</code></a>, <a href="/fr/docs/Web/API/HTMLInputElement"><code>HTMLInputElement</code></a>, <a href="/fr/docs/Web/API/HTMLImageElement"><code>HTMLImageElement</code></a>, etc.</li> -</ul> +Il y a bien d'autres fonctionnalités que vous pouvez utiliser pour manipuler vos documents. Jetez un coup d'œil à quelques-unes de nos notices pour en découvrir davantage : -<p>(Voir notre <a href="/fr/docs/Web/API">Référence Web API</a> pour une liste complète des APIs web documentées sur MDN!)</p> +- [`Document`](/fr/docs/Web/API/Document) +- [`Window`](/fr/docs/Web/API/Window) +- [`Node`](/fr/docs/Web/API/Node) +- [`HTMLElement`](/fr/docs/Web/API/HTMLElement), [`HTMLInputElement`](/fr/docs/Web/API/HTMLInputElement), [`HTMLImageElement`](/fr/docs/Web/API/HTMLImageElement), etc. -<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}}</div> +(Voir notre [Référence Web API](/fr/docs/Web/API) pour une liste complète des APIs web documentées sur MDN!) +{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Introduction", "Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs")}} -<h2 id="in_this_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul>
\ No newline at end of file +- [Introduction aux API du Web](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler des documents](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data) +- [APIs tierces](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des éléments graphiques](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [APIs vidéo et audio](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/client-side_web_apis/third_party_apis/index.md b/files/fr/learn/javascript/client-side_web_apis/third_party_apis/index.md index 15dfb1c063..79886bea99 100644 --- a/files/fr/learn/javascript/client-side_web_apis/third_party_apis/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/third_party_apis/index.md @@ -8,131 +8,144 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Third_party_APIs original_slug: Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs --- -<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}} -<p>Jusqu'à présent, nous avons uniquement abordé des API qui sont fournies par le navigateur. Il en existe d'autres : de nombreux sites et services, tels que Google Maps, Twitter, Facebook, PayPal, etc. fournissent des API permettant aux développeurs d'exploiter leurs données (ex. afficher un flux Twitter sur un blog) ou leurs services (utiliser l'outil de connexion Facebook pour que vos utilisateurs se connectent sur votre application). Dans cet article, nous verrons les différences entre les API du navigateur et celles fournies par des services tiers (en anglais, on parle de « <em>third-party API</em> ») et nous illustrerons certains cas d'usage pour ces API tierces.</p> +Jusqu'à présent, nous avons uniquement abordé des API qui sont fournies par le navigateur. Il en existe d'autres : de nombreux sites et services, tels que Google Maps, Twitter, Facebook, PayPal, etc. fournissent des API permettant aux développeurs d'exploiter leurs données (ex. afficher un flux Twitter sur un blog) ou leurs services (utiliser l'outil de connexion Facebook pour que vos utilisateurs se connectent sur votre application). Dans cet article, nous verrons les différences entre les API du navigateur et celles fournies par des services tiers (en anglais, on parle de « _third-party API_ ») et nous illustrerons certains cas d'usage pour ces API tierces. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Les bases de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, <a href="/fr/docs/Apprendre/JavaScript/Building_blocks"> blocs de construction</a>, <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), <a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction">les bases des API côté client</a>.</td> - </tr> - <tr> - <th scope="row">Objectifs :</th> - <td>Comprendre le fonctionnement des API tierces et comment les utiliser pour ajouter des fonctionnalités à ses sites / applications.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Les bases de JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas</a>, + <a href="/fr/docs/Apprendre/JavaScript/Building_blocks" + >blocs de construction</a + >, + <a href="/fr/docs/Learn/JavaScript/Objects">les objets JavaScript</a>), + <a + href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction" + >les bases des API côté client</a + >. + </td> + </tr> + <tr> + <th scope="row">Objectifs :</th> + <td> + Comprendre le fonctionnement des API tierces et comment les utiliser + pour ajouter des fonctionnalités à ses sites / applications. + </td> + </tr> + </tbody> </table> -<h2 id="Quest-ce_quune_API_tierce">Qu'est-ce qu'une API tierce ?</h2> +## Qu'est-ce qu'une API tierce ? -<p>Les API tierces sont des API qui sont fournis par des tiers, généralement des entreprises comme Facebook, Twitter ou Google, qui permettent d'accéder à leurs données et/ou leurs fonctionnalités grâce à JavaScript afin de les utiliser sur son site. Utiliser une API de cartographie afin d'afficher une carte sur une page est un exemple.</p> +Les API tierces sont des API qui sont fournis par des tiers, généralement des entreprises comme Facebook, Twitter ou Google, qui permettent d'accéder à leurs données et/ou leurs fonctionnalités grâce à JavaScript afin de les utiliser sur son site. Utiliser une API de cartographie afin d'afficher une carte sur une page est un exemple. -<p>Regardons <a href="https://mdn.github.io/learning-area/javascript/apis/third-party-apis/mapquest/">cet exemple qui utilise l'API MapQuest</a> et voyons avec lui les différences entre les API tierces et celles du navigateur.</p> +Regardons [cet exemple qui utilise l'API MapQuest](https://mdn.github.io/learning-area/javascript/apis/third-party-apis/mapquest/) et voyons avec lui les différences entre les API tierces et celles du navigateur. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez <a href="/fr/docs/Apprendre#Obtenir_nos_exemples_de_code">récupérer l'ensemble des exemples de code</a> en une seule fois. Dans ce cas, il vous suffit de rechercher dans votre dépôt les fichiers utilisés pour chaque section.</p> -</div> +> **Note :** Vous pouvez [récupérer l'ensemble des exemples de code](/fr/docs/Apprendre#Obtenir_nos_exemples_de_code) en une seule fois. Dans ce cas, il vous suffit de rechercher dans votre dépôt les fichiers utilisés pour chaque section. -<h3 id="Elles_sont_situées_sur_des_serveurs_tiers">Elles sont situées sur des serveurs tiers</h3> +### Elles sont situées sur des serveurs tiers -<p>Les API fournies par le navigateur sont construites <strong>dans</strong> le navigateur et on peut y accéder immédiatement avec du code JavaScript. Ainsi, l'API Web Audio <a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction#Comment_les_API_fonctionnent-elles"> que nous avons vu dans cet article introductif</a> s'utilise via l'objet {{domxref("AudioContext")}} fourni nativement :</p> +Les API fournies par le navigateur sont construites **dans** le navigateur et on peut y accéder immédiatement avec du code JavaScript. Ainsi, l'API Web Audio [que nous avons vu dans cet article introductif](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction#Comment_les_API_fonctionnent-elles) s'utilise via l'objet {{domxref("AudioContext")}} fourni nativement : -<pre class="brush: js">const audioCtx = new AudioContext(); +```js +const audioCtx = new AudioContext(); ... const audioElement = document.querySelector('audio'); ... const audioSource = audioCtx.createMediaElementSource(audioElement); -// etc.</pre> +// etc. +``` -<p>En revanche, les API tierces sont situées sur des serveurs tiers. Pour y accéder avec JavaScript, il faut d'abord se connecter aux fonctionnalités de l'API afin de les rendre disponibles sur la page. Pour cela, on pourra utiliser une bibliothèque JavaScript disponible sur le serveur via un élément {{htmlelement("script")}}. Pour notre exemple avec MapQuest, voici ce que ça donne :</p> +En revanche, les API tierces sont situées sur des serveurs tiers. Pour y accéder avec JavaScript, il faut d'abord se connecter aux fonctionnalités de l'API afin de les rendre disponibles sur la page. Pour cela, on pourra utiliser une bibliothèque JavaScript disponible sur le serveur via un élément {{htmlelement("script")}}. Pour notre exemple avec MapQuest, voici ce que ça donne : -<pre class="brush: js"><script src="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script> -<link type="text/css" rel="stylesheet" href="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.css"/></pre> +```js +<script src="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script> +<link type="text/css" rel="stylesheet" href="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.css"/> +``` -<p>On peut alors utiliser les objets fournis par cette bibliothèque. Voici un fragment de code qui illustre cette utilisation :</p> +On peut alors utiliser les objets fournis par cette bibliothèque. Voici un fragment de code qui illustre cette utilisation : -<pre class="brush: js">var L; +```js +var L; var map = L.mapquest.map('map', { center: [53.480759, -2.242631], layers: L.mapquest.tileLayer('map'), zoom: 12 -});</pre> +}); +``` -<p>Ici on crée une variable dans laquelle enregistrer les informations de la carte puis on crée une nouvelle carte à l'aide de la méthode <code>mapquest.map()</code> qui prend comme argument :</p> +Ici on crée une variable dans laquelle enregistrer les informations de la carte puis on crée une nouvelle carte à l'aide de la méthode `mapquest.map()` qui prend comme argument : -<ul> - <li>l'identifiant (la valeur de l'attribut <code>id</code>) d'un élément {{htmlelement("div")}} dans lequel on souhaite afficher la carte (ici, c'est <code>"map"</code>)</li> - <li>un objet indiquant les options pour la carte qu'on souhaite afficher. Ici, on indique les coordonnées du centre de la carte, le pavage utilisé (ici on utilise la méthode <code>mapquest.tileLayer()</code> ainsi que le niveau de zoom.</li> -</ul> +- l'identifiant (la valeur de l'attribut `id`) d'un élément {{htmlelement("div")}} dans lequel on souhaite afficher la carte (ici, c'est `"map"`) +- un objet indiquant les options pour la carte qu'on souhaite afficher. Ici, on indique les coordonnées du centre de la carte, le pavage utilisé (ici on utilise la méthode `mapquest.tileLayer()` ainsi que le niveau de zoom. -<p>C'est tout ce dont l'API MapQuest a besoin pour dessiner une carte. C'est le serveur auquel on se connecte qui gère les aspects plus compliqués (comme afficher les bonnes tuiles pour la zone géographique, etc.).</p> +C'est tout ce dont l'API MapQuest a besoin pour dessiner une carte. C'est le serveur auquel on se connecte qui gère les aspects plus compliqués (comme afficher les bonnes tuiles pour la zone géographique, etc.). -<div class="note"> -<p><strong>Note :</strong> Certaines API fonctionnent différemment pour l'accès aux fonctionnalités et passent par une requête HTTP sur une URL spécifique pour récupérer les données. Ces API sont appelées <a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs#A_RESTful_API_%E2%80%94_NYTimes">API REST (ou <em>RESTful APIs</em> en anglais) et nous les abordons plus bas dans l'article</a>.</p> -</div> +> **Note :** Certaines API fonctionnent différemment pour l'accès aux fonctionnalités et passent par une requête HTTP sur une URL spécifique pour récupérer les données. Ces API sont appelées [API REST (ou _RESTful APIs_ en anglais) et nous les abordons plus bas dans l'article](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs#A_RESTful_API_%E2%80%94_NYTimes). -<h3 id="Des_clés_dAPI_sont_nécessaires_pour_les_utiliser">Des clés d'API sont nécessaires pour les utiliser</h3> +### Des clés d'API sont nécessaires pour les utiliser -<p>Dans les navigateurs, <a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction#Elles_ont_des_mécanismes_de_sécurité_supplémentaires_si_nécessaire">comme nous l'avons vu dans le premier article</a>, les sécurités relatives aux API sont gérées via des permissions afin d'avertir l'utilisateur et d'éviter les utilisations malveillantes de la part des sites.</p> +Dans les navigateurs, [comme nous l'avons vu dans le premier article](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction#Elles_ont_des_mécanismes_de_sécurité_supplémentaires_si_nécessaire), les sécurités relatives aux API sont gérées via des permissions afin d'avertir l'utilisateur et d'éviter les utilisations malveillantes de la part des sites. -<p>Pour les API tierces, le système est légèrement différent. Généralement, ce sont des clés qui sont utilisées afin de fournir aux développeurs l'accès aux fonctionnalités de l'API. Dans ce système, la clé sert plutôt à protéger des abus de la part des développeurs envers le site tiers.</p> +Pour les API tierces, le système est légèrement différent. Généralement, ce sont des clés qui sont utilisées afin de fournir aux développeurs l'accès aux fonctionnalités de l'API. Dans ce système, la clé sert plutôt à protéger des abus de la part des développeurs envers le site tiers. -<p>Dans l'exemple MapQuest, vous pourrez trouver une ligne semblable à celle-ci :</p> +Dans l'exemple MapQuest, vous pourrez trouver une ligne semblable à celle-ci : -<pre>L.mapquest.key = 'VOTRE-CLE-D-API-ICI';</pre> + L.mapquest.key = 'VOTRE-CLE-D-API-ICI'; -<p>Cette ligne indique une clé d'API utilisée par notre application. Le développeur de l'application doit obtenir une clé et l'inclure dans le code de l'application afin de pouvoir accéder aux fonctionnalités de l'API. Pour cet exemple, il s'agit d'une valeur imaginaire.</p> +Cette ligne indique une clé d'API utilisée par notre application. Le développeur de l'application doit obtenir une clé et l'inclure dans le code de l'application afin de pouvoir accéder aux fonctionnalités de l'API. Pour cet exemple, il s'agit d'une valeur imaginaire. -<div class="blockIndicator note"> -<p><strong>Note :</strong> Lorsque vous construisez votre propre application, utilisez une « vraie » valeur de clé plutôt que la valeur de substitution fournie en exemple.</p> -</div> +> **Note :** Lorsque vous construisez votre propre application, utilisez une « vraie » valeur de clé plutôt que la valeur de substitution fournie en exemple. -<p>Certaines API peuvent nécessiter de fournir la clé d'une façon différente mais le fonctionnement général reste similaire.</p> +Certaines API peuvent nécessiter de fournir la clé d'une façon différente mais le fonctionnement général reste similaire. -<p>L'existence d'une telle clé d'API permet au fournisseur tiers de contrôler les accès et actions des différents développeurs/utilisateurs. Ainsi, lorsqu'un développeur demande une clé, il devient alors connu du fournisseur de l'API et ce dernier peut agir de son côté si l'API est détournée ou utilisée de façon incorrecte (par exemple pour pister des personnes ou parce que le site du développeur sollicite l'API avec de trop nombreuses requêtes). Dès qu'un usage incorrect est détecté du côté du fournisseur, il suffit alors de révoquer l'accès et de couper ou de limiter les accès pour cette clé.</p> +L'existence d'une telle clé d'API permet au fournisseur tiers de contrôler les accès et actions des différents développeurs/utilisateurs. Ainsi, lorsqu'un développeur demande une clé, il devient alors connu du fournisseur de l'API et ce dernier peut agir de son côté si l'API est détournée ou utilisée de façon incorrecte (par exemple pour pister des personnes ou parce que le site du développeur sollicite l'API avec de trop nombreuses requêtes). Dès qu'un usage incorrect est détecté du côté du fournisseur, il suffit alors de révoquer l'accès et de couper ou de limiter les accès pour cette clé. -<h2 id="Étendre_lexemple_«_MapQuest_»">Étendre l'exemple « MapQuest »</h2> +## Étendre l'exemple « MapQuest » -<p>Ajoutons quelques fonctionnalités à cet exemple MapQuest afin d'illustrer le fonctionnement d'autres aspects de l'API.</p> +Ajoutons quelques fonctionnalités à cet exemple MapQuest afin d'illustrer le fonctionnement d'autres aspects de l'API. -<ol> - <li> - <p>Pour commencer cette section, copiez <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/mapquest/starter-file.html">le fichier initial</a> dans un nouveau répertoire. Si vous avez déjà <a href="/fr/docs/Apprendre#Obtenir_nos_exemples_de_code">cloné le dépôt des exemples</a>, vous disposez déjà d'une copie située sous le répertoire <em>javascript/apis/third-party-apis/mapquest</em>.</p> - </li> - <li> - <p>Ensuite, <a href="https://developer.mapquest.com/">rendez-vous sur le site MapQuest pour les développeurs</a>, créez un compte puis créez une clé de développement (au moment où nous écrivons ces lignes, sur le site, le nom utilisé est "consumer key" et la procédure de création demande aussi la saisie d'une URL "callback URL" qui est optionnelle (vous pouvez la laisser vide).</p> - </li> - <li>Ouvrez un éditeur pour éditer le fichier initial et remplacez la valeur pour la clé d'API avec la vôtre.</li> -</ol> +1. Pour commencer cette section, copiez [le fichier initial](https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/mapquest/starter-file.html) dans un nouveau répertoire. Si vous avez déjà [cloné le dépôt des exemples](/fr/docs/Apprendre#Obtenir_nos_exemples_de_code), vous disposez déjà d'une copie située sous le répertoire _javascript/apis/third-party-apis/mapquest_. +2. Ensuite, [rendez-vous sur le site MapQuest pour les développeurs](https://developer.mapquest.com/), créez un compte puis créez une clé de développement (au moment où nous écrivons ces lignes, sur le site, le nom utilisé est "consumer key" et la procédure de création demande aussi la saisie d'une URL "callback URL" qui est optionnelle (vous pouvez la laisser vide). +3. Ouvrez un éditeur pour éditer le fichier initial et remplacez la valeur pour la clé d'API avec la vôtre. -<h3 id="Modifier_le_type_de_la_carte">Modifier le type de la carte</h3> +### Modifier le type de la carte -<p>L'API MapQuest permet d'afficher différents types de carte. Localisez la ligne suivante dans votre fichier :</p> +L'API MapQuest permet d'afficher différents types de carte. Localisez la ligne suivante dans votre fichier : -<pre class="brush: js">layers: L.mapquest.tileLayer('map')</pre> +```js +layers: L.mapquest.tileLayer('map') +``` -<p>Ici, vous pouvez changer <code>'map'</code> en <code>'hybrid'</code> afin d'afficher une carte avec un style hybride. Vous pouvez essayer d'autres valeurs comme celles indiquées sur <a href="https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-tile-layer/">la page de référence de la méthode <code>tileLayer()</code></a>.</p> +Ici, vous pouvez changer `'map'` en `'hybrid'` afin d'afficher une carte avec un style hybride. Vous pouvez essayer d'autres valeurs comme celles indiquées sur [la page de référence de la méthode `tileLayer()`](https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-tile-layer/). -<h3 id="Ajouter_différents_contrôles">Ajouter différents contrôles</h3> +### Ajouter différents contrôles -<p>Sur la carte, on peut utiliser différents contrôles. Par défaut, seul un contrôle pour le zoom est affiché. Il est possible d'étendre les contrôles disponibles en utilisant la méthode<code>map.addControl()</code>. Ajoutez la ligne suivante à l'intérieur du gestionnaire <code>window.onload</code> :</p> +Sur la carte, on peut utiliser différents contrôles. Par défaut, seul un contrôle pour le zoom est affiché. Il est possible d'étendre les contrôles disponibles en utilisant la méthode`map.addControl()`. Ajoutez la ligne suivante à l'intérieur du gestionnaire `window.onload` : -<pre class="brush: js">map.addControl(L.mapquest.control());</pre> +```js +map.addControl(L.mapquest.control()); +``` -<p>La méthode <a href="https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-control/"><code>mapquest.control()</code></a> crée un ensemble complet de contrôle et est placée, par défaut, dans le coin supérieur droit de la carte. Cette position peut être ajustée grâce à un paramètre d'options contenant une propriété <code>position</code> dont la valeur est un mot-clé décrivant la position souhaitée. Vous pouvez modifier la ligne de la façon suivante par exemple :</p> +La méthode [`mapquest.control()`](https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-control/) crée un ensemble complet de contrôle et est placée, par défaut, dans le coin supérieur droit de la carte. Cette position peut être ajustée grâce à un paramètre d'options contenant une propriété `position` dont la valeur est un mot-clé décrivant la position souhaitée. Vous pouvez modifier la ligne de la façon suivante par exemple : -<pre class="brush: js"> map.addControl(L.mapquest.control({ position: 'bottomright' }));</pre> +```js + map.addControl(L.mapquest.control({ position: 'bottomright' })); +``` -<p>D'autres types de contrôle sont disponibles comme <code><a href="https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-search-control/">mapquest.searchControl()</a></code> et <code><a href="https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-satellite-control/">mapquest.satelliteControl()</a></code>. Certains sont avancés et permettent de nombreuses choses. N'hésitez pas à en essayer différents pour voir ce qui vous semble le mieux pour votre projet.</p> +D'autres types de contrôle sont disponibles comme [`mapquest.searchControl()`](https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-search-control/) et [`mapquest.satelliteControl()`](https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-satellite-control/). Certains sont avancés et permettent de nombreuses choses. N'hésitez pas à en essayer différents pour voir ce qui vous semble le mieux pour votre projet. -<h3 id="Ajouter_un_marqueur_personnalisé">Ajouter un marqueur personnalisé</h3> +### Ajouter un marqueur personnalisé -<p>Pour ajouter une icône sur un point de la carte, on pourra utiliser la méthode <code><a href="https://leafletjs.com/reference-1.3.0.html#marker">L.marker()</a></code> (documentée dans la documentation de Leaflet.js). Dans <code>window.onload</code>, vous pouvez ajouter le fragment de code suivante <code>window.onload</code> :</p> +Pour ajouter une icône sur un point de la carte, on pourra utiliser la méthode [`L.marker()`](https://leafletjs.com/reference-1.3.0.html#marker) (documentée dans la documentation de Leaflet.js). Dans `window.onload`, vous pouvez ajouter le fragment de code suivante `window.onload` : -<pre class="brush: js">L.marker([53.480759, -2.242631], { +```js +L.marker([53.480759, -2.242631], { icon: L.mapquest.icons.marker({ primaryColor: '#22407F', secondaryColor: '#3B5998', @@ -142,158 +155,142 @@ var map = L.mapquest.map('map', { }) }) .bindPopup('Ici se trouve Manchester !') -.addTo(map);</pre> +.addTo(map); +``` -<p>Comme on peut le voir ici, la méthode peut prendre deux paramètres :</p> +Comme on peut le voir ici, la méthode peut prendre deux paramètres : -<ul> - <li>le premier qui contient les coordonnées géographiques de l'emplacement où afficher le pointeur sous la forme d'un tableau</li> - <li>le deuxième qui est un objet d'options contenant une propriété <code>icon</code> qui définit l'icône à afficher à cet emplacement.</li> -</ul> +- le premier qui contient les coordonnées géographiques de l'emplacement où afficher le pointeur sous la forme d'un tableau +- le deuxième qui est un objet d'options contenant une propriété `icon` qui définit l'icône à afficher à cet emplacement. -<p>L'icône est définie via un appel à la méthode <code><a href="https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-icons/">mapquest.icons.marker()</a></code> à laquelle on fournit des informations telles que la couleur et la taille du marqueur.</p> +L'icône est définie via un appel à la méthode [`mapquest.icons.marker()`](https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-icons/) à laquelle on fournit des informations telles que la couleur et la taille du marqueur. -<p>Après l'appel à la première méthode, on enchaîne avec un appel avec <code>.bindPopup('Ici se trouve Manchester !')</code>, qui fournit le contenu à afficher lorsqu'on cliquera sur le marqueur.</p> +Après l'appel à la première méthode, on enchaîne avec un appel avec `.bindPopup('Ici se trouve Manchester !')`, qui fournit le contenu à afficher lorsqu'on cliquera sur le marqueur. -<p>Enfin, on chaîne un appel <code>.addTo(map)</code> pour ajouter le marqueur sur la carte.</p> +Enfin, on chaîne un appel `.addTo(map)` pour ajouter le marqueur sur la carte. -<p>Essayez les différentes options que vous trouverez dans la documentation et voyez quel résultat vous pouvez obtenir ! MapQuest fournit certaines fonctionnalités relativement avancées (itinéraire, recherche, etc.).</p> +Essayez les différentes options que vous trouverez dans la documentation et voyez quel résultat vous pouvez obtenir ! MapQuest fournit certaines fonctionnalités relativement avancées (itinéraire, recherche, etc.). -<div class="blockIndicator note"> -<p><strong>Note :</strong> Si vous ne parvenez pas à faire fonctionner l'exemple, vous pouvez consulter la version finalisée de notre exemple : <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/mapquest/expanded-example.html">expanded-example.html</a>.</p> -</div> +> **Note :** Si vous ne parvenez pas à faire fonctionner l'exemple, vous pouvez consulter la version finalisée de notre exemple : [expanded-example.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/mapquest/expanded-example.html). -<h2 id="Quid_de_Google_Maps">Quid de Google Maps ?</h2> +## Quid de Google Maps ? -<p>Google Maps est sans doute l'API de cartographie la plus populaire. Pourquoi ne l'avons-nous pas incluse ici ? Nous avons choisi MapQuest pour plusieurs raisons :</p> +Google Maps est sans doute l'API de cartographie la plus populaire. Pourquoi ne l'avons-nous pas incluse ici ? Nous avons choisi MapQuest pour plusieurs raisons : -<ul> - <li>L'utilisation est beaucoup plus simple. Pour les API Google, il faut créer un compte Google, se connecter à la <a href="https://console.cloud.google.com">Google Cloud Platform Console</a> pour créer des clés d'API avec une procédure assez complexe.</li> - <li>Pour utiliser l'API <a href="https://cloud.google.com/maps-platform/">Google Maps</a> et bien qu'un usage léger soit gratuit, il est nécessaire de fournir une carte de crédit à des fins de facturation et nous pensions que cela n'était pas acceptable pour un tel tutoriel.</li> - <li>Nous souhaitions montrer que des alternatives étaient disponibles.</li> -</ul> +- L'utilisation est beaucoup plus simple. Pour les API Google, il faut créer un compte Google, se connecter à la [Google Cloud Platform Console](https://console.cloud.google.com) pour créer des clés d'API avec une procédure assez complexe. +- Pour utiliser l'API [Google Maps](https://cloud.google.com/maps-platform/) et bien qu'un usage léger soit gratuit, il est nécessaire de fournir une carte de crédit à des fins de facturation et nous pensions que cela n'était pas acceptable pour un tel tutoriel. +- Nous souhaitions montrer que des alternatives étaient disponibles. -<h2 id="Une_approche_pour_utiliser_les_API_tierces">Une approche pour utiliser les API tierces</h2> +## Une approche pour utiliser les API tierces -<h3 id="Une_API_REST_du_NYTimes">Une API REST du NYTimes</h3> +### Une API REST du NYTimes -<p>Prenons un autre exemple d'API, l'API du <a href="https://developer.nytimes.com">New York Times</a>. Cette API permet de récupérer les informations provenant du New York Times et de les afficher sur votre site. Cette API est ce qu'on appelle une API REST car elle permet de récupérer des données via des requêtes HTTP sur des URL spécifiques dans lesquelles on peut fournir des données comme des termes de recherches (souvent encodés comme paramètres dans l'URL). Ce type d'API est relativement fréquent.</p> +Prenons un autre exemple d'API, l'API du [New York Times](https://developer.nytimes.com). Cette API permet de récupérer les informations provenant du New York Times et de les afficher sur votre site. Cette API est ce qu'on appelle une API REST car elle permet de récupérer des données via des requêtes HTTP sur des URL spécifiques dans lesquelles on peut fournir des données comme des termes de recherches (souvent encodés comme paramètres dans l'URL). Ce type d'API est relativement fréquent. -<p>Construisons un second exemple pour comprendre comment utiliser l'API du NYTimes. Au fur et à mesure nous décrirons également une approche plus générale pour consommer d'autres API tierces.</p> +Construisons un second exemple pour comprendre comment utiliser l'API du NYTimes. Au fur et à mesure nous décrirons également une approche plus générale pour consommer d'autres API tierces. -<h3 id="Trouver_la_documentation">Trouver la documentation</h3> +### Trouver la documentation -<p>Lorsqu'on veut utiliser une API tierce, il est toujours utile de trouver la documentation correspondante pour connaître les fonctionnalités offertes, comment les utiliser, etc. La documentation de l'API du New York Times API se situe ici : <a href="https://developer.nytimes.com/">https://developer.nytimes.com/</a>.</p> +Lorsqu'on veut utiliser une API tierce, il est toujours utile de trouver la documentation correspondante pour connaître les fonctionnalités offertes, comment les utiliser, etc. La documentation de l'API du New York Times API se situe ici : <https://developer.nytimes.com/>. -<h3 id="Obtenir_une_clé_de_développement">Obtenir une clé de développement</h3> +### Obtenir une clé de développement -<p>La plupart des API reposent sur l'obtention et l'utilisation d'une clé de développement (tant pour des raisons de sécurité que de responsabilité). Pour obtenir une clé de développement pour l'API du NYTimes, vous pouvez suivre les instructions de <a href="https://developer.nytimes.com/get-started">https://developer.nytimes.com/get-started</a>.</p> +La plupart des API reposent sur l'obtention et l'utilisation d'une clé de développement (tant pour des raisons de sécurité que de responsabilité). Pour obtenir une clé de développement pour l'API du NYTimes, vous pouvez suivre les instructions de <https://developer.nytimes.com/get-started>. -<ol> - <li> - <p>Demandez une clé pour l'API Article Search — créez une nouvelle application et sélectionnez cette API, fournissez un nom et une description pour votre application, activez le bouton sous "Article Search API" puis cliquez sur "Create").</p> - </li> - <li> - <p>Vous pouvez alors récupérer la clé d'API à partir de la page suivante.</p> - </li> - <li> - <p>Pour construire le socle de notre exemple, copiez <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/nytimes/nytimes_start.html">nytimes_start.html</a> et <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/nytimes/nytimes.css">nytimes.css</a> dans un nouveau répertoire sur votre ordinateur. Si vous avez déjà <a href="/fr/docs/Apprendre#Obtenir_nos_exemples_de_code">cloné le dépôt des exemples</a>, vous disposez déjà d'un exemplaire de ces fichiers et vous pourrez les trouver sous le répertoire <em>javascript/apis/third-party-apis/nytimes</em>. L'élément <code><script></code> contient un certain nombre de variables nécessaires à l'initialisation de l'exemple. Nous allons ensuite remplir les fonctionnalités nécessaires.</p> - </li> -</ol> +1. Demandez une clé pour l'API Article Search — créez une nouvelle application et sélectionnez cette API, fournissez un nom et une description pour votre application, activez le bouton sous "Article Search API" puis cliquez sur "Create"). +2. Vous pouvez alors récupérer la clé d'API à partir de la page suivante. +3. Pour construire le socle de notre exemple, copiez [nytimes_start.html](https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/nytimes/nytimes_start.html) et [nytimes.css](https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/nytimes/nytimes.css) dans un nouveau répertoire sur votre ordinateur. Si vous avez déjà [cloné le dépôt des exemples](/fr/docs/Apprendre#Obtenir_nos_exemples_de_code), vous disposez déjà d'un exemplaire de ces fichiers et vous pourrez les trouver sous le répertoire _javascript/apis/third-party-apis/nytimes_. L'élément `<script>` contient un certain nombre de variables nécessaires à l'initialisation de l'exemple. Nous allons ensuite remplir les fonctionnalités nécessaires. -<p>Au final, on souhaite que l'application permette de saisir un terme de recherche, des dates optionnelles pour le début et la fin de la période à rechercher. Nous utiliserons alors ces paramètres afin de d'envoyer des requêtes sur l'API Article Search puis nous afficherons les résultats obtenus.</p> +Au final, on souhaite que l'application permette de saisir un terme de recherche, des dates optionnelles pour le début et la fin de la période à rechercher. Nous utiliserons alors ces paramètres afin de d'envoyer des requêtes sur l'API Article Search puis nous afficherons les résultats obtenus. -<p><img alt="" src="nytimes-search.png"></p> + -<h3 id="Connecter_lAPI_à_son_application">Connecter l'API à son application</h3> +### Connecter l'API à son application -<p>Tout d'abord, vous devrez créer une connexion entre l'API et votre application. Pour cette API, vous devez fournir la clé d'API comme paramètre <a href="/fr/docs/Web/HTTP/Méthode/GET">GET</a> à chaque requête.</p> +Tout d'abord, vous devrez créer une connexion entre l'API et votre application. Pour cette API, vous devez fournir la clé d'API comme paramètre [GET](/fr/docs/Web/HTTP/Méthode/GET) à chaque requête. -<ol> - <li> - <p>Localisez la ligne qui suit et remplacez la valeur avec la clé de développement que vous avez obtenu plus tôt :</p> +1. Localisez la ligne qui suit et remplacez la valeur avec la clé de développement que vous avez obtenu plus tôt : - <pre class="brush: js">var key = ' ... ';</pre> - </li> - <li> - <p>Ajoutez la ligne suivante sous le commentaire <code>// Event listeners to control the functionality</code>. Cette ligne permet d'exécuter la fonction <code>submitSearch()</code> lorsque le formulaire est envoyé (quand on presse le bouton).</p> + ```js + var key = ' ... '; + ``` - <pre class="brush: js">searchForm.addEventListener('submit', submitSearch);</pre> - </li> - <li> - <p>Sous cette nouvelle ligne, ajoutons les fonctions <code>submitSearch()</code> et <code>fetchResults()</code> :</p> +2. Ajoutez la ligne suivante sous le commentaire `// Event listeners to control the functionality`. Cette ligne permet d'exécuter la fonction `submitSearch()` lorsque le formulaire est envoyé (quand on presse le bouton). - <pre class="brush: js">function submitSearch(e) { - pageNumber = 0; - fetchResults(e); -} + ```js + searchForm.addEventListener('submit', submitSearch); + ``` + +3. Sous cette nouvelle ligne, ajoutons les fonctions `submitSearch()` et `fetchResults()` : -function fetchResults(e) { - // On utilise preventDefault() afin d'éviter - // l'envoie vers notre serveur et le rafraîchissement - // de la page - e.preventDefault(); + ```js + function submitSearch(e) { + pageNumber = 0; + fetchResults(e); + } - // On compose l'URL - url = baseURL + '?api-key=' + key + '&page=' + pageNumber + '&q=' + searchTerm.value + '&fq=document_type:("article")'; + function fetchResults(e) { + // On utilise preventDefault() afin d'éviter + // l'envoie vers notre serveur et le rafraîchissement + // de la page + e.preventDefault(); - if(startDate.value !== '') { - url += '&begin_date=' + startDate.value; - }; + // On compose l'URL + url = baseURL + '?api-key=' + key + '&page=' + pageNumber + '&q=' + searchTerm.value + '&fq=document_type:("article")'; - if(endDate.value !== '') { - url += '&end_date=' + endDate.value; - }; + if(startDate.value !== '') { + url += '&begin_date=' + startDate.value; + }; -}</pre> - </li> -</ol> + if(endDate.value !== '') { + url += '&end_date=' + endDate.value; + }; + + } + ``` -<p><code>submitSearch()</code> commence par réinitialiser le nombre de page à 0 puis appelle <code>fetchResults()</code>. Cette fonction commence par appeler <code><a href="/fr/docs/Web/API/Event/preventDefault">preventDefault()</a></code> sur l'évènement afin d'empêcher l'envoi du formulaire vers notre serveur (ce qui casserait l'exemple). Ensuite, on assemble la chaîne de caractères qui formera l'URL sur laquelle on fera la requête. Dans cette URL, on commence par mettre les fragments « obligatoires » (en tout cas pour cette démonstration) :</p> +`submitSearch()` commence par réinitialiser le nombre de page à 0 puis appelle `fetchResults()`. Cette fonction commence par appeler [`preventDefault()`](/fr/docs/Web/API/Event/preventDefault) sur l'évènement afin d'empêcher l'envoi du formulaire vers notre serveur (ce qui casserait l'exemple). Ensuite, on assemble la chaîne de caractères qui formera l'URL sur laquelle on fera la requête. Dans cette URL, on commence par mettre les fragments « obligatoires » (en tout cas pour cette démonstration) : -<ul> - <li>L'URL de base (telle que fournie par la variable <code>baseURL</code>).</li> - <li>La clé d'API qui a été passée au paramètre d'URL <code>api-key</code> et dont la valeur dans notre script est fournie par la variable <code>key</code>.</li> - <li>Le nombre de pages est fourni dans l'URL avec le paramètre <code>page</code> et provient de la variable <code>pageNumber</code> dans notre script.</li> - <li>Le terme de la recherche est fourni dans l'URL avec le paramètre <code>q</code> et provient du texte <code>searchTerm</code> fourni par l'élément {{htmlelement("input")}}.</li> - <li>Le type de document qu'on souhaite obtenir dans les résultats est une expression passée via le paramètre <code>fq</code> de l'URL. Ici, on souhaite obtenir les articles.</li> -</ul> +- L'URL de base (telle que fournie par la variable `baseURL`). +- La clé d'API qui a été passée au paramètre d'URL `api-key` et dont la valeur dans notre script est fournie par la variable `key`. +- Le nombre de pages est fourni dans l'URL avec le paramètre `page` et provient de la variable `pageNumber` dans notre script. +- Le terme de la recherche est fourni dans l'URL avec le paramètre `q` et provient du texte `searchTerm` fourni par l'élément {{htmlelement("input")}}. +- Le type de document qu'on souhaite obtenir dans les résultats est une expression passée via le paramètre `fq` de l'URL. Ici, on souhaite obtenir les articles. -<p>Après, on utilise un ensemble d'instructions <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">if()</a></code> pour vérifier si des valeurs ont été fournies pour les champs <code>startDate</code> et <code>endDate</code> dans le formulaire. Si c'est le cas, on utilise ces valeurs pour renseigner les paramètres d'URL <code>begin_date</code> et/ou <code>end_date</code>.</p> +Après, on utilise un ensemble d'instructions [`if()`](/fr/docs/Web/JavaScript/Reference/Instructions/if...else) pour vérifier si des valeurs ont été fournies pour les champs `startDate` et `endDate` dans le formulaire. Si c'est le cas, on utilise ces valeurs pour renseigner les paramètres d'URL `begin_date` et/ou `end_date`. -<p>Si on prend un exemple d'URL complète ainsi construite :</p> +Si on prend un exemple d'URL complète ainsi construite : -<pre>https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=YOUR-API-KEY-HERE&page=0&q=cats -&fq=document_type:("article")&begin_date=20170301&end_date=20170312 </pre> + https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=YOUR-API-KEY-HERE&page=0&q=cats + &fq=document_type:("article")&begin_date=20170301&end_date=20170312 -<div class="note"> -<p><strong>Note :</strong> Pour en savoir plus sur les différents paramètres d'URL qui peuvent être utilisés, vous pouvez consulter <a href="https://developer.nytimes.com/">la documentation du NYTimes</a>.</p> -</div> +> **Note :** Pour en savoir plus sur les différents paramètres d'URL qui peuvent être utilisés, vous pouvez consulter [la documentation du NYTimes](https://developer.nytimes.com/). -<div class="note"> -<p><strong>Note :</strong> Dans cet exemple, la validation du formulaire est assez rudimentaire : le terme recherché doit nécessairement être renseigné avant de pouvoir valider le formulaire grâce à l'attribut <code>required</code>. Les champs pour les dates doivent suivre un format particulier et elles ne seront pas envoyées tant que leur valeur ne se composera pas de 8 chiffres (en HTML, c'est ce qui est indiqué par l'attribut <code>pattern="[0-9]{8}"</code>). Voir la page sur <a href="/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire">la validation des données d'un formulaire</a> pour en savoir plus sur ce fonctionnement.</p> -</div> +> **Note :** Dans cet exemple, la validation du formulaire est assez rudimentaire : le terme recherché doit nécessairement être renseigné avant de pouvoir valider le formulaire grâce à l'attribut `required`. Les champs pour les dates doivent suivre un format particulier et elles ne seront pas envoyées tant que leur valeur ne se composera pas de 8 chiffres (en HTML, c'est ce qui est indiqué par l'attribut `pattern="[0-9]{8}"`). Voir la page sur [la validation des données d'un formulaire](/fr/docs/Web/Guide/HTML/Formulaires/Validation_donnees_formulaire) pour en savoir plus sur ce fonctionnement. -<h3 id="Récupérer_des_données_depuis_lAPI">Récupérer des données depuis l'API</h3> +### Récupérer des données depuis l'API -<p>Maintenant que nous avons construit notre URL, envoyons une requête à cet endroit. Pour cela, nous utiliserons l'<a href="/fr/docs/Web/API/Fetch_API/Using_Fetch">API Fetch</a>.</p> +Maintenant que nous avons construit notre URL, envoyons une requête à cet endroit. Pour cela, nous utiliserons l'[API Fetch](/fr/docs/Web/API/Fetch_API/Using_Fetch). -<p>Dans la fonction <code>fetchResults()</code>, juste avant l'accolade de fin, ajoutez le fragment de code suivant :</p> +Dans la fonction `fetchResults()`, juste avant l'accolade de fin, ajoutez le fragment de code suivant : -<pre class="brush: js">// On utilise fetch() pour envoyer la requête à l'API +```js +// On utilise fetch() pour envoyer la requête à l'API fetch(url).then(function(result) { return result.json(); }).then(function(json) { displayResults(json); -});</pre> +}); +``` -<p>On envoie la requête en passant la variable <code>url</code> comme paramètre à la fonction <code><a href="/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code> puis on convertit le corps de la réponse avec la fonction <code><a href="/fr/docs/Web/API/Body/json">json()</a></code> puis on passe le JSON ainsi obtenu à la fonction <code>displayResults()</code> afin que les données puissent être affichées dans l'interface utilisateur.</p> +On envoie la requête en passant la variable `url` comme paramètre à la fonction [`fetch()`](/fr/docs/Web/API/WindowOrWorkerGlobalScope/fetch) puis on convertit le corps de la réponse avec la fonction [`json()`](/fr/docs/Web/API/Body/json) puis on passe le JSON ainsi obtenu à la fonction `displayResults()` afin que les données puissent être affichées dans l'interface utilisateur. -<h3 id="Afficher_les_données">Afficher les données</h3> +### Afficher les données -<p>Voyons maintenant comment afficher les données reçues. Dans le fichier contenant votre code, ajoutez la fonction suivante après la fonction <code>fetchResults()</code>.</p> +Voyons maintenant comment afficher les données reçues. Dans le fichier contenant votre code, ajoutez la fonction suivante après la fonction `fetchResults()`. -<pre class="brush: js">function displayResults(json) { +```js +function displayResults(json) { while (section.firstChild) { section.removeChild(section.firstChild); } @@ -311,7 +308,7 @@ fetch(url).then(function(result) { para.textContent = 'Aucun résultat reçu.' section.appendChild(para); } else { - for(var i = 0; i < articles.length; i++) { + for(var i = 0; i < articles.length; i++) { var article = document.createElement('article'); var heading = document.createElement('h2'); var link = document.createElement('a'); @@ -327,13 +324,13 @@ fetch(url).then(function(result) { link.textContent = current.headline.main; para1.textContent = current.snippet; para2.textContent = 'Mots-clés : '; - for(var j = 0; j < current.keywords.length; j++) { + for(var j = 0; j < current.keywords.length; j++) { var span = document.createElement('span'); span.textContent += current.keywords[j].value + ' '; para2.appendChild(span); } - if(current.multimedia.length > 0) { + if(current.multimedia.length > 0) { img.src = 'http://www.nytimes.com/' + current.multimedia[0].url; img.alt = current.headline.main; } @@ -349,93 +346,83 @@ fetch(url).then(function(result) { section.appendChild(article); } } -}</pre> - -<p>Il y a pas mal de code ici. Reprenons étape par étape pour l'expliquer :</p> - -<ul> - <li>La boucle <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/while">while</a></code> est utilisée afin de supprimer tout le contenu d'un élément du DOM. Dans ce cas, on enlève ce qu'il y a dans l'élément {{htmlelement("section")}}. On teste si la <code><section></code> possède un élément fils et si c'est le cas, on retire le premier, ainsi de suite jusqu'à ce que l'élément <code><section></code> n'ait plus d'éléments fils.</li> - <li>Ensuite, on renseigne la variable <code>articles</code> avec <code>json.response.docs</code> : le tableau contenant les objets qui représentent les articles renvoyés par la recherche. Ce renommage sert uniquement à rendre le code plus simple.</li> - <li>Le premier bloc <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">if()</a></code> vérifie si 10 ont été renvoyés par l'API (cette dernière envoie les articles par bloc de 10 à chaque appel). Dans ce cas, on affiche l'élément {{htmlelement("nav")}} qui contient des boutons de pagination <em>10 articles précédents</em>/<em>10 articles suivants</em>. S'il y a moins de 10 articles, tout le contenu tiendra sur une page et il ne sera pas nécessaire d'avoir les boutons. Nous verrons comment « câbler » ces boutons pour qu'ils fonctionnent dans la prochaine section.</li> - <li>Le bloc <code>if()</code> suivant sert à vérifier si aucun article n'a été renvoyé. Lorsqu'il n'y a aucun résultat, on crée un élément {{htmlelement("p")}} qui affiche le texte "Aucun résultat reçu" puis on insère ce paragraphe dans l'élément <code><section></code>.</li> - <li>Si des articles sont renvoyés, on commence par créer les éléments qu'on souhaite utiliser afin de les afficher puis on insère le contenu dans chaque puis on insère ces éléments dans le DOM. Pour connaître les propriétés des objets obtenues via l'API, nous avons consulté la référence de l'API <em>Article Search</em> (voir <a href="https://developer.nytimes.com/apis">les API NYTimes</a>). La plupart de ces opérations sont assez parlantes mais voici quelques-unes qui sont notables : - <ul> - <li>On utilise une boucle <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/for">for</a></code> (<code>for(var j = 0; j < current.keywords.length; j++) { ... }</code> ) pour parcourir les mots-clés associés à chaque article et on insère ces mots-clés dans des éléments {{htmlelement("span")}} à l'intérieur d'un paragraphe <code><p></code>. De cette façon, nous pourrons plus facilement mettre en forme ces mots-clés.</li> - <li>On utilise un bloc <code>if()</code> (<code>if(current.multimedia.length > 0) { ... }</code>) afin de voir si l'article possède des images associées. Si c'est le cas, on affiche la première image qui existe.</li> - <li>On applique la classe <code>"clearfix"</code> à l'élément <code><div></code> afin de pouvoir le dégager.</li> - </ul> - </li> -</ul> - -<h3 id="Câbler_les_boutons_pour_la_pagination">Câbler les boutons pour la pagination</h3> - -<p>Pour que les boutons de pagination fonctionnent, on incrémente (ou on décrémente) la valeur de la variable <code>pageNumber</code> puis on renvoie une requête avec la nouvelle valeur incluse dans le paramètre de l'URL <code>page</code>. Cela fonctionne car l'API du NYTimes ne renvoie que 10 résultats à la fois. S'il y a plus de 10 résultats disponibles, la requête renverra les 10 premiers (0 à 9) lorsque le paramètre <code>page</code> vaut 0 dans l'URL (ou lorsqu'il n'est pas inclus du tout, c'est la valeur par défaut). Les 10 prochains résultats (10 à 19) peuvent être récupérés lorsque le paramètre <code>page</code> vaut 1 et ainsi de suite.</p> - -<p>En connaissant cela, on peut écrire une fonction pour gérer la pagination.</p> - -<ol> - <li> - <p>Après l'appel existant à <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>, on ajoute les deux prochaines lignes qui appelleront les fonctions <code>nextPage()</code> et <code>previousPage()</code> lorsqu'on cliquera sur le bouton correspondant :</p> - - <pre class="brush: js">nextBtn.addEventListener('click', nextPage); -previousBtn.addEventListener('click', previousPage);</pre> - </li> - <li> - <p>À la suite, on définit le corps de ces fonctions :</p> - - <pre class="brush: js">function nextPage(e) { - pageNumber++; - fetchResults(e); -}; - -function previousPage(e) { - if(pageNumber > 0) { - pageNumber--; - } else { - return; - } - fetchResults(e); -};</pre> +} +``` + +Il y a pas mal de code ici. Reprenons étape par étape pour l'expliquer : + +- La boucle [`while`](/fr/docs/Web/JavaScript/Reference/Instructions/while) est utilisée afin de supprimer tout le contenu d'un élément du DOM. Dans ce cas, on enlève ce qu'il y a dans l'élément {{htmlelement("section")}}. On teste si la `<section>` possède un élément fils et si c'est le cas, on retire le premier, ainsi de suite jusqu'à ce que l'élément `<section>` n'ait plus d'éléments fils. +- Ensuite, on renseigne la variable `articles` avec `json.response.docs` : le tableau contenant les objets qui représentent les articles renvoyés par la recherche. Ce renommage sert uniquement à rendre le code plus simple. +- Le premier bloc [`if()`](/fr/docs/Web/JavaScript/Reference/Instructions/if...else) vérifie si 10 ont été renvoyés par l'API (cette dernière envoie les articles par bloc de 10 à chaque appel). Dans ce cas, on affiche l'élément {{htmlelement("nav")}} qui contient des boutons de pagination _10 articles précédents_/_10 articles suivants_. S'il y a moins de 10 articles, tout le contenu tiendra sur une page et il ne sera pas nécessaire d'avoir les boutons. Nous verrons comment « câbler » ces boutons pour qu'ils fonctionnent dans la prochaine section. +- Le bloc `if()` suivant sert à vérifier si aucun article n'a été renvoyé. Lorsqu'il n'y a aucun résultat, on crée un élément {{htmlelement("p")}} qui affiche le texte "Aucun résultat reçu" puis on insère ce paragraphe dans l'élément `<section>`. +- Si des articles sont renvoyés, on commence par créer les éléments qu'on souhaite utiliser afin de les afficher puis on insère le contenu dans chaque puis on insère ces éléments dans le DOM. Pour connaître les propriétés des objets obtenues via l'API, nous avons consulté la référence de l'API _Article Search_ (voir [les API NYTimes](https://developer.nytimes.com/apis)). La plupart de ces opérations sont assez parlantes mais voici quelques-unes qui sont notables : + + - On utilise une boucle [`for`](/fr/docs/Web/JavaScript/Reference/Instructions/for) (`for(var j = 0; j < current.keywords.length; j++) { ... }` ) pour parcourir les mots-clés associés à chaque article et on insère ces mots-clés dans des éléments {{htmlelement("span")}} à l'intérieur d'un paragraphe `<p>`. De cette façon, nous pourrons plus facilement mettre en forme ces mots-clés. + - On utilise un bloc `if()` (`if(current.multimedia.length > 0) { ... }`) afin de voir si l'article possède des images associées. Si c'est le cas, on affiche la première image qui existe. + - On applique la classe `"clearfix"` à l'élément `<div>` afin de pouvoir le dégager. + +### Câbler les boutons pour la pagination + +Pour que les boutons de pagination fonctionnent, on incrémente (ou on décrémente) la valeur de la variable `pageNumber` puis on renvoie une requête avec la nouvelle valeur incluse dans le paramètre de l'URL `page`. Cela fonctionne car l'API du NYTimes ne renvoie que 10 résultats à la fois. S'il y a plus de 10 résultats disponibles, la requête renverra les 10 premiers (0 à 9) lorsque le paramètre `page` vaut 0 dans l'URL (ou lorsqu'il n'est pas inclus du tout, c'est la valeur par défaut). Les 10 prochains résultats (10 à 19) peuvent être récupérés lorsque le paramètre `page` vaut 1 et ainsi de suite. + +En connaissant cela, on peut écrire une fonction pour gérer la pagination. + +1. Après l'appel existant à [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener), on ajoute les deux prochaines lignes qui appelleront les fonctions `nextPage()` et `previousPage()` lorsqu'on cliquera sur le bouton correspondant : + + ```js + nextBtn.addEventListener('click', nextPage); + previousBtn.addEventListener('click', previousPage); + ``` + +2. À la suite, on définit le corps de ces fonctions : + + ```js + function nextPage(e) { + pageNumber++; + fetchResults(e); + }; + + function previousPage(e) { + if(pageNumber > 0) { + pageNumber--; + } else { + return; + } + fetchResults(e); + }; + ``` - <p>La première fonction est assez simple : on incrémente la variable <code>pageNumber</code> puis on exécute à nouveau la fonction <code>fetchResults()</code> afin d'afficher les prochains résultats.</p> + La première fonction est assez simple : on incrémente la variable `pageNumber` puis on exécute à nouveau la fonction `fetchResults()` afin d'afficher les prochains résultats. - <p>La seconde fonction est similaire, mais on prend la précaution de vérifier que <code>pageNumber</code> ne vaut pas déjà 0 avant de diminuer sa valeur (si la requête est envoyée avec un paramètre négatif, on pourrait avoir une erreur). Lorsque <code>pageNumber</code> vaut déjà 0, on sort de la fonction avec <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/return">return</a></code> afin d'éviter de lancer une requête pour rien (si on est déjà sur la première page, pas besoin de recharger les résultats à nouveau).</p> - </li> -</ol> + La seconde fonction est similaire, mais on prend la précaution de vérifier que `pageNumber` ne vaut pas déjà 0 avant de diminuer sa valeur (si la requête est envoyée avec un paramètre négatif, on pourrait avoir une erreur). Lorsque `pageNumber` vaut déjà 0, on sort de la fonction avec [`return`](/fr/docs/Web/JavaScript/Reference/Instructions/return) afin d'éviter de lancer une requête pour rien (si on est déjà sur la première page, pas besoin de recharger les résultats à nouveau). -<div class="blockIndicator note"> -<p><strong>Note :</strong> Vous pouvez trouver <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/nytimes/index.html">l'exemple complet sur l'API du NYTimes sur GitHub</a>.</p> -</div> +> **Note :** Vous pouvez trouver [l'exemple complet sur l'API du NYTimes sur GitHub](https://github.com/mdn/learning-area/blob/master/javascript/apis/third-party-apis/nytimes/index.html). -<h2 id="Exemple_dutilisation_de_lAPI_YouTube">Exemple d'utilisation de l'API YouTube</h2> +## Exemple d'utilisation de l'API YouTube -<p>Nous avons également mis à disposition un autre exemple que vous pouvez étudier et adapter : <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/third-party-apis/youtube">exemple de recherche de vidéo YouTube</a>. Dans cet exemple, on utilise deux API :</p> +Nous avons également mis à disposition un autre exemple que vous pouvez étudier et adapter : [exemple de recherche de vidéo YouTube](https://github.com/mdn/learning-area/tree/master/javascript/apis/third-party-apis/youtube). Dans cet exemple, on utilise deux API : -<ul> - <li><a href="https://developers.google.com/youtube/v3/docs/">L'API YouTube Data</a> qui permet de chercher parmi les vidéos YouTube et de renvoyer des résultats.</li> - <li><a href="https://developers.google.com/youtube/iframe_api_reference">L'API YouTube IFrame Player</a> afin d'afficher les vidéos recherchées dans un lecteur vidéo, affiché dans une <em>iframe</em> pour les regarder.</li> -</ul> +- [L'API YouTube Data](https://developers.google.com/youtube/v3/docs/) qui permet de chercher parmi les vidéos YouTube et de renvoyer des résultats. +- [L'API YouTube IFrame Player](https://developers.google.com/youtube/iframe_api_reference) afin d'afficher les vidéos recherchées dans un lecteur vidéo, affiché dans une _iframe_ pour les regarder. -<p>Cet exemple est intéressant car il permet d'illustrer l'utilisation combinée de deux API tierces pour construire une application. La première API est une API REST tandis que la seconde est plus proche du fonctionnement de MapQuest (des méthodes spécifiques à l'API, etc.). On notera que les deux API ont besoin qu'une bibliothèque JavaScript soit chargée sur la page. L'API REST possède des fonctions qui permettent de gérer les requêtes HTTP et de renvoyer les résultats.</p> +Cet exemple est intéressant car il permet d'illustrer l'utilisation combinée de deux API tierces pour construire une application. La première API est une API REST tandis que la seconde est plus proche du fonctionnement de MapQuest (des méthodes spécifiques à l'API, etc.). On notera que les deux API ont besoin qu'une bibliothèque JavaScript soit chargée sur la page. L'API REST possède des fonctions qui permettent de gérer les requêtes HTTP et de renvoyer les résultats. -<p><img alt="" src="youtube-example.png"></p> + -<p>Nous n'allons pas détailler plus encore cet exemple ici, vous pouvez <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/third-party-apis/youtube">consulter le code source</a> qui contient des commentaires expliquant son fonctionnement. Là encore, pour utiliser vous-même l'exemple, vous aurez besoin de récupérer une clé d'API et de l'insérer dans le code afin que les exemples fonctionnent.</p> +Nous n'allons pas détailler plus encore cet exemple ici, vous pouvez [consulter le code source](https://github.com/mdn/learning-area/tree/master/javascript/apis/third-party-apis/youtube) qui contient des commentaires expliquant son fonctionnement. Là encore, pour utiliser vous-même l'exemple, vous aurez besoin de récupérer une clé d'API et de l'insérer dans le code afin que les exemples fonctionnent. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Dans cet article, nous avons vu une introduction à l'utilisation des API tierces afin d'ajouter des fonctionnalités à nos sites web.</p> +Dans cet article, nous avons vu une introduction à l'utilisation des API tierces afin d'ajouter des fonctionnalités à nos sites web. -<p>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs")}} -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Une introduction aux API Web</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler les documents</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">Les API tierces</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des graphiques</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">Les API pour l'audio et la vidéo</a></li> - <li><a href="/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul> +- [Une introduction aux API Web](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler les documents](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data) +- [Les API tierces](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des graphiques](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [Les API pour l'audio et la vidéo](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/docs/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/client-side_web_apis/video_and_audio_apis/index.md b/files/fr/learn/javascript/client-side_web_apis/video_and_audio_apis/index.md index a091835f18..c29906bb7f 100644 --- a/files/fr/learn/javascript/client-side_web_apis/video_and_audio_apis/index.md +++ b/files/fr/learn/javascript/client-side_web_apis/video_and_audio_apis/index.md @@ -14,101 +14,114 @@ tags: translation_of: Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs original_slug: Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Learn/JavaScript/Client-side_web_APIs")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Learn/JavaScript/Client-side_web_APIs")}}</div> - -<p>HTML5 fournit des éléments pour intégrer du multimédia dans les documents — {{htmlelement("video")}} et {{htmlelement("audio")}} — et qui viennent avec leurs propres APIs pour contrôler la lecture, se déplacer dans le flux, etc<em>. </em>Cet article montre comment réaliser les tâches les plus communes, comme créer des contrôles de lectures personnalisés.</p> +HTML5 fournit des éléments pour intégrer du multimédia dans les documents — {{htmlelement("video")}} et {{htmlelement("audio")}} — et qui viennent avec leurs propres APIs pour contrôler la lecture, se déplacer dans le flux, etc*.* Cet article montre comment réaliser les tâches les plus communes, comme créer des contrôles de lectures personnalisés. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis:</th> - <td>Les bases du JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">premiers pas en JavaScript</a>, <a href="/fr/Apprendre/JavaScript/Building_blocks">les briques Javascript</a>, <a href="/fr/docs/Learn/JavaScript/Objects">Introduction aux objets</a>), <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux APIs web</a></td> - </tr> - <tr> - <th scope="row">Objectif:</th> - <td>Apprendre à utiliser les APIs du navigateur pour contrôler la lecture de audio et vidéo.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td> + Les bases du JavaScript (voir <a + href="/fr/docs/Learn/JavaScript/First_steps" + >premiers pas en JavaScript</a + >, + <a href="/fr/Apprendre/JavaScript/Building_blocks" + >les briques Javascript</a + >, + <a href="/fr/docs/Learn/JavaScript/Objects">Introduction aux objets</a + >), <a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction" + >Introduction aux APIs web</a + > + </td> + </tr> + <tr> + <th scope="row">Objectif:</th> + <td> + Apprendre à utiliser les APIs du navigateur pour contrôler la lecture de + audio et vidéo. + </td> + </tr> + </tbody> </table> -<h2 id="Les_balises_HTML5_video_et_audio">Les balises HTML5 video et audio</h2> +## Les balises HTML5 video et audio + +Les balises {{htmlelement("video")}} et {{htmlelement("audio")}} permettent d'intégrer des vidéos et de l'audio dans des pages web. Comme nous l'avons montré dans [Contenu audio et vidéo](/fr/Apprendre/HTML/Multimedia_and_embedding/Contenu_audio_et_video), une implémentation habituelle ressemble à ça : -<p>Les balises {{htmlelement("video")}} et {{htmlelement("audio")}} permettent d'intégrer des vidéos et de l'audio dans des pages web. Comme nous l'avons montré dans <a href="/fr/Apprendre/HTML/Multimedia_and_embedding/Contenu_audio_et_video">Contenu audio et vidéo</a>, une implémentation habituelle ressemble à ça :</p> +```html +<video controls> + <source src="rabbit320.mp4" type="video/mp4"> + <source src="rabbit320.webm" type="video/webm"> + <p>Votre navigateur ne supporte pas la vidéo HTML5. Voici à la place <a href="rabbit320.mp4">un lien vers la vidéo</a>.</p> +</video> +``` -<pre class="brush: html"><video controls> - <source src="rabbit320.mp4" type="video/mp4"> - <source src="rabbit320.webm" type="video/webm"> - <p>Votre navigateur ne supporte pas la vidéo HTML5. Voici à la place <a href="rabbit320.mp4">un lien vers la vidéo</a>.</p> -</video></pre> +Cela crée un lecteur vidéo à l'intérieur du navigateur: -<p>Cela crée un lecteur vidéo à l'intérieur du navigateur:</p> +{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html", '100%', 380)}} -<p>{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html", '100%', 380)}}</p> +Vous pouvez consulter toutes fonctionnalités HTML audio et vidéo dans l'article mentionné précédemment. Pour notre utilisation ici, l'attribut le plus intéressant est {{htmlattrxref("controls", "video")}}. Il permet d'activer l'ensemble des contrôles de lecture par défaut; si vous ne le spécifiez pas, vous aucun contrôle ne sera affiché: -<p>Vous pouvez consulter toutes fonctionnalités HTML audio et vidéo dans l'article mentionné précédemment. Pour notre utilisation ici, l'attribut le plus intéressant est {{htmlattrxref("controls", "video")}}. Il permet d'activer l'ensemble des contrôles de lecture par défaut; si vous ne le spécifiez pas, vous aucun contrôle ne sera affiché:</p> +{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats-no-controls.html", '100%', 380)}} -<p>{{EmbedGHLiveSample("learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats-no-controls.html", '100%', 380)}}</p> +Ce n'est pas immédiatement utile pour la lecture de vidéos, mais ça a des avantages. Les contrôles natifs des navigateurs différent complètement d'un navigateur à l'autre — ce qui est embêtant pour un support global des différents navigateurs. Un autre problème est que le contrôles natifs sont généralement assez peu accessibles au clavier. -<p>Ce n'est pas immédiatement utile pour la lecture de vidéos, mais ça a des avantages. Les contrôles natifs des navigateurs différent complètement d'un navigateur à l'autre — ce qui est embêtant pour un support global des différents navigateurs. Un autre problème est que le contrôles natifs sont généralement assez peu accessibles au clavier.</p> +Vous pouvez régler ces deux problèmes en cachant les contrôles natifs (en supprimant l'attribut `controls`) et en les remplaçant par les votres en HTML, CSS et JavaScript. Dans la prochaine section, nous verrons les outils de base à notre disposition pour faire ça. -<p>Vous pouvez régler ces deux problèmes en cachant les contrôles natifs (en supprimant l'attribut <code>controls</code>) et en les remplaçant par les votres en HTML, CSS et JavaScript. Dans la prochaine section, nous verrons les outils de base à notre disposition pour faire ça.</p> +## L'API HTMLMediaElement -<h2 id="L'API_HTMLMediaElement">L'API HTMLMediaElement</h2> +L'API {{domxref("HTMLMediaElement")}}, spécifiée dans HTML5, fournit des fonctionnalités qui permettent de controller des lecteurs audio et vidéo avec JavaScript — avec par exemple {{domxref("HTMLMediaElement.play()")}} ou encore {{domxref("HTMLMediaElement.pause()")}}. Cette interface est disponible à la fois pour les balises {{htmlelement("audio")}} et {{htmlelement("video")}}, les fonctionnalités utiles pour les deux étant quasiment identiques. Voyons un exemple pour découvrir ces fonctionnalités. -<p>L'API {{domxref("HTMLMediaElement")}}, spécifiée dans HTML5, fournit des fonctionnalités qui permettent de controller des lecteurs audio et vidéo avec JavaScript — avec par exemple {{domxref("HTMLMediaElement.play()")}} ou encore {{domxref("HTMLMediaElement.pause()")}}. Cette interface est disponible à la fois pour les balises {{htmlelement("audio")}} et {{htmlelement("video")}}, les fonctionnalités utiles pour les deux étant quasiment identiques. Voyons un exemple pour découvrir ces fonctionnalités.</p> +Notre exemple final ressemblera (et fonctionnera) comme ceci: -<p>Notre exemple final ressemblera (et fonctionnera) comme ceci:</p> +{{EmbedGHLiveSample("learning-area/javascript/apis/video-audio/finished/", '100%', 360)}} -<p>{{EmbedGHLiveSample("learning-area/javascript/apis/video-audio/finished/", '100%', 360)}}</p> +### Débuter -<h3 id="Débuter">Débuter</h3> +Pour commencer avec cet exemple, [télechargez notre media-player-start.zip](https://github.com/mdn/learning-area/raw/master/javascript/apis/video-audio/start/media-player-start.zip) et décompressez-le dans un nouveau dossier sur votre disque dur. Si vous avez téléchargé notre dépôt d'exemples, vous le trouverez dans `javascript/apis/video-audio/start/`. -<p>Pour commencer avec cet exemple, <a href="https://github.com/mdn/learning-area/raw/master/javascript/apis/video-audio/start/media-player-start.zip">télechargez notre media-player-start.zip</a> et décompressez-le dans un nouveau dossier sur votre disque dur. Si vous avez téléchargé notre dépôt d'exemples, vous le trouverez dans <code>javascript/apis/video-audio/start/</code>.</p> +Si vous ouvrez la page HTML, vous devriez voir un lecteur HTML5 utilisant les contrôles natifs. -<p>Si vous ouvrez la page HTML, vous devriez voir un lecteur HTML5 utilisant les contrôles natifs.</p> +#### Exploration du HTML -<h4 id="Exploration_du_HTML">Exploration du HTML</h4> +Ouvrez le fichier HTML d'index. Vous allez voir que le HTML contient majoritairement du code pour le lecteur et ses contrôles: -<p>Ouvrez le fichier HTML d'index. Vous allez voir que le HTML contient majoritairement du code pour le lecteur et ses contrôles:</p> +```html +<div class="player"> + <video controls> + <source src="video/sintel-short.mp4" type="video/mp4"> + <source src="video/sintel-short.mp4" type="video/webm"> + <!-- fallback contenu ici --> + </video> + <div class="controls"> + <button class="play" data-icon="P" aria-label="bascule lecture pause"></button> + <button class="stop" data-icon="S" aria-label="stop"></button> + <div class="timer"> + <div></div> + <span aria-label="timer">00:00</span> + </div> + <button class="rwd" data-icon="B" aria-label="retour arrière"></button> + <button class="fwd" data-icon="F" aria-label="avance rapide"></button> + </div> +</div> +``` -<pre class="brush: html"><div class="player"> - <video controls> - <source src="video/sintel-short.mp4" type="video/mp4"> - <source src="video/sintel-short.mp4" type="video/webm"> - <!-- fallback contenu ici --> - </video> - <div class="controls"> - <button class="play" data-icon="P" aria-label="bascule lecture pause"></button> - <button class="stop" data-icon="S" aria-label="stop"></button> - <div class="timer"> - <div></div> - <span aria-label="timer">00:00</span> - </div> - <button class="rwd" data-icon="B" aria-label="retour arrière"></button> - <button class="fwd" data-icon="F" aria-label="avance rapide"></button> - </div> -</div> -</pre> +- Le lecteur complet est englobé dans une balise {{htmlelement("div")}} pour pouvoir appliquer du style sur le bloc complet si nécessaire. +- La balise {{htmlelement("video")}} contient deux éléments {{htmlelement("source")}} pour permettre la lecture du média selon les capacités de chaque navigateur. +- La partie _controls_ du HTML est la plus intéressante: -<ul> - <li>Le lecteur complet est englobé dans une balise {{htmlelement("div")}} pour pouvoir appliquer du style sur le bloc complet si nécessaire.</li> - <li>La balise {{htmlelement("video")}} contient deux éléments {{htmlelement("source")}} pour permettre la lecture du média selon les capacités de chaque navigateur.</li> - <li>La partie <em>controls</em> du HTML est la plus intéressante: - <ul> - <li>Il contient 4 {{htmlelement("button")}} : lecture/mise en pause, stop, retour arrière et avance rapide.</li> - <li>Chaque <code><button></code> a un nom de classe, un attribut <code>data-icon</code> (pour définir l'icône affichée), et un attribut <code>aria-label</code> (qui fournit une description de chaque bouton pour le rendre accessible). Le contenu d'un attribut <code>aria-label</code> est lu par les lecteurs d'écran quand l'élément sur lequel il se situe prend le focus.</li> - <li>Il y a également un élément {{htmlelement("div")}}, qui affiche le temps écoulé quand la vidéo est en cours de lecture. Pour s'amuser, nous avons mis deux mécanismes en place — un {{htmlelement("span")}} qui affiche le temps écoulé en minutes/secondes, et un autre <code><div></code> pour afficher une barre de progrès. Pour vous faire une idée du produit final, vous pouvez jeter un d'oeil à <a href="https://mdn.github.io/learning-area/javascript/apis/video-audio/finished/">la version finie</a>.</li> - </ul> - </li> -</ul> + - Il contient 4 {{htmlelement("button")}} : lecture/mise en pause, stop, retour arrière et avance rapide. + - Chaque `<button>` a un nom de classe, un attribut `data-icon` (pour définir l'icône affichée), et un attribut `aria-label` (qui fournit une description de chaque bouton pour le rendre accessible). Le contenu d'un attribut `aria-label` est lu par les lecteurs d'écran quand l'élément sur lequel il se situe prend le focus. + - Il y a également un élément {{htmlelement("div")}}, qui affiche le temps écoulé quand la vidéo est en cours de lecture. Pour s'amuser, nous avons mis deux mécanismes en place — un {{htmlelement("span")}} qui affiche le temps écoulé en minutes/secondes, et un autre `<div>` pour afficher une barre de progrès. Pour vous faire une idée du produit final, vous pouvez jeter un d'oeil à [la version finie](https://mdn.github.io/learning-area/javascript/apis/video-audio/finished/). -<h4 id="Exploration_du_CSS">Exploration du CSS</h4> +#### Exploration du CSS -<p>Maintenant, ouvrez le fichier CSS et jetez-y un coup d'oeil. Le CSS pour cet exemple n'est pas très compliqué, mais nous allons voir les éléments les plus intéressants ici. Tout d'abord, le style de <code>.controls</code>:</p> +Maintenant, ouvrez le fichier CSS et jetez-y un coup d'oeil. Le CSS pour cet exemple n'est pas très compliqué, mais nous allons voir les éléments les plus intéressants ici. Tout d'abord, le style de `.controls`: -<pre class="brush: css">.controls { +```css +.controls { visibility: hidden; opacity: 0.5; width: 400px; @@ -126,17 +139,16 @@ original_slug: Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs .player:hover .controls, player:focus .controls { opacity: 1; } -</pre> +``` -<ul> - <li>Nous commençons par définir la propriété {{cssxref("visibility")}} à <code>hidden</code>. Plus tard dans notre JavaScript, nous le rendrons <code>visible</code>, et supprimerons l'attribut <code>controls</code> de l'élément <code><video></code>. Ainsi, si pour une raison quelconque le JavaScript ne se charge pas, les utilisateurs peuvent toujours utiliser la vidéo avec les contrôles natifs.</li> - <li>Nous donnons aux propriétés une {{cssxref("opacity")}} de 0.5 par défaut, pour qu'ils ne soient pas génants lorsqu'on veut regarder la vidéo. Ce n'est qu'en passant la souris sur le lecteur que les contrôles sont affichés en pleine opacité.</li> - <li>Ne plaçons les boutons à l'intérieur du div en utilisant Flexbox ({{cssxref("display")}}: flex), c'est plus simple comme ça.</li> -</ul> +- Nous commençons par définir la propriété {{cssxref("visibility")}} à `hidden`. Plus tard dans notre JavaScript, nous le rendrons `visible`, et supprimerons l'attribut `controls` de l'élément `<video>`. Ainsi, si pour une raison quelconque le JavaScript ne se charge pas, les utilisateurs peuvent toujours utiliser la vidéo avec les contrôles natifs. +- Nous donnons aux propriétés une {{cssxref("opacity")}} de 0.5 par défaut, pour qu'ils ne soient pas génants lorsqu'on veut regarder la vidéo. Ce n'est qu'en passant la souris sur le lecteur que les contrôles sont affichés en pleine opacité. +- Ne plaçons les boutons à l'intérieur du div en utilisant Flexbox ({{cssxref("display")}}: flex), c'est plus simple comme ça. -<p>Ensuite, voyons les icônes des boutons:</p> +Ensuite, voyons les icônes des boutons: -<pre class="brush: css">@font-face { +```css +@font-face { font-family: 'HeydingsControlsRegular'; src: url('fonts/heydings_controls-webfont.eot'); src: url('fonts/heydings_controls-webfont.eot?#iefix') format('embedded-opentype'), @@ -153,23 +165,23 @@ button:before { content: attr(data-icon); color: #aaa; text-shadow: 1px 1px 0px black; -}</pre> +} +``` -<p>Tout d'abord, en haut du CSS, nous utilisons un bloc {{cssxref("@font-face")}} pour importer une police web personnalisée. Il s'agit d'une police d'icônes — tous les caractères de l'alphabet correspondent à des icônes que vous pouvez utiliser dans votre application.</p> +Tout d'abord, en haut du CSS, nous utilisons un bloc {{cssxref("@font-face")}} pour importer une police web personnalisée. Il s'agit d'une police d'icônes — tous les caractères de l'alphabet correspondent à des icônes que vous pouvez utiliser dans votre application. -<p>Ensuite, nous générons du contenu pour afficher une icône sur chaque bouton:</p> +Ensuite, nous générons du contenu pour afficher une icône sur chaque bouton: -<ul> - <li>Nous utilisons le sélecteur {{cssxref("::before")}} pour afficher le contenu au début de chaque élément {{htmlelement("button")}}.</li> - <li>Nous utilisons la propriété {{cssxref("content")}} pour que le contenu à afficher soit égal au contenu de l'attribut <code><a href="/fr/Apprendre/HTML/Comment/Utiliser_attributs_donnes">data-icon</a></code>. Dans le cas du bouton play par exemple, <code>data-icon</code> contient un "P" majuscule.</li> - <li>Nous apliquons la police web personnalisée au bouton en utilisant {{cssxref("font-family")}}. Dans cette police, "P" est une icône "play", donc le bouton play a une icône "play" affichée dedans.</li> -</ul> +- Nous utilisons le sélecteur {{cssxref("::before")}} pour afficher le contenu au début de chaque élément {{htmlelement("button")}}. +- Nous utilisons la propriété {{cssxref("content")}} pour que le contenu à afficher soit égal au contenu de l'attribut [`data-icon`](/fr/Apprendre/HTML/Comment/Utiliser_attributs_donnes). Dans le cas du bouton play par exemple, `data-icon` contient un "P" majuscule. +- Nous apliquons la police web personnalisée au bouton en utilisant {{cssxref("font-family")}}. Dans cette police, "P" est une icône "play", donc le bouton play a une icône "play" affichée dedans. -<p>Les polices d'icônes sont très cool pour de nombreuses raisons: réduire les requêtes HTTP (puisque vous n'avez pas besoin de télécharger des icônes sous forme de fichiers image), bonne scalabilité, et le fait que vous pouvez utiliser les propriétés de texte pour les formatter — comme {{cssxref("color")}} et {{cssxref("text-shadow")}}.</p> +Les polices d'icônes sont très cool pour de nombreuses raisons: réduire les requêtes HTTP (puisque vous n'avez pas besoin de télécharger des icônes sous forme de fichiers image), bonne scalabilité, et le fait que vous pouvez utiliser les propriétés de texte pour les formatter — comme {{cssxref("color")}} et {{cssxref("text-shadow")}}. -<p>Dernier point mais non des moindres, le CSS du décompte:</p> +Dernier point mais non des moindres, le CSS du décompte: -<pre class="brush: css">.timer { +```css +.timer { line-height: 38px; font-size: 10px; font-family: monospace; @@ -193,231 +205,215 @@ button:before { position: absolute; z-index: 3; left: 19px; -}</pre> - -<ul> - <li>Nous donnons au <code><div></code> <code>.timer</code> la propriété <code>flex: 5</code>, pour qu'il occupe la plus grande partie de la barre de contrôle en largeur. Nous ajoutons également {{cssxref("position")}}<code>: relative</code>, pour que les éléments à l'intérieur puissent être positionnés relativement à ses dimensions et non à celles de l'élément {{htmlelement("body")}}.</li> - <li>Le <code><div></code> interne est positionné en absolu pour être situé au-dessus du <code><div></code> externe. On lui donne également une largeur initiale de 0, de sorte qu'on ne le voie pas du tout. Au fur et à mesure de la lecture de la vidéo, la largeur sera augmentée via JavaScript.</li> - <li>Le <code><span></code> est également positionné en absolu pour être situé sur le côté gauche de la barre de progrès.</li> - <li>Nous donnons au <code><div></code> et au <code><span></code> le {{cssxref("z-index")}} approprié pour que les données soient visibles — qu'un élément n'en cache pas un autre.</li> -</ul> - -<h3 id="Implémenter_le_JavaScript">Implémenter le JavaScript</h3> - -<p>Nous avons déjà une interface HTML et CSS assez complète; nous avons maintenant besoin de gérer les boutons pour que les contrôles fonctionnent.</p> - -<ol> - <li> - <p>Créez un nouveau fichier JavaScript dans le même répertoire que votre fichier index.html. Nous l'appelerons <code>custom-player.js</code>.</p> - </li> - <li> - <p>En haut de ce fichier, insérez le code suivant:</p> - - <pre class="brush: js">var media = document.querySelector('video'); -var controls = document.querySelector('.controls'); - -var play = document.querySelector('.play'); -var stop = document.querySelector('.stop'); -var rwd = document.querySelector('.rwd'); -var fwd = document.querySelector('.fwd'); - -var timerWrapper = document.querySelector('.timer'); -var timer = document.querySelector('.timer span'); -var timerBar = document.querySelector('.timer div'); -</pre> - - <p>Ici, nous créons des variables pour stocker les références de tous les objets que nous voulons manipuler. Nous avons trois groupes:</p> - - <ul> - <li>L'élément <code><video></code>, et la barre de contrôle.</li> - <li>Les boutons play/pause, stop, retour arrière, et avance rapide.</li> - <li>Le <code><div></code> externe, le <code><span></code> qui décompte le temps écoulé, et le <code><div></code> interne qui affiche le progrès de la vidéo.</li> - </ul> - </li> - <li> - <p>Ensuite, insérez ce qui suit en bas de votre code:</p> - - <pre class="brush: js">media.removeAttribute('controls'); -controls.style.visibility = 'visible';</pre> - - <p>Ces deux lignes suppriment les contrôles par défaut du navigateur sur la vidéo, et rendent nos contrôles personnalisés visibles.</p> - </li> -</ol> - -<h4 id="Lecture_et_pause_de_la_vidéo">Lecture et pause de la vidéo</h4> - -<p>Imlémentons le contrôle le plus important — le bouton play/pause.</p> - -<ol> - <li> - <p>Tout d'abord, ajoutez ce qui suit au bas de votre code, pour que la fonction <code>playPauseMedia()</code> soit invoquée quand le bouton play est cliqué:</p> - - <pre class="brush: js">play.addEventListener('click', playPauseMedia); -</pre> - </li> - <li> - <p>Maintenant, définissons <code>playPauseMedia()</code> — ajoutez ce qui suit, toujours au bas de votre code:</p> - - <pre class="brush: js">function playPauseMedia() { - if(media.paused) { - play.setAttribute('data-icon','u'); - media.play(); - } else { - play.setAttribute('data-icon','P'); - media.pause(); - } -}</pre> +} +``` - <p>Ici, nous utilisons une instruction <code><a href="/fr/docs/Web/JavaScript/Reference/Instructions/if...else">if</a></code> pour vérifier si la vidéo est en pause. La propriété {{domxref("HTMLMediaElement.paused")}} retourne vrai si le média est en pause — c'est le cas quand la vidéo n'est pas en cours de lecture, y compris quand la vidéo est au début après son chargement. Si elle est en pause, nous définissons la valeur de l'attribut <code>data-icon</code> à "u", qui est une icône "en pause", et invoquons la méthode {{domxref("HTMLMediaElement.play()")}} pour jouer le média.</p> +- Nous donnons au `<div>` `.timer` la propriété `flex: 5`, pour qu'il occupe la plus grande partie de la barre de contrôle en largeur. Nous ajoutons également {{cssxref("position")}}`: relative`, pour que les éléments à l'intérieur puissent être positionnés relativement à ses dimensions et non à celles de l'élément {{htmlelement("body")}}. +- Le `<div>` interne est positionné en absolu pour être situé au-dessus du `<div>` externe. On lui donne également une largeur initiale de 0, de sorte qu'on ne le voie pas du tout. Au fur et à mesure de la lecture de la vidéo, la largeur sera augmentée via JavaScript. +- Le `<span>` est également positionné en absolu pour être situé sur le côté gauche de la barre de progrès. +- Nous donnons au `<div>` et au `<span>` le {{cssxref("z-index")}} approprié pour que les données soient visibles — qu'un élément n'en cache pas un autre. - <p>Au second clic, le bouton sera de nouveau alterné — l'icône "play" sera affiché, et la vidéo sera mise en pause avec {{domxref("HTMLMediaElement.paused()")}}.</p> - </li> -</ol> +### Implémenter le JavaScript -<h4 id="Stopper_la_vidéo">Stopper la vidéo</h4> +Nous avons déjà une interface HTML et CSS assez complète; nous avons maintenant besoin de gérer les boutons pour que les contrôles fonctionnent. -<ol> - <li> - <p>Ajoutons la possibilité d'arrêter la vidéo. Ajoutez les lignes <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> suivantes au-dessous de vos ajouts précédents:</p> +1. Créez un nouveau fichier JavaScript dans le même répertoire que votre fichier index.html. Nous l'appelerons `custom-player.js`. +2. En haut de ce fichier, insérez le code suivant: - <pre class="brush: js">stop.addEventListener('click', stopMedia); -media.addEventListener('ended', stopMedia); -</pre> + ```js + var media = document.querySelector('video'); + var controls = document.querySelector('.controls'); - <p>L'événement {{event("click")}} est explicite — nous voulons stopper la vidéo en appelant la fonction <code>stopMedia()</code> quand le bouton stop est cliqué. Cependant, nous voulons également stopper la vidéo quand elle a fini de jouer — signalé par l'événement {{event("ended")}}, nous pouvons donc mettre en place un gestionnaire d'événement pour exécuter la fonction quand cet événément se produit.</p> - </li> - <li> - <p>Ensuite, définissons <code>stopMedia()</code> — ajoutez ce qui suit après la fonction <code>playPauseMedia()</code>:</p> + var play = document.querySelector('.play'); + var stop = document.querySelector('.stop'); + var rwd = document.querySelector('.rwd'); + var fwd = document.querySelector('.fwd'); - <pre class="brush: js">function stopMedia() { - media.pause(); - media.currentTime = 0; - play.setAttribute('data-icon','P'); -} -</pre> + var timerWrapper = document.querySelector('.timer'); + var timer = document.querySelector('.timer span'); + var timerBar = document.querySelector('.timer div'); + ``` - <p>Il n'y a pas de méthode <code>stop()</code> dans l'API HTMLMediaElement — l'équivalent du stop est de mettre <code>pause()</code> sur la vidéo, et de définir la propriété {{domxref("HTMLMediaElement.currentTime","currentTime")}} à 0. Définir une valeur à <code>currentTime</code> (en secondes) change immédiatement la position du temps du média.</p> + Ici, nous créons des variables pour stocker les références de tous les objets que nous voulons manipuler. Nous avons trois groupes: - <p>Tout ce qui nous reste à faire après ça est d'afficher l'icône "play". Que la vidéo ait été en train de jouer ou en pause, quand le bouton stop est pressé, vous voulez qu'elle doit prête à être lue.</p> - </li> -</ol> + - L'élément `<video>`, et la barre de contrôle. + - Les boutons play/pause, stop, retour arrière, et avance rapide. + - Le `<div>` externe, le `<span>` qui décompte le temps écoulé, et le `<div>` interne qui affiche le progrès de la vidéo. -<h4 id="Retour_arrière_et_avance_rapide">Retour arrière et avance rapide</h4> +3. Ensuite, insérez ce qui suit en bas de votre code: -<p>Il y a différentes manières d'implémenter le retour arrière et l'avance rapide; ici, nous vous montrons une manière relativement complexe de le faire, qui n'a pas de comportement inattendu quand différents boutons sont pressés dans un ordre aléatoire.</p> + ```js + media.removeAttribute('controls'); + controls.style.visibility = 'visible'; + ``` -<ol> - <li> - <p>Tout d'abord, ajoutez les lignes <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> suivantes à la suite des précédentes:</p> + Ces deux lignes suppriment les contrôles par défaut du navigateur sur la vidéo, et rendent nos contrôles personnalisés visibles. - <pre class="brush: js">rwd.addEventListener('click', mediaBackward); -fwd.addEventListener('click', mediaForward); -</pre> - </li> - <li> - <p>Maintenant, occupons-nous des fonctions des gestionnaires d'événément — ajoutez le code suivant à la suite des fonctions précédentes pour définir <code>mediaBackward()</code> et <code>mediaForward()</code>:</p> +#### Lecture et pause de la vidéo - <pre class="brush: js">var intervalFwd; -var intervalRwd; +Imlémentons le contrôle le plus important — le bouton play/pause. -function mediaBackward() { - clearInterval(intervalFwd); - fwd.classList.remove('active'); +1. Tout d'abord, ajoutez ce qui suit au bas de votre code, pour que la fonction `playPauseMedia()` soit invoquée quand le bouton play est cliqué: - if(rwd.classList.contains('active')) { - rwd.classList.remove('active'); - clearInterval(intervalRwd); - media.play(); - } else { - rwd.classList.add('active'); - media.pause(); - intervalRwd = setInterval(windBackward, 200); - } -} + ```js + play.addEventListener('click', playPauseMedia); + ``` -function mediaForward() { - clearInterval(intervalRwd); - rwd.classList.remove('active'); +2. Maintenant, définissons `playPauseMedia()` — ajoutez ce qui suit, toujours au bas de votre code: - if(fwd.classList.contains('active')) { - fwd.classList.remove('active'); - clearInterval(intervalFwd); - media.play(); - } else { - fwd.classList.add('active'); - media.pause(); - intervalFwd = setInterval(windForward, 200); - } -} -</pre> - - <p>Vous remarquerez que nous commençons par initialiser deux variables — <code>intervalFwd</code> et <code>intervalRwd</code> — vous verrez à quoi elles servent plus tard.</p> - - <p>Voyons pas à pas <code>mediaBackward()</code> (<code>mediaForward()</code> fait la même chose, mais dans l'autre sens):</p> - - <ol> - <li>Nous effaçons les classes et intervales qui sont définits sur la fonctionnalité d'avance rapide — de cette manière, si on presse le bouton <code>rwd</code> après avoir pressé le bouton <code>fwd</code>, on annule l'avance rapide et la remplaçons avec le retour arrière. Si on essayait de faire les deux à la fois, le lecteur échouerait.</li> - <li>Nous utilisons une instruction <code>if</code> pour vérifier si la classe <code>active</code> a été définie sur le bouton <code>rwd</code>, ce qui indique qu'il a déjà été pressé. La propriété {{domxref("classList")}} est une propriété plutôt pratique qui existe sur chaque élément — elle contient une liste de toutes les classes définies sur l'élément, ainsi que des méthodes pour en ajouter/supprimer, etc. Nous utilisons la méthode <code>classList.contains()</code> pour vérifier si la liste contient la classe <code>active</code>. Cela retourne un booléen <code>true</code>/<code>false</code> en résultat.</li> - <li>Si la classe <code>active</code> a été définie sur le bouton <code>rwd</code>, nous la supprimons avec <code>classList.remove()</code>, effaçons l'intervale qui a été définit sur le bouton quand il a été pressé (voir ci-dessous pour plus d'explication), et utilisons {{domxref("HTMLMediaElement.play()")}} pour annuler le retour arrière et démarrer la vidéo normalement.</li> - <li> - <p>Sinon, nous ajoutons la classe <code>active</code> sur le bouton <code>rwd</code> avec <code>classList.add()</code>, mettons la vidéo en pause en utilisant {{domxref("HTMLMediaElement.pause()")}}, puis définissons la variable <code>intervalRwd</code> en appelant {{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}. Quand elle invoquée, la fonction <code>setInterval()</code> créé un intervale actif, ce qui signifie qu'une fonction donnée en paramètre est exécutée toutes les x millisecondes — x est la valeur du 2ème paramètre. Ainsi, nous exécutons ici la fonction <code>windBackward()</code> toutes les 200 millisecondes — nous utiliserons cette fonction pour retourner la fonction en arrière de manière constante. Pour stopper un intervale actif, vous devez appeler {{domxref("WindowOrWorkerGlobalScope.clearInterval", "clearInterval()")}} en lui donnant l'intervale à arrêter en paramètre, dans notre cas il est stocké dans la variable <code>intervalRwd</code> (voir l'appel à <code>clearInterval()</code> effectué plus tôt dans la fonction).</p> - </li> - </ol> - </li> - <li> - <p>Pour en finir avec cette section, nous devons définir les fonctions <code>windBackward()</code> et <code>windForward()</code> invoquées dans les appels <code>setInterval()</code>. Ajoutez ce qui suit après les deux fonctions précédentes:</p> - - <pre class="brush: js">function windBackward() { - if(media.currentTime <= 3) { - rwd.classList.remove('active'); - clearInterval(intervalRwd); - stopMedia(); - } else { - media.currentTime -= 3; - } -} + ```js + function playPauseMedia() { + if(media.paused) { + play.setAttribute('data-icon','u'); + media.play(); + } else { + play.setAttribute('data-icon','P'); + media.pause(); + } + } + ``` -function windForward() { - if(media.currentTime >= media.duration - 3) { - fwd.classList.remove('active'); - clearInterval(intervalFwd); - stopMedia(); - } else { - media.currentTime += 3; - } -}</pre> - Encore une fois, nous allons voir pas à pas la première fonction, puisque les deux fonctions font la même chose mais dans le sens inverse. Dans <code>windBackward()</code>, nous faisons comme suit — gardez à l'esprit que la fonction est exécutée toutes les 200 millisecondes. + Ici, nous utilisons une instruction [`if`](/fr/docs/Web/JavaScript/Reference/Instructions/if...else) pour vérifier si la vidéo est en pause. La propriété {{domxref("HTMLMediaElement.paused")}} retourne vrai si le média est en pause — c'est le cas quand la vidéo n'est pas en cours de lecture, y compris quand la vidéo est au début après son chargement. Si elle est en pause, nous définissons la valeur de l'attribut `data-icon` à "u", qui est une icône "en pause", et invoquons la méthode {{domxref("HTMLMediaElement.play()")}} pour jouer le média. + + Au second clic, le bouton sera de nouveau alterné — l'icône "play" sera affiché, et la vidéo sera mise en pause avec {{domxref("HTMLMediaElement.paused()")}}. + +#### Stopper la vidéo + +1. Ajoutons la possibilité d'arrêter la vidéo. Ajoutez les lignes [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener) suivantes au-dessous de vos ajouts précédents: + + ```js + stop.addEventListener('click', stopMedia); + media.addEventListener('ended', stopMedia); + ``` + + L'événement {{event("click")}} est explicite — nous voulons stopper la vidéo en appelant la fonction `stopMedia()` quand le bouton stop est cliqué. Cependant, nous voulons également stopper la vidéo quand elle a fini de jouer — signalé par l'événement {{event("ended")}}, nous pouvons donc mettre en place un gestionnaire d'événement pour exécuter la fonction quand cet événément se produit. + +2. Ensuite, définissons `stopMedia()` — ajoutez ce qui suit après la fonction `playPauseMedia()`: + + ```js + function stopMedia() { + media.pause(); + media.currentTime = 0; + play.setAttribute('data-icon','P'); + } + ``` + + Il n'y a pas de méthode `stop()` dans l'API HTMLMediaElement — l'équivalent du stop est de mettre `pause()` sur la vidéo, et de définir la propriété {{domxref("HTMLMediaElement.currentTime","currentTime")}} à 0. Définir une valeur à `currentTime` (en secondes) change immédiatement la position du temps du média. - <ol> - <li>Nous commençons avec une instruction <code>if</code> qui vérifie si le temps en cours est inférieur à 3 secondes, c'est à dire si le retour arrière nous ramènerait avant le début de la vidéo. Cela provoquerait un comportement étrange. Ainsi, si c'est le cas, nous arrêtons la vidéo en appelant <code>stopMedia()</code>, supprimons la classe <code>active</code> du bouton, et stoppons l'intervale <code>intervalRwd</code> pour stopper le retour arrière. Si nous n'avions pas ajouté cette dernière étape, la vidéo continuerait de se remboniner éternellement.</li> - <li>Si le temps en cours n'est pas inférieur à 3 secondes, nous retournons en arrière de 3 secondes en exécutant <code>media.currentTime -= 3</code>. Dans les faits, on rembobine donc la vidéo de 3 secondes toutes les 200 millisecondes.</li> - </ol> - </li> -</ol> + Tout ce qui nous reste à faire après ça est d'afficher l'icône "play". Que la vidéo ait été en train de jouer ou en pause, quand le bouton stop est pressé, vous voulez qu'elle doit prête à être lue. -<h4 id="Mettre_à_jour_le_temps_écoulé">Mettre à jour le temps écoulé</h4> +#### Retour arrière et avance rapide -<p>La dernière chose à implémenter pour notre lecteur multimédia est l'affichage du temps écoulé. Pour ce faire, nous allons exécuter une fonction pour mettre à jour le temps affiché à chaque fois que l'événement {{event("timeupdate")}} est déclenché sur l'élément <code><video></code>. La fréquence à laquelle cet événement se déclenche dépend de votre navigateur, de la puissance de votre CPU, etc (<a href="http://stackoverflow.com/questions/9678177/how-often-does-the-timeupdate-event-fire-for-an-html5-video">voir post stackoverflow</a>).</p> +Il y a différentes manières d'implémenter le retour arrière et l'avance rapide; ici, nous vous montrons une manière relativement complexe de le faire, qui n'a pas de comportement inattendu quand différents boutons sont pressés dans un ordre aléatoire. -<p>Ajoutez la ligne <code>addEventListener()</code> suivante à la suite des autres:</p> +1. Tout d'abord, ajoutez les lignes [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener) suivantes à la suite des précédentes: -<pre class="brush: js">media.addEventListener('timeupdate', setTime);</pre> + ```js + rwd.addEventListener('click', mediaBackward); + fwd.addEventListener('click', mediaForward); + ``` -<p>Maintenant, ajoutez la fonction <code>setTime()</code>:</p> +2. Maintenant, occupons-nous des fonctions des gestionnaires d'événément — ajoutez le code suivant à la suite des fonctions précédentes pour définir `mediaBackward()` et `mediaForward()`: -<pre class="brush: js">function setTime() { + ```js + var intervalFwd; + var intervalRwd; + + function mediaBackward() { + clearInterval(intervalFwd); + fwd.classList.remove('active'); + + if(rwd.classList.contains('active')) { + rwd.classList.remove('active'); + clearInterval(intervalRwd); + media.play(); + } else { + rwd.classList.add('active'); + media.pause(); + intervalRwd = setInterval(windBackward, 200); + } + } + + function mediaForward() { + clearInterval(intervalRwd); + rwd.classList.remove('active'); + + if(fwd.classList.contains('active')) { + fwd.classList.remove('active'); + clearInterval(intervalFwd); + media.play(); + } else { + fwd.classList.add('active'); + media.pause(); + intervalFwd = setInterval(windForward, 200); + } + } + ``` + + Vous remarquerez que nous commençons par initialiser deux variables — `intervalFwd` et `intervalRwd` — vous verrez à quoi elles servent plus tard. + + Voyons pas à pas `mediaBackward()` (`mediaForward()` fait la même chose, mais dans l'autre sens): + + 1. Nous effaçons les classes et intervales qui sont définits sur la fonctionnalité d'avance rapide — de cette manière, si on presse le bouton `rwd` après avoir pressé le bouton `fwd`, on annule l'avance rapide et la remplaçons avec le retour arrière. Si on essayait de faire les deux à la fois, le lecteur échouerait. + 2. Nous utilisons une instruction `if` pour vérifier si la classe `active` a été définie sur le bouton `rwd`, ce qui indique qu'il a déjà été pressé. La propriété {{domxref("classList")}} est une propriété plutôt pratique qui existe sur chaque élément — elle contient une liste de toutes les classes définies sur l'élément, ainsi que des méthodes pour en ajouter/supprimer, etc. Nous utilisons la méthode `classList.contains()` pour vérifier si la liste contient la classe `active`. Cela retourne un booléen `true`/`false` en résultat. + 3. Si la classe `active` a été définie sur le bouton `rwd`, nous la supprimons avec `classList.remove()`, effaçons l'intervale qui a été définit sur le bouton quand il a été pressé (voir ci-dessous pour plus d'explication), et utilisons {{domxref("HTMLMediaElement.play()")}} pour annuler le retour arrière et démarrer la vidéo normalement. + 4. Sinon, nous ajoutons la classe `active` sur le bouton `rwd` avec `classList.add()`, mettons la vidéo en pause en utilisant {{domxref("HTMLMediaElement.pause()")}}, puis définissons la variable `intervalRwd` en appelant {{domxref("WindowOrWorkerGlobalScope.setInterval", "setInterval()")}}. Quand elle invoquée, la fonction `setInterval()` créé un intervale actif, ce qui signifie qu'une fonction donnée en paramètre est exécutée toutes les x millisecondes — x est la valeur du 2ème paramètre. Ainsi, nous exécutons ici la fonction `windBackward()` toutes les 200 millisecondes — nous utiliserons cette fonction pour retourner la fonction en arrière de manière constante. Pour stopper un intervale actif, vous devez appeler {{domxref("WindowOrWorkerGlobalScope.clearInterval", "clearInterval()")}} en lui donnant l'intervale à arrêter en paramètre, dans notre cas il est stocké dans la variable `intervalRwd` (voir l'appel à `clearInterval()` effectué plus tôt dans la fonction). + +3. Pour en finir avec cette section, nous devons définir les fonctions `windBackward()` et `windForward()` invoquées dans les appels `setInterval()`. Ajoutez ce qui suit après les deux fonctions précédentes: + + ```js + function windBackward() { + if(media.currentTime <= 3) { + rwd.classList.remove('active'); + clearInterval(intervalRwd); + stopMedia(); + } else { + media.currentTime -= 3; + } + } + + function windForward() { + if(media.currentTime >= media.duration - 3) { + fwd.classList.remove('active'); + clearInterval(intervalFwd); + stopMedia(); + } else { + media.currentTime += 3; + } + } + ``` + + Encore une fois, nous allons voir pas à pas la première fonction, puisque les deux fonctions font la même chose mais dans le sens inverse. Dans `windBackward()`, nous faisons comme suit — gardez à l'esprit que la fonction est exécutée toutes les 200 millisecondes. + + 1. Nous commençons avec une instruction `if` qui vérifie si le temps en cours est inférieur à 3 secondes, c'est à dire si le retour arrière nous ramènerait avant le début de la vidéo. Cela provoquerait un comportement étrange. Ainsi, si c'est le cas, nous arrêtons la vidéo en appelant `stopMedia()`, supprimons la classe `active` du bouton, et stoppons l'intervale `intervalRwd` pour stopper le retour arrière. Si nous n'avions pas ajouté cette dernière étape, la vidéo continuerait de se remboniner éternellement. + 2. Si le temps en cours n'est pas inférieur à 3 secondes, nous retournons en arrière de 3 secondes en exécutant `media.currentTime -= 3`. Dans les faits, on rembobine donc la vidéo de 3 secondes toutes les 200 millisecondes. + +#### Mettre à jour le temps écoulé + +La dernière chose à implémenter pour notre lecteur multimédia est l'affichage du temps écoulé. Pour ce faire, nous allons exécuter une fonction pour mettre à jour le temps affiché à chaque fois que l'événement {{event("timeupdate")}} est déclenché sur l'élément `<video>`. La fréquence à laquelle cet événement se déclenche dépend de votre navigateur, de la puissance de votre CPU, etc ([voir post stackoverflow](http://stackoverflow.com/questions/9678177/how-often-does-the-timeupdate-event-fire-for-an-html5-video)). + +Ajoutez la ligne `addEventListener()` suivante à la suite des autres: + +```js +media.addEventListener('timeupdate', setTime); +``` + +Maintenant, ajoutez la fonction `setTime()`: + +```js +function setTime() { var minutes = Math.floor(media.currentTime / 60); var seconds = Math.floor(media.currentTime - minutes * 60); var minuteValue; var secondValue; - if (minutes < 10) { + if (minutes < 10) { minuteValue = '0' + minutes; } else { minuteValue = minutes; } - if (seconds < 10) { + if (seconds < 10) { secondValue = '0' + seconds; } else { secondValue = seconds; @@ -429,91 +425,74 @@ function windForward() { var barLength = timerWrapper.clientWidth * (media.currentTime/media.duration); timerBar.style.width = barLength + 'px'; } -</pre> +``` -<p>C'est une fonction assez longue, alors allons-y étape par étape:</p> +C'est une fonction assez longue, alors allons-y étape par étape: -<ol> - <li>Tout d'abord, nous récupérons le nombre de minutes et de secondes à partir de {{domxref("HTMLMediaElement.currentTime")}}.</li> - <li>Ensuite, on initialise deux variables supplémentaires — <code>minuteValue</code> et <code>secondValue</code>.</li> - <li>Les deux instructions <code>if</code> qui suivent déterminent si le nombre de minutes et secondes est inférieur à 10. Si c'est le cas, on ajoute un zéro à gauche pour afficher le numéro sur deux chiffres — comme sur une horloge digitale.</li> - <li>Le temps est au final la concaténation de <code>minuteValue</code>, un caractère deux-points, et <code>secondValue</code>.</li> - <li>Le temps qu'on vient de définir devient la valeur {{domxref("Node.textContent")}} du décompte, pour qu'il s'affiche dans l'interface utilisateur.</li> - <li>La largeur que nous devons donner <code><div></code> intérieur est calculée en récupérant la largeur du <code><div></code> externe (la propriété {{domxref("HTMLElement.clientWidth", "clientWidth")}} retourne la largeur de l'élément), et en la multipliant par {{domxref("HTMLMediaElement.currentTime")}} divisé par le total {{domxref("HTMLMediaElement.duration")}} du média.</li> - <li>Nous assignons la largeur du <code><div></code> intérieur à la valeur calculée, plus "px", il sera donc fixé à ce nombre de pixels.</li> -</ol> +1. Tout d'abord, nous récupérons le nombre de minutes et de secondes à partir de {{domxref("HTMLMediaElement.currentTime")}}. +2. Ensuite, on initialise deux variables supplémentaires — `minuteValue` et `secondValue`. +3. Les deux instructions `if` qui suivent déterminent si le nombre de minutes et secondes est inférieur à 10. Si c'est le cas, on ajoute un zéro à gauche pour afficher le numéro sur deux chiffres — comme sur une horloge digitale. +4. Le temps est au final la concaténation de `minuteValue`, un caractère deux-points, et `secondValue`. +5. Le temps qu'on vient de définir devient la valeur {{domxref("Node.textContent")}} du décompte, pour qu'il s'affiche dans l'interface utilisateur. +6. La largeur que nous devons donner `<div>` intérieur est calculée en récupérant la largeur du `<div>` externe (la propriété {{domxref("HTMLElement.clientWidth", "clientWidth")}} retourne la largeur de l'élément), et en la multipliant par {{domxref("HTMLMediaElement.currentTime")}} divisé par le total {{domxref("HTMLMediaElement.duration")}} du média. +7. Nous assignons la largeur du `<div>` intérieur à la valeur calculée, plus "px", il sera donc fixé à ce nombre de pixels. -<h4 id="Corriger_play_et_pause">Corriger play et pause</h4> +#### Corriger play et pause -<p>Il nous reste un problème à régler. Si on presse les boutons play/pause ou stop pendant que le retour arrière ou l'avance rapide sont actifs, alors ça ne marchera pas. Comment corriger le code pour qu'ils annulent l'action <code>rwd</code>/<code>fwd</code> et joue/stoppe la vidéo comme on s'y attendrait? C'est relativement simple.</p> +Il nous reste un problème à régler. Si on presse les boutons play/pause ou stop pendant que le retour arrière ou l'avance rapide sont actifs, alors ça ne marchera pas. Comment corriger le code pour qu'ils annulent l'action `rwd`/`fwd` et joue/stoppe la vidéo comme on s'y attendrait? C'est relativement simple. -<p>Tout d'abord, ajoutez les lignes qui suivent à l'intérieur de la fonction <code>stopMedia()</code> — n'importe où:</p> +Tout d'abord, ajoutez les lignes qui suivent à l'intérieur de la fonction `stopMedia()` — n'importe où: -<pre class="brush: js">rwd.classList.remove('active'); +```js +rwd.classList.remove('active'); fwd.classList.remove('active'); clearInterval(intervalRwd); clearInterval(intervalFwd); -</pre> +``` -<p>Maintenant, ajoutez ces mêmes lignes une fois de plus, au début de la fonction <code>playPauseMedia()</code> (juste avant le début de l'instruction <code>if</code>).</p> +Maintenant, ajoutez ces mêmes lignes une fois de plus, au début de la fonction `playPauseMedia()` (juste avant le début de l'instruction `if`). -<p>À ce stade, vous pouvez supprimer les lignes équivalentes des fonctions <code>windBackward()</code> et <code>windForward()</code>, puisqu'elles ont été ajoutées à la fonction <code>stopMedia()</code> à la place.</p> +À ce stade, vous pouvez supprimer les lignes équivalentes des fonctions `windBackward()` et `windForward()`, puisqu'elles ont été ajoutées à la fonction `stopMedia()` à la place. -<div class="note"> -<p><strong>Note :</strong> Vous pouvez améliorer votre code en créant une fonction séparée qui exécute ces lignes, et l'appeler aux endroits où vous en avez besoin plutôt que de répéter ces lignes à de multiples endroits du code. Mais nous vous laissons vous en occuper.</p> -</div> +> **Note :** Vous pouvez améliorer votre code en créant une fonction séparée qui exécute ces lignes, et l'appeler aux endroits où vous en avez besoin plutôt que de répéter ces lignes à de multiples endroits du code. Mais nous vous laissons vous en occuper. -<div class="note"> -<p><strong>Note :</strong> Le <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/video-audio/finished">code terminé</a> est disponible sur Github (le <a href="https://mdn.github.io/learning-area/javascript/apis/video-audio/finished/">voir en direct</a>).</p> -</div> +> **Note :** Le [code terminé](https://github.com/mdn/learning-area/tree/master/javascript/apis/video-audio/finished) est disponible sur Github (le [voir en direct](https://mdn.github.io/learning-area/javascript/apis/video-audio/finished/)). + +## Sommaire + +Je pense que nous vous en avons suffisamment appris dans cet article. L'API {{domxref("HTMLMediaElement")}} offre une multitude de fonctionnalités pour la création de lecteurs audio et vidéo simples, et ce n'est que le sommet de l'iceberg. La section "Voir aussi" ci-dessous vous fournirea des liens vers des fonctionnalités plus complexes et plus intéressantes. + +Voici quelques suggestions de modifications à apporter à l'exemple que nous avons construit: + +1. Si la vidéo dure plus d'une heure, le temps écoulé va bien afficher les minutes et les secondes mais pas les heures. Changez l'exemple pour lui faire afficher les heures. +2. Parce que les éléments `<audio>` ont la même fonctionnalité {{domxref("HTMLMediaElement")}} de disponible, vous pouvez faire fonctionner ce lecteur avec un élément `<audio>`. Essayez de le faire. +3. Trouvez un moyen de transformer le `<div>` interne en une véritable barre de progrès — quand vous cliquez quelque part sur la barre, vous vous déplacez à la position relative dans la vidéo. Un indice: vous pouvez trouver les valeurs X et Y des côtés gauche/droite et haut/bas d'un l'élément via la méthode [`getBoundingClientRect()`](/fr/docs/Web/API/Element/getBoundingClientRect), et vous pouvez trouver les coordonnées de la souris au moment du clic à l'intérieur de l'objet `event` du clic, appelé sur l'objet {{domxref("Document")}}. Par exemple: + + ```js + document.onclick = function(e) { + console.log(e.x) + ',' + console.log(e.y) + } + ``` + +## Voir aussi + +- {{domxref("HTMLMediaElement")}} +- [Contenu audio et vidéo](/fr/Apprendre/HTML/Multimedia_and_embedding/Contenu_audio_et_video) — simple guide aux `<video>` et `<audio>` HTML. +- [Intégration audio et vidéo](/fr/Apps/Build/Audio_and_video_delivery) — guide détaillé sur l'intégration de média dans le navigateur, avec de nombreux conseils, astuces et liens vers des tutoriels plus avancés. +- [Manipulation audio et vidéo](/fr/Apps/Fundamentals/Audio_and_video_manipulation) — guide détaillé pour manipuler l'audio et vidéo avec [Canvas API](/fr/docs/Web/HTML/Canvas), [Web Audio API](/fr/docs/Web/API/Web_Audio_API), et plus encore. +- Les pages référence {{htmlelement("video")}} et {{htmlelement("audio")}}. +- [Formats pris en charge par les éléments HTML audio et vidéo](/fr/docs/Web/HTML/Formats_pour_audio_video). + +{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}} + + + +## Dans ce module -<h2 id="Sommaire">Sommaire</h2> - -<p>Je pense que nous vous en avons suffisamment appris dans cet article. L'API {{domxref("HTMLMediaElement")}} offre une multitude de fonctionnalités pour la création de lecteurs audio et vidéo simples, et ce n'est que le sommet de l'iceberg. La section "Voir aussi" ci-dessous vous fournirea des liens vers des fonctionnalités plus complexes et plus intéressantes.</p> - -<p>Voici quelques suggestions de modifications à apporter à l'exemple que nous avons construit:</p> - -<ol> - <li> - <p>Si la vidéo dure plus d'une heure, le temps écoulé va bien afficher les minutes et les secondes mais pas les heures. Changez l'exemple pour lui faire afficher les heures.</p> - </li> - <li> - <p>Parce que les éléments <code><audio></code> ont la même fonctionnalité {{domxref("HTMLMediaElement")}} de disponible, vous pouvez faire fonctionner ce lecteur avec un élément <code><audio></code>. Essayez de le faire.</p> - </li> - <li> - <p>Trouvez un moyen de transformer le <code><div></code> interne en une véritable barre de progrès — quand vous cliquez quelque part sur la barre, vous vous déplacez à la position relative dans la vidéo. Un indice: vous pouvez trouver les valeurs X et Y des côtés gauche/droite et haut/bas d'un l'élément via la méthode <code><a href="/fr/docs/Web/API/Element/getBoundingClientRect">getBoundingClientRect()</a></code>, et vous pouvez trouver les coordonnées de la souris au moment du clic à l'intérieur de l'objet <code>event</code> du clic, appelé sur l'objet {{domxref("Document")}}. Par exemple:</p> - - <pre class="brush: js">document.onclick = function(e) { - console.log(e.x) + ',' + console.log(e.y) -}</pre> - </li> -</ol> - -<h2 id="Voir_aussi">Voir aussi</h2> - -<ul> - <li>{{domxref("HTMLMediaElement")}}</li> - <li><a href="/fr/Apprendre/HTML/Multimedia_and_embedding/Contenu_audio_et_video">Contenu audio et vidéo</a> — simple guide aux <code><video></code> et <code><audio></code> HTML.</li> - <li><a href="/fr/Apps/Build/Audio_and_video_delivery">Intégration audio et vidéo</a> — guide détaillé sur l'intégration de média dans le navigateur, avec de nombreux conseils, astuces et liens vers des tutoriels plus avancés.</li> - <li><a href="/fr/Apps/Fundamentals/Audio_and_video_manipulation">Manipulation audio et vidéo</a> — guide détaillé pour manipuler l'audio et vidéo avec <a href="/fr/docs/Web/HTML/Canvas">Canvas API</a>, <a href="/fr/docs/Web/API/Web_Audio_API">Web Audio API</a>, et plus encore.</li> - <li>Les pages référence {{htmlelement("video")}} et {{htmlelement("audio")}}.</li> - <li> - <p><a href="/fr/docs/Web/HTML/Formats_pour_audio_video">Formats pris en charge par les éléments HTML audio et vidéo</a>.</p> - </li> -</ul> - -<p>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</p> - -<p> </p> - -<h2 id="Dans_ce_module">Dans ce module</h2> - -<ul> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction">Introduction aux API du Web</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipuler des documents</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data">Récupérer des données du serveur</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs tierces</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics">Dessiner des éléments graphiques</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs vidéo et audio</a></li> - <li><a href="/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage">Stockage côté client</a></li> -</ul> +- [Introduction aux API du Web](/fr/Apprendre/JavaScript/Client-side_web_APIs/Introduction) +- [Manipuler des documents](/fr/Apprendre/JavaScript/Client-side_web_APIs/Manipulating_documents) +- [Récupérer des données du serveur](/fr/Apprendre/JavaScript/Client-side_web_APIs/Fetching_data) +- [APIs tierces](/fr/Apprendre/JavaScript/Client-side_web_APIs/Third_party_APIs) +- [Dessiner des éléments graphiques](/fr/Apprendre/JavaScript/Client-side_web_APIs/Drawing_graphics) +- [APIs vidéo et audio](/fr/Apprendre/JavaScript/Client-side_web_APIs/Video_and_audio_APIs) +- [Stockage côté client](/fr/Apprendre/JavaScript/Client-side_web_APIs/Client-side_storage) diff --git a/files/fr/learn/javascript/first_steps/a_first_splash/index.md b/files/fr/learn/javascript/first_steps/a_first_splash/index.md index 40c91d2fa4..4964b628aa 100644 --- a/files/fr/learn/javascript/first_steps/a_first_splash/index.md +++ b/files/fr/learn/javascript/first_steps/a_first_splash/index.md @@ -14,51 +14,50 @@ tags: - structures conditionnelles translation_of: Learn/JavaScript/First_steps/A_first_splash --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</div> - -<p>Maintenant que vous avez appris quelques éléments théoriques sur le JavaScript, et ce que vous pouvez faire avec, nous allons vous donner un cours intensif sur les fonctionnalités basiques du JavaScript avec un tutoriel entièrement pratique. Vous allez construire un jeu simple, étape par étape. Il s'agit de faire deviner un nombre, notre jeu s'appelle « Guess the number ».</p> +Maintenant que vous avez appris quelques éléments théoriques sur le JavaScript, et ce que vous pouvez faire avec, nous allons vous donner un cours intensif sur les fonctionnalités basiques du JavaScript avec un tutoriel entièrement pratique. Vous allez construire un jeu simple, étape par étape. Il s'agit de faire deviner un nombre, notre jeu s'appelle « Guess the number ». <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Une culture informatique basique, et des notions de HTML et CSS.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Avoir une première expérience d'écriture de JavaScript et comprendre les implications de l'écriture d'un programme en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td>Une culture informatique basique, et des notions de HTML et CSS.</td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Avoir une première expérience d'écriture de JavaScript et comprendre les + implications de l'écriture d'un programme en JavaScript. + </td> + </tr> + </tbody> </table> -<p>Ne vous attendez pas à comprendre tout le code en détail immédiatement — nous voulons simplement vous présenter les grands concepts pour le moment, et vous donner une idée de la façon dont JavaScript (et d'autres langages de programmation) fonctionne. Dans les articles suivants, vous reviendrez plus en détails sur toutes ces fonctionnalités !</p> - -<div class="note"> -<p><strong>Note :</strong> De nombreuses fonctionnalités que vous allez voir en JavaScript sont identiques à celles d'autres langages de programmation — fonctions, boucles, etc. La syntaxe du code est différente mais les concepts sont globalement identiques.</p> -</div> +Ne vous attendez pas à comprendre tout le code en détail immédiatement — nous voulons simplement vous présenter les grands concepts pour le moment, et vous donner une idée de la façon dont JavaScript (et d'autres langages de programmation) fonctionne. Dans les articles suivants, vous reviendrez plus en détails sur toutes ces fonctionnalités ! -<h2 id="Penser_comme_un_programmeur">Penser comme un programmeur</h2> +> **Note :** De nombreuses fonctionnalités que vous allez voir en JavaScript sont identiques à celles d'autres langages de programmation — fonctions, boucles, etc. La syntaxe du code est différente mais les concepts sont globalement identiques. -<p>Une des choses les plus difficiles à apprendre en programmation n'est pas la syntaxe, mais comment l'appliquer afin de résoudre un problème réel. Vous devez commencer à penser comme un programmeur — ce qui implique généralement d'examiner les tâches que votre programme doit effectuer, de déterminer les fonctionnalités du code nécessaires à leurs réalisations et comment les faire fonctionner ensemble.</p> +## Penser comme un programmeur -<p>Cela requiert un mélange de travail acharné, d'expérience avec la syntaxe de programmation (de manière générale) et surtout de la pratique — ainsi qu'un peu de créativité. Plus vous allez coder, plus vous aller vous améliorer. On ne peut pas garantir que vous aurez un « cerveau de développeur » en 5 minutes, mais nous allons vous donner plein d'occasions pour pratiquer cette façon de penser, tout au long du cours.</p> +Une des choses les plus difficiles à apprendre en programmation n'est pas la syntaxe, mais comment l'appliquer afin de résoudre un problème réel. Vous devez commencer à penser comme un programmeur — ce qui implique généralement d'examiner les tâches que votre programme doit effectuer, de déterminer les fonctionnalités du code nécessaires à leurs réalisations et comment les faire fonctionner ensemble. -<p>Maintenant que vous avez cela en tête, regardons l'exemple que nous allons construire dans cet article et comment le découper en plusieurs tâches qui ont du sens.</p> +Cela requiert un mélange de travail acharné, d'expérience avec la syntaxe de programmation (de manière générale) et surtout de la pratique — ainsi qu'un peu de créativité. Plus vous allez coder, plus vous aller vous améliorer. On ne peut pas garantir que vous aurez un « cerveau de développeur » en 5 minutes, mais nous allons vous donner plein d'occasions pour pratiquer cette façon de penser, tout au long du cours. -<h2 id="Exemple_—_Jeu_Guess_the_number">Exemple — Jeu : Guess the number</h2> +Maintenant que vous avez cela en tête, regardons l'exemple que nous allons construire dans cet article et comment le découper en plusieurs tâches qui ont du sens. -<p>Dans cet article, nous allons vous montrer comment construire le jeu simple que vous pouvez voir ci-dessous :</p> +## Exemple — Jeu : Guess the number +Dans cet article, nous allons vous montrer comment construire le jeu simple que vous pouvez voir ci-dessous : -<pre class="brush: html hidden"><!DOCTYPE html> -<html> +```html hidden +<!DOCTYPE html> +<html> -<head> - <meta charset="utf-8"> - <title>Number guessing game</title> - <style> +<head> + <meta charset="utf-8"> + <title>Number guessing game</title> + <style> html { font-family: sans-serif; } @@ -74,20 +73,20 @@ translation_of: Learn/JavaScript/First_steps/A_first_splash color: white; padding: 3px; } - </style> -</head> - -<body> - <h1>Deviner un nombre</h1> - <p>Nous avons généré un nombre aléatoire entre 1 et 100, tentez de le deviner en 10 tours maximum. Pour chaque tentative, nous vous dirons si votre estimation est trop ou pas assez élevée.</p> - <div class="form"> <label for="guessField">Entrez votre proposition : </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="Valider" class="guessSubmit"> </div> - <div class="resultParas"> - <p class="guesses"></p> - <p class="lastResult"></p> - <p class="lowOrHi"></p> - </div> -</body> -<script> + </style> +</head> + +<body> + <h1>Deviner un nombre</h1> + <p>Nous avons généré un nombre aléatoire entre 1 et 100, tentez de le deviner en 10 tours maximum. Pour chaque tentative, nous vous dirons si votre estimation est trop ou pas assez élevée.</p> + <div class="form"> <label for="guessField">Entrez votre proposition : </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="Valider" class="guessSubmit"> </div> + <div class="resultParas"> + <p class="guesses"></p> + <p class="lastResult"></p> + <p class="lowOrHi"></p> + </div> +</body> +<script> // Le JavaScript se place ici let randomNumber = Math.floor(Math.random() * 100) + 1; let guesses = document.querySelector('.guesses'); @@ -118,9 +117,9 @@ translation_of: Learn/JavaScript/First_steps/A_first_splash } else { lastResult.textContent = 'Faux!'; lastResult.style.backgroundColor = 'red'; - if (userGuess < randomNumber) { + if (userGuess < randomNumber) { lowOrHi.textContent='Le nombre saisi est trop petit !' ; - } else if(userGuess > randomNumber) { + } else if(userGuess > randomNumber) { lowOrHi.textContent = 'Le nombre saisi est trop grand!'; } } @@ -143,7 +142,7 @@ translation_of: Learn/JavaScript/First_steps/A_first_splash function resetGame() { guessCount = 1; let resetParas = document.querySelectorAll('.resultParas p'); - for (let i = 0 ; i < resetParas.length ; i++) { + for (let i = 0 ; i < resetParas.length ; i++) { resetParas[i].textContent=''; } @@ -155,72 +154,68 @@ translation_of: Learn/JavaScript/First_steps/A_first_splash lastResult.style.backgroundColor='white'; randomNumber=Math.floor(Math.random() * 100) + 1; } -</script> - -</html></pre> - -<p>{{ EmbedLiveSample('Exemple_—_Jeu_Guess_the_number', '100%', 320, "", "", "hide-codepen-jsfiddle") }}</p> - -<p>Essayez de jouer et familiarisez-vous avec ce jeu avant de continuer.</p> - -<p>Imaginons que votre patron vous ait donné le résumé suivant pour créer ce jeu :</p> - -<blockquote> -<p>Je vous demande de créer un jeu simple de devinette de nombre. Le jeu choisit aléatoirement un nombre entre 1 et 100, puis il met le joueur au défi de le deviner en 10 tentatives maxi. À chaque tour, le joueur doit être informé s'il a deviné ou non le bon nombre — si ce n'est pas le cas, le jeu lui indique si son estimation est trop basse ou trop élevée. Le jeu doit également rappeler au joueur les nombres déjà proposés. Le jeu se termine quand le joueur a deviné le nombre mystère, ou s'il a épuisé ses 10 chances. À la fin du jeu, le joueur a la possibilité de débuter une nouvelle partie.</p> -</blockquote> - -<p>La première chose à faire en regardant ce résumé, c'est de le décomposer en tâches simples et codables comme le ferait un programmeur :</p> - -<ol> - <li>Générer un nombre aléatoire entre 1 et 100.</li> - <li>Stocker le nombre de tours déjà joués. Commencer par 1.</li> - <li>Fournir au joueur le moyen de saisir un nombre.</li> - <li>Stocker l'ensemble des propositions de nombres pour que le joueur puisse les consulter.</li> - <li>Vérifier si le nombre saisi par le joueur est correct.</li> - <li>S'il est correct : - <ol> - <li>Afficher un message de félicitations.</li> - <li>Empêcher que le joueur saisisse de nouveau un nombre.</li> - <li>Afficher un contrôle pour que le joueur puisse rejouer.</li> - </ol> - </li> - <li>S'il est faux et que le joueur a encore des tours à jouer : - <ol> - <li>Informer le joueur que sa proposition de nombre est fausse.</li> - <li>Lui permettre d'entrer une nouvelle proposition de nombre.</li> - <li>Incrémenter le nombre de tours de 1.</li> - </ol> - </li> - <li>S'il est faux et que le joueur n'a plus de tours à jouer : - <ol> - <li>Informer le joueur qu'il a perdu et que la partie est finie.</li> - <li>Empêcher que le joueur saisisse de nouveau un nombre.</li> - <li>Afficher un contrôle pour que le joueur puisse rejouer.</li> - </ol> - </li> - <li>Une fois le jeu redémarré, s'assurer que la logique du jeu et l'interface utilisateur sont complètement réinitialisées, puis revenir à l'étape 1.</li> -</ol> - -<p>Voyons maintenant comment nous pouvons transformer ces étapes en code. Nous allons développer cet exemple et explorer les fonctionnalités JavaScript au fur et à mesure.</p> - -<h3 id="Configuration_initiale">Configuration initiale</h3> - -<p>Pour commencer ce didacticiel, faites une copie locale du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game-start.html">number-guessing-game-start.html</a> (à voir <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/first-splash/number-guessing-game-start.html">directement ici</a>). Ouvrez-le dans votre éditeur de code et votre navigateur web. Pour l'instant, vous ne verrez qu'un titre, un paragraphe d'instructions et un formulaire pour entrer une estimation, mais le formulaire est pour l'instant inactif.</p> - -<p>L'endroit où nous allons ajouter tout notre code se trouve dans l'élément {{htmlelement ("script")}} au bas du code HTML :</p> - -<pre class="brush: html"><script> +</script> + +</html> +``` + +{{ EmbedLiveSample('Exemple_—_Jeu_Guess_the_number', '100%', 320, "", "", "hide-codepen-jsfiddle") }} + +Essayez de jouer et familiarisez-vous avec ce jeu avant de continuer. + +Imaginons que votre patron vous ait donné le résumé suivant pour créer ce jeu : + +> Je vous demande de créer un jeu simple de devinette de nombre. Le jeu choisit aléatoirement un nombre entre 1 et 100, puis il met le joueur au défi de le deviner en 10 tentatives maxi. À chaque tour, le joueur doit être informé s'il a deviné ou non le bon nombre — si ce n'est pas le cas, le jeu lui indique si son estimation est trop basse ou trop élevée. Le jeu doit également rappeler au joueur les nombres déjà proposés. Le jeu se termine quand le joueur a deviné le nombre mystère, ou s'il a épuisé ses 10 chances. À la fin du jeu, le joueur a la possibilité de débuter une nouvelle partie. + +La première chose à faire en regardant ce résumé, c'est de le décomposer en tâches simples et codables comme le ferait un programmeur : + +1. Générer un nombre aléatoire entre 1 et 100. +2. Stocker le nombre de tours déjà joués. Commencer par 1. +3. Fournir au joueur le moyen de saisir un nombre. +4. Stocker l'ensemble des propositions de nombres pour que le joueur puisse les consulter. +5. Vérifier si le nombre saisi par le joueur est correct. +6. S'il est correct : + + 1. Afficher un message de félicitations. + 2. Empêcher que le joueur saisisse de nouveau un nombre. + 3. Afficher un contrôle pour que le joueur puisse rejouer. + +7. S'il est faux et que le joueur a encore des tours à jouer : + + 1. Informer le joueur que sa proposition de nombre est fausse. + 2. Lui permettre d'entrer une nouvelle proposition de nombre. + 3. Incrémenter le nombre de tours de 1. + +8. S'il est faux et que le joueur n'a plus de tours à jouer : + + 1. Informer le joueur qu'il a perdu et que la partie est finie. + 2. Empêcher que le joueur saisisse de nouveau un nombre. + 3. Afficher un contrôle pour que le joueur puisse rejouer. + +9. Une fois le jeu redémarré, s'assurer que la logique du jeu et l'interface utilisateur sont complètement réinitialisées, puis revenir à l'étape 1. + +Voyons maintenant comment nous pouvons transformer ces étapes en code. Nous allons développer cet exemple et explorer les fonctionnalités JavaScript au fur et à mesure. + +### Configuration initiale + +Pour commencer ce didacticiel, faites une copie locale du fichier [number-guessing-game-start.html](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game-start.html) (à voir [directement ici](http://mdn.github.io/learning-area/javascript/introduction-to-js-1/first-splash/number-guessing-game-start.html)). Ouvrez-le dans votre éditeur de code et votre navigateur web. Pour l'instant, vous ne verrez qu'un titre, un paragraphe d'instructions et un formulaire pour entrer une estimation, mais le formulaire est pour l'instant inactif. + +L'endroit où nous allons ajouter tout notre code se trouve dans l'élément {{htmlelement ("script")}} au bas du code HTML : + +```html +<script> // Votre code JavaScript se place ici -</script> -</pre> +</script> +``` -<h3 id="Ajouter_des_variables_pour_stocker_les_données">Ajouter des variables pour stocker les données</h3> +### Ajouter des variables pour stocker les données -<p>Commençons. Tout d'abord, ajoutez les lignes suivantes dans l'élément {{htmlelement ("script")}} :</p> +Commençons. Tout d'abord, ajoutez les lignes suivantes dans l'élément {{htmlelement ("script")}} : -<pre class="brush: js">let randomNumber = Math.floor(Math.random() * 100) + 1; +```js +let randomNumber = Math.floor(Math.random() * 100) + 1; let guesses = document.querySelector('.guesses'); let lastResult = document.querySelector('.lastResult'); @@ -230,64 +225,70 @@ let guessSubmit = document.querySelector('.guessSubmit'); let guessField = document.querySelector('.guessField'); let guessCount = 1; -let resetButton;</pre> +let resetButton; +``` + +Cette partie de code définit les variables nécessaires au stockage des données que notre programme utilisera. Les variables sont essentiellement des conteneurs de valeurs (tels que des nombres ou des chaînes de texte). Une variable se crée avec le mot-clé `let` suivi du nom de la variable. Vous pouvez ensuite attribuer une valeur à la variable avec le signe égal (`=`) suivi de la valeur que vous voulez lui donner. -<p>Cette partie de code définit les variables nécessaires au stockage des données que notre programme utilisera. Les variables sont essentiellement des conteneurs de valeurs (tels que des nombres ou des chaînes de texte). Une variable se crée avec le mot-clé <code>let</code> suivi du nom de la variable. Vous pouvez ensuite attribuer une valeur à la variable avec le signe égal (<code>=</code>) suivi de la valeur que vous voulez lui donner.</p> +Dans notre exemple : -<p>Dans notre exemple :</p> +- La première variable — `randomNumber` — reçoit le nombre aléatoire entre 1 et 100, calculé en utilisant un algorithme mathématique. +- Les trois variables suivantes sont chacune faite pour stocker une référence aux paragraphes de résultats dans le HTML ; elles sont utilisées pour insérer des valeurs dans les paragraphes plus tard dans le code : -<ul> - <li>La première variable — <code>randomNumber</code> — reçoit le nombre aléatoire entre 1 et 100, calculé en utilisant un algorithme mathématique.</li> - <li>Les trois variables suivantes sont chacune faite pour stocker une référence aux paragraphes de résultats dans le HTML ; elles sont utilisées pour insérer des valeurs dans les paragraphes plus tard dans le code : - <pre class="brush: html"><p class="guesses"></p> -<p class="lastResult"></p> -<p class="lowOrHi"></p></pre> - </li> - <li>Les deux variables suivantes stockent des références au champ de saisie du formulaire et au bouton de soumission ; elles sont utilisées pour écouter l'envoi de la supposition (guess) plus tard. - <pre class="brush: html"><label for="guessField">Enter a guess: </label><input type="text" id="guessField" class="guessField"> -<input type="submit" value="Submit guess" class="guessSubmit"></pre> - </li> - <li>Nos deux dernières variables stockent un nombre de suppositions qui vaut initialement 1 (utilisées pour garder une trace du nombre de suppositions que le joueur a faite) et une référence à un bouton de réinitialisation qui n'existe pas encore.</li> -</ul> + ```html + <p class="guesses"></p> + <p class="lastResult"></p> + <p class="lowOrHi"></p> + ``` -<div class="note"> -<p><strong>Note :</strong> Vous en apprendrez beaucoup plus sur les variables plus tard dans le cours, en commençant par le <a href="/fr/docs/Learn/JavaScript/First_steps/Variables">prochain article</a>.</p> -</div> +- Les deux variables suivantes stockent des références au champ de saisie du formulaire et au bouton de soumission ; elles sont utilisées pour écouter l'envoi de la supposition (guess) plus tard. -<h3 id="Fonctions">Fonctions</h3> + ```html + <label for="guessField">Enter a guess: </label><input type="text" id="guessField" class="guessField"> + <input type="submit" value="Submit guess" class="guessSubmit"> + ``` -<p>Ajoutez maintenant ce qui suit dans votre code JavaScript :</p> +- Nos deux dernières variables stockent un nombre de suppositions qui vaut initialement 1 (utilisées pour garder une trace du nombre de suppositions que le joueur a faite) et une référence à un bouton de réinitialisation qui n'existe pas encore. -<pre class="brush: js">function checkGuess() { +> **Note :** Vous en apprendrez beaucoup plus sur les variables plus tard dans le cours, en commençant par le [prochain article](/fr/docs/Learn/JavaScript/First_steps/Variables). + +### Fonctions + +Ajoutez maintenant ce qui suit dans votre code JavaScript : + +```js +function checkGuess() { alert('Je suis un espace réservé'); -}</pre> +} +``` -<p>Les fonctions sont des blocs de code réutilisables que vous pouvez écrire une fois et exécuter encore et encore, pour éviter de réécrire le même code tout le temps. C'est vraiment utile. Il y a plusieurs façons de définir les fonctions, mais pour l'instant nous allons nous concentrer sur un type simple. Ici, nous avons défini une fonction en utilisant le mot-clé <code>function</code> accompagné de son nom suivi de parenthèses. Ensuite, nous avons mis deux accolades (<code>{ }</code>). Dans ces accolades est placé tout le code à exécuter à chaque appel de la fonction.</p> +Les fonctions sont des blocs de code réutilisables que vous pouvez écrire une fois et exécuter encore et encore, pour éviter de réécrire le même code tout le temps. C'est vraiment utile. Il y a plusieurs façons de définir les fonctions, mais pour l'instant nous allons nous concentrer sur un type simple. Ici, nous avons défini une fonction en utilisant le mot-clé `function` accompagné de son nom suivi de parenthèses. Ensuite, nous avons mis deux accolades (`{ }`). Dans ces accolades est placé tout le code à exécuter à chaque appel de la fonction. -<p>Quand nous voulons exécuter le code, nous saisissons le nom de la fonction suivi des parenthèses.</p> +Quand nous voulons exécuter le code, nous saisissons le nom de la fonction suivi des parenthèses. -<p>Essayez. Enregistrez le code et actualisez la page du navigateur. Puis, allez dans les<a href="/fr/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs"> outils de développement et la console JavaScript </a>et entrez la ligne suivante :</p> +Essayez. Enregistrez le code et actualisez la page du navigateur. Puis, allez dans les[ outils de développement et la console JavaScript ](/fr/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs)et entrez la ligne suivante : -<pre class="brush: js">checkGuess();</pre> +```js +checkGuess(); +``` -<p>Après avoir pressé <kbd>Entrée</kbd> ou <kbd>Retour</kbd>, vous devriez voir apparaître une alerte « Je suis un espace réservé » ; nous avons défini une fonction dans notre code créant une alerte chaque fois que nous l'appelons.</p> +Après avoir pressé <kbd>Entrée</kbd> ou <kbd>Retour</kbd>, vous devriez voir apparaître une alerte « Je suis un espace réservé » ; nous avons défini une fonction dans notre code créant une alerte chaque fois que nous l'appelons. -<div class="note"> -<p><strong>Note :</strong> Vous allez en apprendre beaucoup plus sur les fonctions plus tard dans ce cours.</p> -</div> +> **Note :** Vous allez en apprendre beaucoup plus sur les fonctions plus tard dans ce cours. -<h3 id="Opérateurs">Opérateurs</h3> +### Opérateurs -<p>Les opérateurs en JavaScript nous permettent d'effectuer des tests, de faire des calculs, de joindre des chaînes ensemble et d'autres choses de ce genre.</p> +Les opérateurs en JavaScript nous permettent d'effectuer des tests, de faire des calculs, de joindre des chaînes ensemble et d'autres choses de ce genre. -<p>Si vous ne l'avez pas déjà fait, sauvegardez ce code, actualisez la page affichée dans le navigateur et ouvrez les<a href="/fr/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs"> outils de développement et la console Javascript</a>. Ensuite, vous pouvez saisir les exemples ci‑dessous — saisissez chacun dans les colonnes « Exemple » exactement comme indiqué, en appuyant sur la touche <kbd>Entrée</kbd> du clavier après chacun et regardez le résultat renvoyé. Si vous n'avez pas facilement accès aux outils de développement du navigateur, vous pouvez toujours utiliser la console intégrée ci-dessous :</p> +Si vous ne l'avez pas déjà fait, sauvegardez ce code, actualisez la page affichée dans le navigateur et ouvrez les[ outils de développement et la console Javascript](/fr/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs). Ensuite, vous pouvez saisir les exemples ci‑dessous — saisissez chacun dans les colonnes « Exemple » exactement comme indiqué, en appuyant sur la touche <kbd>Entrée</kbd> du clavier après chacun et regardez le résultat renvoyé. Si vous n'avez pas facilement accès aux outils de développement du navigateur, vous pouvez toujours utiliser la console intégrée ci-dessous : -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Console JavaScript</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Console JavaScript</title> + <style> * { box-sizing: border-box; } @@ -335,14 +336,14 @@ let resetButton;</pre> clear: both; } - </style> - </head> - <body> + </style> + </head> + <body> - </body> + </body> - <script> + <script> let geval = eval; function createInput() { @@ -351,13 +352,13 @@ let resetButton;</pre> let inputForm = document.createElement('input'); inputDiv.setAttribute('class','input'); - inputPara.textContent = '>'; + inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); inputDiv.focus(); - if (document.querySelectorAll('div').length > 1) { + if (document.querySelectorAll('div').length > 1) { inputForm.focus(); } @@ -387,101 +388,61 @@ let resetButton;</pre> createInput(); - </script> -</html></pre> + </script> +</html> +``` -<p>{{ EmbedLiveSample('Opérateurs', '100%', 300,"", "", "hide-codepen-jsfiddle") }}</p> +{{ EmbedLiveSample('Opérateurs', '100%', 300,"", "", "hide-codepen-jsfiddle") }} -<p>Regardons d'abord les opérateurs arithmétiques, par exemple :</p> +Regardons d'abord les opérateurs arithmétiques, par exemple : -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Operator</th> - <th scope="col">Name</th> - <th scope="col">Example</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>+</code></td> - <td>Addition</td> - <td><code>6 + 9</code></td> - </tr> - <tr> - <td><code>-</code></td> - <td>Soustraction</td> - <td><code>20 - 15</code></td> - </tr> - <tr> - <td><code>*</code></td> - <td>Multiplication</td> - <td><code>3 * 7</code></td> - </tr> - <tr> - <td><code>/</code></td> - <td>Division</td> - <td><code>10 / 5</code></td> - </tr> - </tbody> -</table> +| Operator | Name | Example | +| -------- | -------------- | --------- | +| `+` | Addition | `6 + 9` | +| `-` | Soustraction | `20 - 15` | +| `*` | Multiplication | `3 * 7` | +| `/` | Division | `10 / 5` | -<p>L'opérateur <code>+</code> peut aussi s'utiliser pour unir des chaînes de caractères (en informatique, on dit <em>concaténer</em>). Entrez les lignes suivantes, une par une :</p> +L'opérateur `+` peut aussi s'utiliser pour unir des chaînes de caractères (en informatique, on dit *concaténer*). Entrez les lignes suivantes, une par une : -<pre class="brush: js">let name = 'Bingo'; +```js +let name = 'Bingo'; name; let hello = ' dit bonjour !'; hello; let greeting = name + hello; -greeting;</pre> +greeting; +``` -<p>Des raccourcis d'opérateurs sont également disponibles, appelés <a href="/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_d_affectation">opérateurs d'assignation</a> augmentés. Par exemple, si vous voulez simplement ajouter une nouvelle chaîne de texte à une chaîne existante et renvoyer le résultat, vous pouvez faire :</p> +Des raccourcis d'opérateurs sont également disponibles, appelés [opérateurs d'assignation](/fr/docs/Web/JavaScript/Reference/Opérateurs/Opérateurs_d_affectation) augmentés. Par exemple, si vous voulez simplement ajouter une nouvelle chaîne de texte à une chaîne existante et renvoyer le résultat, vous pouvez faire : -<pre class="brush: js">name += ' dit bonjour !';</pre> +```js +name += ' dit bonjour !'; +``` -<p>Cela équivaut à :</p> +Cela équivaut à : -<pre class="brush: js">name = name + ' dit bonjour !';</pre> +```js +name = name + ' dit bonjour !'; +``` -<p>Lorsque nous exécutons des tests vrai/faux (par exemple, dans des conditions — voir {{anch ("Structures conditionnelles", "ci-dessous")}}, nous utilisons des <a href="/fr/docs/Web/JavaScript/Reference/Operators/Comparison_Operators">opérateurs de comparaison</a>, par exemple :</p> +Lorsque nous exécutons des tests vrai/faux (par exemple, dans des conditions — voir {{anch ("Structures conditionnelles", "ci-dessous")}}, nous utilisons des [opérateurs de comparaison](/fr/docs/Web/JavaScript/Reference/Operators/Comparison_Operators), par exemple : -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Operator</th> - <th scope="col">Name</th> - <th scope="col">Example</th> - </tr> - <tr> - <td><code>===</code></td> - <td>Égalité stricte (est-ce exactement identique ?)</td> - <td><code>5 === 2 + 4</code></td> - </tr> - <tr> - <td><code>!==</code></td> - <td>Non égalité (est-ce différent ?)</td> - <td><code>'Chris' !== 'Ch' + 'ris'</code></td> - </tr> - <tr> - <td><code><</code></td> - <td>Inférieur à</td> - <td><code>10 < 6</code></td> - </tr> - <tr> - <td><code>></code></td> - <td>Supérieur à</td> - <td><code>10 > 20</code></td> - </tr> - </thead> -</table> +| Operator | Name | Example | +| -------- | ----------------------------------------------- | -------------------------- | +| `===` | Égalité stricte (est-ce exactement identique ?) | `5 === 2 + 4` | +| `!==` | Non égalité (est-ce différent ?) | `'Chris' !== 'Ch' + 'ris'` | +| `<` | Inférieur à | `10 < 6` | +| `>` | Supérieur à | `10 > 20` | -<h3 id="Structures_conditionnelles">Structures conditionnelles</h3> +### Structures conditionnelles -<p>Revenons à la fonction <code>checkGuess()</code>. Nous pouvons assurément dire que nous ne souhaitons pas qu'elle renvoie un message d'emplacement réservé. Nous voulons qu'elle vérifie si la supposition du joueur est correcte ou non et qu'elle renvoie une réponse appropriée.</p> +Revenons à la fonction `checkGuess()`. Nous pouvons assurément dire que nous ne souhaitons pas qu'elle renvoie un message d'emplacement réservé. Nous voulons qu'elle vérifie si la supposition du joueur est correcte ou non et qu'elle renvoie une réponse appropriée. -<p>Donc, remplacez l'actuelle fonction <code>checkGuess()</code> par celle-ci :</p> +Donc, remplacez l'actuelle fonction `checkGuess()` par celle-ci : -<pre class="brush: js">function checkGuess(){ +```js +function checkGuess(){ let userGuess = Number(guessField.value); if (guessCount === 1) { guesses.textContent = 'Propositions précédentes : '; @@ -499,9 +460,9 @@ greeting;</pre> } else { lastResult.textContent = 'Faux !'; lastResult.style.backgroundColor = 'red'; - if (userGuess < randomNumber) { + if (userGuess < randomNumber) { lowOrHi.textContent = 'Le nombre saisi est trop petit !'; - } else if (userGuess > randomNumber) { + } else if (userGuess > randomNumber) { lowOrHi.textContent = 'Le nombre saisi est trop grand !'; } } @@ -510,69 +471,73 @@ greeting;</pre> guessField.value = ''; guessField.focus(); } -</pre> +``` + +Pas mal de code — ouf ! Passons en revue chaque section et expliquons ce qu'elle fait. + +- La première ligne de la fonction (ligne 2) déclare une variable nommée `userGuess` et définit sa valeur par celle qui vient d'être saisie dans le champ de texte. Nous faisons passer aussi cette valeur par la méthode `Number()` , juste pour nous assurer que la valeur stockée dans `userGuess` est bien un nombre. +- Ensuite, nous rencontrons notre premier bloc de code conditionnel (lignes 3-5). Il permet d'exécuter des instructions de manière sélective, selon certaines conditions qui sont vraies ou non. Cela ressemble un peu à une fonction, mais ce n'est pas le cas. La forme la plus simple du bloc conditionnel commence par le mot clé `if`, puis parenthèses, puis des accolades `{ }`. + A l'intérieur de ces parenthèses, nous mettons le test. S'il renvoie `true` , nous exécutons le code à l'intérieur des accolades. Sinon, nous ne le faisons pas, et passons au morceau de code suivant. Dans ce cas, le test vérifie si la variable `guessCount` est égale à `1` (c'est-à-dire s'il s'agit de la première supposition du joueur) : + + ```js + guessCount === 1 + ``` -<p>Pas mal de code — ouf ! Passons en revue chaque section et expliquons ce qu'elle fait.</p> + Si c'est le cas, nous faisons en sorte que le texte affiché soit « Propositions précédentes : ». Sinon, nous ne le faisons pas. -<ul> - <li>La première ligne de la fonction (ligne 2) déclare une variable nommée <code>userGuess</code> et définit sa valeur par celle qui vient d'être saisie dans le champ de texte. Nous faisons passer aussi cette valeur par la méthode <code>Number()</code> , juste pour nous assurer que la valeur stockée dans <code>userGuess</code> est bien un nombre.</li> - <li>Ensuite, nous rencontrons notre premier bloc de code conditionnel (lignes 3-5). Il permet d'exécuter des instructions de manière sélective, selon certaines conditions qui sont vraies ou non. Cela ressemble un peu à une fonction, mais ce n'est pas le cas. La forme la plus simple du bloc conditionnel commence par le mot clé <code>if</code>, puis parenthèses, puis des accolades <code>{ }</code>.<br> - A l'intérieur de ces parenthèses, nous mettons le test. S'il renvoie <code>true</code> , nous exécutons le code à l'intérieur des accolades. Sinon, nous ne le faisons pas, et passons au morceau de code suivant. Dans ce cas, le test vérifie si la variable <code>guessCount</code> est égale à <code>1</code> (c'est-à-dire s'il s'agit de la première supposition du joueur) : - <pre class="brush: js">guessCount === 1</pre> - Si c'est le cas, nous faisons en sorte que le texte affiché soit « Propositions précédentes : ». Sinon, nous ne le faisons pas.</li> - <li>La ligne 6 ajoute la valeur courante <code>userGuess</code> à la fin du paragraphe <code>guesses</code> , plus un espace vide de sorte qu'il y aura un espace entre chaque supposition faite.</li> - <li>Le bloc suivant (lignes 8-24) effectue quelques vérifications : - <ul> - <li>Le premier <code>if(){ }</code> vérifie si la supposition de l'utilisateur est égale au nombre aléatoire <code>randomNumber</code> situé en haut de notre code JavaScript. Si c'est le cas, le joueur a deviné correctement et a gagné le jeu, nous affichons donc un message de félicitations d'une belle couleur verte au joueur, effaçons le contenu de la boîte d'information sur la position de l'estimation et exécutons une fonction appelée <code>setGameOver()</code>, dont nous reparlerons plus tard.</li> - <li>Ensuite, nous chaînons un autre test à la fin du précédent avec une structure <code>else if(){ }</code>. Cette structure vérifie si l'utilisateur a épuisé toutes ses tentatives. Si c'est le cas, le programme fait la même chose que dans le bloc précédent, mais avec un message de fin de partie au lieu d'un message de félicitations.</li> - <li>Le dernier bloc chaîné à la fin de ce code (<code>else { }</code>) contient du code qui n'est exécuté que si aucun des deux autres tests n'a renvoyé <em>vrai</em> (c'est-à-dire que le joueur n'a pas deviné juste, mais qu'il lui reste des possibilité de supposition). Dans ce cas, nous lui disons que sa supposition est mauvaise, puis nous effectuons un autre test conditionnel pour vérifier si elle est supérieure ou inférieure à la valeur exacte et affichons un autre message approprié pour indiquer si sa supposition est trop forte ou trop faible.</li> - </ul> - </li> -</ul> +- La ligne 6 ajoute la valeur courante `userGuess` à la fin du paragraphe `guesses` , plus un espace vide de sorte qu'il y aura un espace entre chaque supposition faite. +- Le bloc suivant (lignes 8-24) effectue quelques vérifications : -<ul> - <li>Les trois dernières lignes de la fonction (ligne 26-28) préparent à une nouvelle proposition. Nous ajoutons 1 à la variable <code>guessCount</code> qui décompte les tours (<code>++</code> est une opération d'incrémentation — ajout de 1), puis effaçons le champ texte du formulaire et lui redonnons le focus, pour être prêt pour la saisie suivante.</li> -</ul> + - Le premier `if(){ }` vérifie si la supposition de l'utilisateur est égale au nombre aléatoire `randomNumber` situé en haut de notre code JavaScript. Si c'est le cas, le joueur a deviné correctement et a gagné le jeu, nous affichons donc un message de félicitations d'une belle couleur verte au joueur, effaçons le contenu de la boîte d'information sur la position de l'estimation et exécutons une fonction appelée `setGameOver()`, dont nous reparlerons plus tard. + - Ensuite, nous chaînons un autre test à la fin du précédent avec une structure `else if(){ }`. Cette structure vérifie si l'utilisateur a épuisé toutes ses tentatives. Si c'est le cas, le programme fait la même chose que dans le bloc précédent, mais avec un message de fin de partie au lieu d'un message de félicitations. + - Le dernier bloc chaîné à la fin de ce code (`else { }`) contient du code qui n'est exécuté que si aucun des deux autres tests n'a renvoyé _vrai_ (c'est-à-dire que le joueur n'a pas deviné juste, mais qu'il lui reste des possibilité de supposition). Dans ce cas, nous lui disons que sa supposition est mauvaise, puis nous effectuons un autre test conditionnel pour vérifier si elle est supérieure ou inférieure à la valeur exacte et affichons un autre message approprié pour indiquer si sa supposition est trop forte ou trop faible. -<h3 id="Evénements">Evénements</h3> +<!----> -<p>À ce stade, nous avons bien implémentée la fonction <code>checkGuess()</code>, mais elle ne s'éxecutera pas parce que nous ne l'avons pas encore appelé.<br> - Idéalement, nous voulons l'appeler lorsque le bouton <kbd>Soumettre</kbd> est cliqué, et pour ce faire, nous devons utiliser un événement. Les événements sont des actions qui se produisent dans le navigateur, comme le clic sur un bouton, le chargement d'une page ou la lecture d'une vidéo, en réponse à quoi nous pouvons exécuter des blocs de code. Les constructions qui écoutent l'événement en cours s'appellent des <strong>écouteurs d'événements</strong>, et les blocs de code exécutés en réponse à l'événement déclencheur sont appelés des <strong>gestionnaires d'évenements</strong>.<br> - <br> - Ajoutez la ligne suivante sous l'accolade de fermeture de votre fonction <code>checkGuess()</code> :</p> +- Les trois dernières lignes de la fonction (ligne 26-28) préparent à une nouvelle proposition. Nous ajoutons 1 à la variable `guessCount` qui décompte les tours (`++` est une opération d'incrémentation — ajout de 1), puis effaçons le champ texte du formulaire et lui redonnons le focus, pour être prêt pour la saisie suivante. -<pre class="brush: js">guessSubmit.addEventListener('click', checkGuess);</pre> +### Evénements -<p>Ici, nous ajoutons un écouteur d'événement au bouton <code>guessSubmit</code> . C'est une méthode qui prend deux valeurs d'entrée (appelées arguments) - le type d'événement que nous écoutons (dans ce cas, <code>click</code>) qui est une chaîne de caractères, et le code que nous voulons exécuter quand l'événement se produit (dans ce cas, la fonction <code>checkGuess()</code> — notez que nous n'avons pas besoin de spécifier les parenthèses lors de l'écriture dans {{domxref("EventTarget.addEventListener", "addEventListener()")}}).</p> +À ce stade, nous avons bien implémentée la fonction `checkGuess()`, mais elle ne s'éxecutera pas parce que nous ne l'avons pas encore appelé. +Idéalement, nous voulons l'appeler lorsque le bouton <kbd>Soumettre</kbd> est cliqué, et pour ce faire, nous devons utiliser un événement. Les événements sont des actions qui se produisent dans le navigateur, comme le clic sur un bouton, le chargement d'une page ou la lecture d'une vidéo, en réponse à quoi nous pouvons exécuter des blocs de code. Les constructions qui écoutent l'événement en cours s'appellent des **écouteurs d'événements**, et les blocs de code exécutés en réponse à l'événement déclencheur sont appelés des **gestionnaires d'évenements**. -<p>Essayez d'enregistrer et d'actualiser votre code, votre exemple devrait désormais fonctionner, jusqu'à un certain point. Maintenant, le seul problème est que si vous devinez la bonne réponse ou si vous n'avez plus de tours à jouer, le jeu "va se casser" parce que nous n'avons pas encore implémenté la fonction <code>setGameOver()</code> dont le rôle est de terminer proprement le jeu. Ajoutons maintenant le code manquant pour compléter notre exemple.</p> +Ajoutez la ligne suivante sous l'accolade de fermeture de votre fonction `checkGuess()` : -<h3 id="Finir_les_fonctionnalités_du_jeu">Finir les fonctionnalités du jeu</h3> +```js +guessSubmit.addEventListener('click', checkGuess); +``` -<p>Pour définir la fonction <code>setGameOver()</code> à la fin de notre programme, ajoutez le code ci-dessous tout en bas :</p> +Ici, nous ajoutons un écouteur d'événement au bouton `guessSubmit` . C'est une méthode qui prend deux valeurs d'entrée (appelées arguments) - le type d'événement que nous écoutons (dans ce cas, `click`) qui est une chaîne de caractères, et le code que nous voulons exécuter quand l'événement se produit (dans ce cas, la fonction `checkGuess()` — notez que nous n'avons pas besoin de spécifier les parenthèses lors de l'écriture dans {{domxref("EventTarget.addEventListener", "addEventListener()")}}). -<pre class="brush: js">function setGameOver() { +Essayez d'enregistrer et d'actualiser votre code, votre exemple devrait désormais fonctionner, jusqu'à un certain point. Maintenant, le seul problème est que si vous devinez la bonne réponse ou si vous n'avez plus de tours à jouer, le jeu "va se casser" parce que nous n'avons pas encore implémenté la fonction `setGameOver()` dont le rôle est de terminer proprement le jeu. Ajoutons maintenant le code manquant pour compléter notre exemple. + +### Finir les fonctionnalités du jeu + +Pour définir la fonction `setGameOver()` à la fin de notre programme, ajoutez le code ci-dessous tout en bas : + +```js +function setGameOver() { guessField.disabled = true; guessSubmit.disabled = true; resetButton = document.createElement('button'); resetButton.textContent = 'Start new game'; document.body.appendChild(resetButton); resetButton.addEventListener('click', resetGame); -}</pre> +} +``` -<ul> - <li>Les deux premières lignes désactivent l'entrée de texte et le bouton en définissant leurs propriétés désactivées à <code>true</code>. Ceci est nécessaire, car si nous ne le faisons pas, l'utilisateur pourrait soumettre plus de propositions après la fin du jeu, ce qui gâcherait les choses.</li> - <li>Les trois lignes suivantes génèrent un nouvel {{htmlelement("button")}} élément, avec le libellé "Démarrer une nouvelle partie" et l'ajoute au bas du HTML existant.</li> - <li>La dernière ligne définit un écouteur d'événement sur ce nouveau bouton : un click sur le bouton déclenchera un appel de la fonction <code>resetGame()</code>.</li> -</ul> +- Les deux premières lignes désactivent l'entrée de texte et le bouton en définissant leurs propriétés désactivées à `true`. Ceci est nécessaire, car si nous ne le faisons pas, l'utilisateur pourrait soumettre plus de propositions après la fin du jeu, ce qui gâcherait les choses. +- Les trois lignes suivantes génèrent un nouvel {{htmlelement("button")}} élément, avec le libellé "Démarrer une nouvelle partie" et l'ajoute au bas du HTML existant. +- La dernière ligne définit un écouteur d'événement sur ce nouveau bouton : un click sur le bouton déclenchera un appel de la fonction `resetGame()`. -<p>Reste à définir cette fonction ! Ajoutez le code suivant, tout en bas de votre JavaScript :</p> +Reste à définir cette fonction ! Ajoutez le code suivant, tout en bas de votre JavaScript : -<pre class="brush: js">function resetGame() { +```js +function resetGame() { guessCount = 1; let resetParas = document.querySelectorAll('.resultParas p'); - for (let i = 0 ; i < resetParas.length ; i++) { + for (let i = 0 ; i < resetParas.length ; i++) { resetParas[i].textContent = ''; } @@ -586,114 +551,121 @@ greeting;</pre> lastResult.style.backgroundColor = 'white'; randomNumber = Math.floor(Math.random() * 100) + 1; -}</pre> +} +``` -<p>Ce bloc de code assez long réinitialise complètement les paramètres du jeu (le joueur pourra commencer une nouvelle partie). Il permet de :</p> +Ce bloc de code assez long réinitialise complètement les paramètres du jeu (le joueur pourra commencer une nouvelle partie). Il permet de : -<ul> - <li>Remettre le compteur <code>guessCount</code> à 1.</li> - <li>Effacer tous les paragraphes d'information.</li> - <li>Supprimer le bouton de réinitialisation de notre code.</li> - <li>Activer les éléments de formulaire, vide et met au point le champ de texte, prêt à entrer une nouvelle proposition.</li> - <li>Supprimer la couleur d'arrière-plan du paragraphe <code>lastResult</code>.</li> - <li>Génèrer un nouveau nombre aléatoire afin que vous ne deviniez plus le même nombre !</li> -</ul> +- Remettre le compteur `guessCount` à 1. +- Effacer tous les paragraphes d'information. +- Supprimer le bouton de réinitialisation de notre code. +- Activer les éléments de formulaire, vide et met au point le champ de texte, prêt à entrer une nouvelle proposition. +- Supprimer la couleur d'arrière-plan du paragraphe `lastResult`. +- Génèrer un nouveau nombre aléatoire afin que vous ne deviniez plus le même nombre ! -<p><strong>À ce stade, vous devriez avoir un jeu (simple) entièrement fonctionnel — félicitations!</strong></p> +**À ce stade, vous devriez avoir un jeu (simple) entièrement fonctionnel — félicitations!** -<p>Pour finir, c'est le moment de faire une synthèse sur quelques caractéristiques importantes du code ; vous les avez déjà vues, sans forcément vous en rendre compte.</p> +Pour finir, c'est le moment de faire une synthèse sur quelques caractéristiques importantes du code ; vous les avez déjà vues, sans forcément vous en rendre compte. -<h3 id="Boucles">Boucles</h3> +### Boucles -<p>Dans le code précédent, une partie à examiner de plus près est la boucle <a href="/fr/docs/Web/JavaScript/Reference/Instructions/for">for</a>. Les boucles sont un concept très important dans la programmation, qui vous permet de continuer à exécuter un morceau de code encore et encore, jusqu'à ce qu'une certaine condition soit remplie.</p> +Dans le code précédent, une partie à examiner de plus près est la boucle [for](/fr/docs/Web/JavaScript/Reference/Instructions/for). Les boucles sont un concept très important dans la programmation, qui vous permet de continuer à exécuter un morceau de code encore et encore, jusqu'à ce qu'une certaine condition soit remplie. -<p>Pour commencer, allez sur votre <a href="/fr/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs">console developpeur Javascript</a> et entrez ce qui suit :</p> +Pour commencer, allez sur votre [console developpeur Javascript](/fr/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs) et entrez ce qui suit : -<pre class="brush: js">for (let i = 1 ; i < 21 ; i++) { console.log(i) }</pre> +```js +for (let i = 1 ; i < 21 ; i++) { console.log(i) } +``` -<p>Que s'est-il passé ? Les nombres de 1 à 20 s'affichent dans la console. C'est à cause de la boucle. Une boucle : <code>for</code> prend trois valeurs d'entrée (arguments)</p> +Que s'est-il passé ? Les nombres de 1 à 20 s'affichent dans la console. C'est à cause de la boucle. Une boucle : `for` prend trois valeurs d'entrée (arguments) -<ol> - <li><strong>Une valeur de départ </strong>: Dans ce cas, nous commençons un compte à 1, mais cela pourrait être n'importe quel nombre. Vous pouvez remplacer <code>i</code> par n'importe quel nom (ou presque...) , mais <code>i</code> est utilisé par convention car il est court et facile à retenir.</li> - <li><strong>Une condition de fin </strong>: Ici, nous avons spécifié <code>i < 21</code> la boucle continuera jusqu'à ce que <code>i</code> ne soit plus inférieur à 21. Quand <code>i</code> atteindra ou dépassera 21, la boucle s'arrêtera.</li> - <li><strong>Un incrémenteur </strong>: Nous avons spécifié <code>i++</code>, ce qui signifie "ajouter 1 à i". La boucle sera exécutée une fois pour chaque valeur de <code>i</code>, jusqu'a ce que <code>i</code> atteigne une valeur de 21 (comme indiqué ci-dessus). Dans ce cas, nous imprimons simplement la valeur de <code>i</code> sur la console à chaque itération en utilisant {{domxref("Console.log", "console.log()")}}.</li> -</ol> +1. **Une valeur de départ** : Dans ce cas, nous commençons un compte à 1, mais cela pourrait être n'importe quel nombre. Vous pouvez remplacer `i` par n'importe quel nom (ou presque...) , mais `i` est utilisé par convention car il est court et facile à retenir. +2. **Une condition de fin** : Ici, nous avons spécifié `i < 21` la boucle continuera jusqu'à ce que `i` ne soit plus inférieur à 21. Quand `i` atteindra ou dépassera 21, la boucle s'arrêtera. +3. **Un incrémenteur** : Nous avons spécifié `i++`, ce qui signifie "ajouter 1 à i". La boucle sera exécutée une fois pour chaque valeur de `i`, jusqu'a ce que `i` atteigne une valeur de 21 (comme indiqué ci-dessus). Dans ce cas, nous imprimons simplement la valeur de `i` sur la console à chaque itération en utilisant {{domxref("Console.log", "console.log()")}}. -<p>Maintenant, regardons la boucle dans notre jeu de devinettes de nombres <strong>—</strong> ce qui suit peut être trouvé dans la fonction <code>resetGame()</code> :</p> +Maintenant, regardons la boucle dans notre jeu de devinettes de nombres **—** ce qui suit peut être trouvé dans la fonction `resetGame()` : -<pre class="brush: js">let resetParas = document.querySelectorAll('.resultParas p'); -for (let i = 0 ; i < resetParas.length ; i++) { +```js +let resetParas = document.querySelectorAll('.resultParas p'); +for (let i = 0 ; i < resetParas.length ; i++) { resetParas[i].textContent = ''; -}</pre> +} +``` + +Ce code crée une variable contenant une liste de tous les paragraphes à l'intérieur de `<div class="resultParas">` en utilisant la méthode {{domxref ("Document.querySelectorAll", "querySelectorAll ()")}}, puis il passe dans la boucle et pour chacun d'entre eux supprime le contenu du texte. + +### Une petite discussion sur les objets -<p>Ce code crée une variable contenant une liste de tous les paragraphes à l'intérieur de <code><div class="resultParas"></code> en utilisant la méthode {{domxref ("Document.querySelectorAll", "querySelectorAll ()")}}, puis il passe dans la boucle et pour chacun d'entre eux supprime le contenu du texte.</p> +Voyons une dernière amélioration avant d'aborder cette discussion. Ajoutez la ligne suivante juste en dessous de `let resetButton;` ligne près du haut de votre JavaScript, puis enregistrez votre fichier : -<h3 id="Une_petite_discussion_sur_les_objets">Une petite discussion sur les objets</h3> +```js +guessField.focus(); +``` -<p>Voyons une dernière amélioration avant d'aborder cette discussion. Ajoutez la ligne suivante juste en dessous de <code>let resetButton;</code> ligne près du haut de votre JavaScript, puis enregistrez votre fichier :</p> +Cette ligne utilise la méthode{{domxref("HTMLElement.focus", "focus()")}} pour placer automatiquement le curseur dans le champ texte {{htmlelement ("input")}} dès le chargement de la page, permettant à l'utilisateur de commencer à taper sa première proposition de suite sans avoir à cliquer préalablement dans le champ. Ce n'est qu'un petit ajout, mais cela améliore la convivialité en donnant à l'utilisateur une bonne idée visuelle de ce qu'il doit faire pour jouer. -<pre class="brush: js">guessField.focus();</pre> +Analysons ce qui se passe ici un peu plus en détail. En JavaScript, tout est objet. Un objet JavaScript possède des propriétés, chacune définissant une caractéristique. Vous pouvez créer vos propres objets, mais cela est une notion assez avancée, nous ne la couvrirons que beaucoup plus tard dans le cours. Pour l'instant, nous allons discuter brièvement des objets intégrés que contient votre navigateur, ce qui vous permet de faire beaucoup de choses utiles. -<p>Cette ligne utilise la méthode{{domxref("HTMLElement.focus", "focus()")}} pour placer automatiquement le curseur dans le champ texte {{htmlelement ("input")}} dès le chargement de la page, permettant à l'utilisateur de commencer à taper sa première proposition de suite sans avoir à cliquer préalablement dans le champ. Ce n'est qu'un petit ajout, mais cela améliore la convivialité en donnant à l'utilisateur une bonne idée visuelle de ce qu'il doit faire pour jouer.</p> +Dans ce cas particulier, nous avons d'abord créé une variable `guessField` qui stocke une référence au champ de formulaire de saisie de texte dans notre HTML **—** la ligne suivante se trouve parmi nos déclarations de variables en haut du code : + +```js +let guessField = document.querySelector('.guessField'); +``` -<p>Analysons ce qui se passe ici un peu plus en détail. En JavaScript, tout est objet. Un objet JavaScript possède des propriétés, chacune définissant une caractéristique. Vous pouvez créer vos propres objets, mais cela est une notion assez avancée, nous ne la couvrirons que beaucoup plus tard dans le cours. Pour l'instant, nous allons discuter brièvement des objets intégrés que contient votre navigateur, ce qui vous permet de faire beaucoup de choses utiles.</p> +Pour obtenir cette référence, nous avons utilisé la méthode {{domxref("document.querySelector", "querySelector()")}} de l'objet {{domxref ("document")}}. `querySelector()` prend une information - un [sélecteur CSS ](/fr/docs/Apprendre/CSS/Introduction_à_CSS/Les_sélecteurs)qui sélectionne l'élément auquel vous voulez faire référence. -<p>Dans ce cas particulier, nous avons d'abord créé une variable <code>guessField</code> qui stocke une référence au champ de formulaire de saisie de texte dans notre HTML <strong>—</strong> la ligne suivante se trouve parmi nos déclarations de variables en haut du code :</p> +Parce que `guessField` contient maintenant une référence à un élément {{htmlelement ("input")}}, il aura maintenant accès à un certain nombre de propriétés (essentiellement des variables stockées dans des objets, dont certaines ne peuvent pas être modifiées) et des méthodes (essentiellement des fonctions stockées dans des objets). Une méthode disponible pour entrer des éléments est `focus()`, donc nous pouvons maintenant utiliser cette ligne pour focaliser l'entrée de texte : -<pre class="brush: js">let guessField = document.querySelector('.guessField');</pre> +```js +guessField.focus(); +``` -<p>Pour obtenir cette référence, nous avons utilisé la méthode {{domxref("document.querySelector", "querySelector()")}} de l'objet {{domxref ("document")}}. <code>querySelector()</code> prend une information - un <a href="/fr/docs/Apprendre/CSS/Introduction_à_CSS/Les_sélecteurs">sélecteur CSS </a>qui sélectionne l'élément auquel vous voulez faire référence.</p> +Les variables qui ne contiennent pas de références aux éléments de formulaire n'auront pas de `focus()` à leur disposition. Par exemple, la variable `guesses` contient une référence à un élément {{htmlelement ("p")}} et `guessCount` contient un nombre. -<p>Parce que <code>guessField</code> contient maintenant une référence à un élément {{htmlelement ("input")}}, il aura maintenant accès à un certain nombre de propriétés (essentiellement des variables stockées dans des objets, dont certaines ne peuvent pas être modifiées) et des méthodes (essentiellement des fonctions stockées dans des objets). Une méthode disponible pour entrer des éléments est <code>focus()</code>, donc nous pouvons maintenant utiliser cette ligne pour focaliser l'entrée de texte :</p> +### Jouer avec les objets du navigateur -<pre class="brush: js">guessField.focus();</pre> +Jouons un peu avec certains objets du navigateur. -<p>Les variables qui ne contiennent pas de références aux éléments de formulaire n'auront pas de <code>focus()</code> à leur disposition. Par exemple, la variable <code>guesses</code> contient une référence à un élément {{htmlelement ("p")}} et <code>guessCount</code> contient un nombre.</p> +1. Tout d'abord, ouvrez votre programme dans un navigateur. +2. Ensuite, ouvrez les [outils de développement](/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs) de votre navigateur et assurez-vous que l'onglet de la console JavaScript est ouvert. +3. Tapez `guessField` et la console vous montrera que la variable contient un élément {{htmlelement ("input")}}. Vous remarquerez également que la console complète automatiquement les noms d'objets existant dans l'environnement d'exécution, y compris vos variables! +4. Maintenant, tapez ce qui suit : -<h3 id="Jouer_avec_les_objets_du_navigateur">Jouer avec les objets du navigateur</h3> + ```js + guessField.value = 'Hello'; + ``` -<p>Jouons un peu avec certains objets du navigateur.</p> + La propriété `value` représente la valeur courante entrée dans un champs de texte. Vous verrez qu'en entrant cette commande nous avons changé ce que c'est. -<ol> - <li> Tout d'abord, ouvrez votre programme dans un navigateur.</li> - <li> Ensuite, ouvrez les <a href="/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs">outils de développement</a> de votre navigateur et assurez-vous que l'onglet de la console JavaScript est ouvert.</li> - <li> Tapez <code>guessField</code> et la console vous montrera que la variable contient un élément {{htmlelement ("input")}}. Vous remarquerez également que la console complète automatiquement les noms d'objets existant dans l'environnement d'exécution, y compris vos variables!</li> - <li> - <p> Maintenant, tapez ce qui suit :</p> +5. Tapez maintenant `guesses` and appuyez sur entrée. La console vous montrera que la variable contient un élément {{htmlelement ("p")}}. +6. Maintenant, essayez d'entrer la ligne suivante : - <pre class="brush: js">guessField.value = 'Hello'; -</pre> + ```js + guesses.value + ``` - <p class="brush: js">La propriété <code>value</code> représente la valeur courante entrée dans un champs de texte. Vous verrez qu'en entrant cette commande nous avons changé ce que c'est.</p> - </li> - <li>Tapez maintenant <code>guesses</code> and appuyez sur entrée. La console vous montrera que la variable contient un élément {{htmlelement ("p")}}.</li> - <li> - <p>Maintenant, essayez d'entrer la ligne suivante :</p> + Le navigateur va retourner `undefined`, parce que `value` n'existe pas dans le paragraphe. - <pre class="brush: js">guesses.value -</pre> +7. Pour changer le texte dans le paragraphe vous aurez besoin de la propriété {{domxref("Node.textContent", "textContent")}} à la place. + Essayez ceci : - <p class="brush: js">Le navigateur va retourner <code>undefined</code>, parce que <code>value</code> n'existe pas dans le paragraphe.</p> - </li> - <li> - <p>Pour changer le texte dans le paragraphe vous aurez besoin de la propriété {{domxref("Node.textContent", "textContent")}} à la place.<br> - Essayez ceci :</p> + ```js + guesses.textContent = 'Where is my paragraph?'; + ``` - <pre class="brush: js">guesses.textContent = 'Where is my paragraph?'; -</pre> - </li> - <li>Maintenant, pour des trucs amusants. Essayez d'entrer les lignes ci-dessous, une par une :</li> -</ol> +8. Maintenant, pour des trucs amusants. Essayez d'entrer les lignes ci-dessous, une par une : -<pre class="brush: js">guesses.style.backgroundColor = 'yellow'; +```js +guesses.style.backgroundColor = 'yellow'; guesses.style.fontSize = '200%'; guesses.style.padding = '10px'; -guesses.style.boxShadow = '3px 3px 6px black';</pre> +guesses.style.boxShadow = '3px 3px 6px black'; +``` -<p>Chaque élément d'une page possède une propriété de <code>style</code> , qui contient elle-même un objet dont les propriétés contiennent tous les styles CSS en ligne appliqués à cet élément. Cela nous permet de définir dynamiquement de nouveaux styles CSS sur des éléments en utilisant JavaScript.</p> +Chaque élément d'une page possède une propriété de `style` , qui contient elle-même un objet dont les propriétés contiennent tous les styles CSS en ligne appliqués à cet élément. Cela nous permet de définir dynamiquement de nouveaux styles CSS sur des éléments en utilisant JavaScript. -<h2 id="Cest_fini_pour_le_moment...">C'est fini pour le moment...</h2> +## C'est fini pour le moment... -<p>Vous voilà parvenu au bout de cet exemple, bravo ! Essayez votre code enfin complété ou<a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/first-splash/number-guessing-game.html"> jouez avec notre version finale ici</a>. Si vous ne parvenez pas à faire fonctionner l'exemple, vérifiez-le par rapport <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html">au code source.</a></p> +Vous voilà parvenu au bout de cet exemple, bravo ! Essayez votre code enfin complété ou[ jouez avec notre version finale ici](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/first-splash/number-guessing-game.html). Si vous ne parvenez pas à faire fonctionner l'exemple, vérifiez-le par rapport [au code source.](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html) -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</p> +{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}} diff --git a/files/fr/learn/javascript/first_steps/arrays/index.md b/files/fr/learn/javascript/first_steps/arrays/index.md index b201776dd1..50bb6db903 100644 --- a/files/fr/learn/javascript/first_steps/arrays/index.md +++ b/files/fr/learn/javascript/first_steps/arrays/index.md @@ -18,39 +18,44 @@ tags: translation_of: Learn/JavaScript/First_steps/Arrays original_slug: Learn/JavaScript/First_steps/tableaux --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</div> - -<p>Dans le dernier article de ce module, nous examinerons les tableaux — une façon de stocker proprement une liste d'éléments de données sous un seul nom de variable. Ici nous verrons pourquoi c'est utile, puis nous apprendrons comment créer un tableau, y retrouver, y ajouter ou en enlever les éléments dedans, et quelques à‑côtés en bonus.</p> +Dans le dernier article de ce module, nous examinerons les tableaux — une façon de stocker proprement une liste d'éléments de données sous un seul nom de variable. Ici nous verrons pourquoi c'est utile, puis nous apprendrons comment créer un tableau, y retrouver, y ajouter ou en enlever les éléments dedans, et quelques à‑côtés en bonus. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Vocabulaire courant de l'informatique, bases de HTML et CSS, compréhension de ce que fait JavaScript.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre ce que sont les tableaux et savoir comment les manipuler en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Vocabulaire courant de l'informatique, bases de HTML et CSS, + compréhension de ce que fait JavaScript. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Comprendre ce que sont les tableaux et savoir comment les manipuler en + JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Quest‑ce_quun_tableau">Qu'est‑ce qu'un tableau ?</h2> +## Qu'est‑ce qu'un tableau ? -<p>Les tableaux sont généralement décrits comme des "objets de type liste" ; un tableau est un objet contenant plusieurs valeurs. Les objets tableau peuvent être stockés dans des variables et traités de la même manière que tout autre type de valeur, la différence étant que nous pouvons accéder à chaque valeur du tableau individuellement, et faire des choses super utiles et efficaces avec la liste des valeurs, comme boucler et faire la même chose pour chaque valeur. Peut-être que nous avons une série d'articles et leurs prix stockés dans un tableau, et nous voulons les parcourir tous et les imprimer sur une facture, tout en totalisant tous les prix ensemble et en imprimant le prix total en bas.</p> +Les tableaux sont généralement décrits comme des "objets de type liste" ; un tableau est un objet contenant plusieurs valeurs. Les objets tableau peuvent être stockés dans des variables et traités de la même manière que tout autre type de valeur, la différence étant que nous pouvons accéder à chaque valeur du tableau individuellement, et faire des choses super utiles et efficaces avec la liste des valeurs, comme boucler et faire la même chose pour chaque valeur. Peut-être que nous avons une série d'articles et leurs prix stockés dans un tableau, et nous voulons les parcourir tous et les imprimer sur une facture, tout en totalisant tous les prix ensemble et en imprimant le prix total en bas. -<p>Sans tableaux, nous devrions stocker chaque valeur dans une variable séparée, puis appeler le code qui effectue l'affichage ou l'impression, puis ajouter séparément chaque élément. Ce serait plus long à écrire, moins efficace et cela comporterait plus de risques d'erreurs. Si nous avions 10 articles à ajouter à la facture, ce serait déjà assez mauvais, mais qu'en serait-il de 100 articles ou de 1000 ? Nous reviendrons sur cet exemple plus loin dans l'article.</p> +Sans tableaux, nous devrions stocker chaque valeur dans une variable séparée, puis appeler le code qui effectue l'affichage ou l'impression, puis ajouter séparément chaque élément. Ce serait plus long à écrire, moins efficace et cela comporterait plus de risques d'erreurs. Si nous avions 10 articles à ajouter à la facture, ce serait déjà assez mauvais, mais qu'en serait-il de 100 articles ou de 1000 ? Nous reviendrons sur cet exemple plus loin dans l'article. -<p>Comme précédemment, initions‑nous aux bases pratiques des tableaux en entrant quelques exemples dans une console JavaScript. En voici une plus bas (vous pouvez aussi <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">ouvrir cette console</a> dans un onglet ou une fenêtre séparés ou utiliser la <a href="/fr/docs/Learn/Common_questions/What_are_browser_developer_tools">console développeur de l'explorateur</a> si vous préférez).</p> +Comme précédemment, initions‑nous aux bases pratiques des tableaux en entrant quelques exemples dans une console JavaScript. En voici une plus bas (vous pouvez aussi [ouvrir cette console](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html) dans un onglet ou une fenêtre séparés ou utiliser la [console développeur de l'explorateur](/fr/docs/Learn/Common_questions/What_are_browser_developer_tools) si vous préférez). -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>JavaScript console</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> * { box-sizing: border-box; } @@ -98,14 +103,14 @@ original_slug: Learn/JavaScript/First_steps/tableaux clear: both; } - </style> - </head> - <body> + </style> + </head> + <body> - </body> + </body> - <script> + <script> var geval = eval; function createInput() { var inputDiv = document.createElement('div'); @@ -113,12 +118,12 @@ original_slug: Learn/JavaScript/First_steps/tableaux var inputForm = document.createElement('input'); inputDiv.setAttribute('class','input'); - inputPara.textContent = '>'; + inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); - if(document.querySelectorAll('div').length > 1) { + if(document.querySelectorAll('div').length > 1) { inputForm.focus(); } @@ -148,181 +153,208 @@ original_slug: Learn/JavaScript/First_steps/tableaux createInput(); - </script> -</html></pre> + </script> +</html> +``` + +{{ EmbedLiveSample('Quest‑ce_quun_tableau', '100%', 300) }} + +### Créer un tableau + +On définit les valeurs d'un tableau par une liste d'éléments entre crochets droits, séparés par des virgules. + +1. Disons que nous voulons mettre une liste d'achats dans un tableau — nous devons opérer comme suit. Entrez les lignes ci‑après dans la console : + + ```js + let shopping = ['pain', 'lait', 'fromage', 'houmous', 'nouilles']; + shopping; + ``` + +2. Dans ce cas, chaque élément du tableau est une chaîne, mais gardez en tête que vous pouvez stocker n'importe quel élément dans un tableau — chaîne, nombre, objet, autre variable et même d'autres tableaux. Vous pouvez également mélanger et assortir les types d'articles — il n'est pas obligatoire que ce soient tous des nombres, des chaînes, etc. Essayez ceci : +3. ```js + let sequence = [1, 1, 2, 3, 5, 8, 13]; + let random = ['arbre', 795, [0, 1, 2]]; + ``` +4. Créez donc quelques tableaux de votre cru avant de continuer. -<p>{{ EmbedLiveSample('Quest‑ce_quun_tableau', '100%', 300) }}</p> +### Accès aux éléments de tableau et modification de ceux‑ci -<h3 id="Créer_un_tableau">Créer un tableau</h3> +Vous pouvez avoir accès isolément aux éléments dans un tableau en utilisant la notation crochet, de la même façon que nous avons eu [accès aux lettres dans une chaîne](/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods#retrieving_a_specific_string_character). -<p>On définit les valeurs d'un tableau par une liste d'éléments entre crochets droits, séparés par des virgules.</p> +1. Entrez ceci dans la console : -<ol> - <li>Disons que nous voulons mettre une liste d'achats dans un tableau — nous devons opérer comme suit. Entrez les lignes ci‑après dans la console : - <pre class="brush: js">let shopping = ['pain', 'lait', 'fromage', 'houmous', 'nouilles']; -shopping;</pre> - </li> - <li>Dans ce cas, chaque élément du tableau est une chaîne, mais gardez en tête que vous pouvez stocker n'importe quel élément dans un tableau — chaîne, nombre, objet, autre variable et même d'autres tableaux. Vous pouvez également mélanger et assortir les types d'articles — il n'est pas obligatoire que ce soient tous des nombres, des chaînes, etc. Essayez ceci :</li> - <li> - <pre class="brush: js">let sequence = [1, 1, 2, 3, 5, 8, 13]; -let random = ['arbre', 795, [0, 1, 2]];</pre> - </li> - <li>Créez donc quelques tableaux de votre cru avant de continuer.</li> -</ol> + ```js + shopping[0]; + // renvoie "pain" + ``` -<h3 id="Accès_aux_éléments_de_tableau_et_modification_de_ceux‑ci">Accès aux éléments de tableau et modification de ceux‑ci</h3> +2. Vous pouvez aussi modifier un élément dans un tableau en donnant simplement une nouvelle valeur à l'élément. Essayez ceci : -<p>Vous pouvez avoir accès isolément aux éléments dans un tableau en utilisant la notation crochet, de la même façon que nous avons eu <a href="/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods#retrieving_a_specific_string_character">accès aux lettres dans une chaîne</a>.</p> + ```js + shopping[0] = 'crème de sésame'; + shopping; + // shopping renvoie maintenant [ "crème de sésame", "lait", "fromage", "houmous", "nouilles" ] + ``` -<ol> - <li>Entrez ceci dans la console : - <pre class="brush: js">shopping[0]; -// renvoie "pain"</pre> - </li> - <li>Vous pouvez aussi modifier un élément dans un tableau en donnant simplement une nouvelle valeur à l'élément. Essayez ceci : - <pre class="brush: js">shopping[0] = 'crème de sésame'; -shopping; -// shopping renvoie maintenant [ "crème de sésame", "lait", "fromage", "houmous", "nouilles" ]</pre> + > **Note :** Nous l'avons déjà dit, mais enseigner c'est répéter — les ordinateurs commencent les décomptes à partir de 0 ! - <div class="note"> - <p><strong>Note :</strong> Nous l'avons déjà dit, mais enseigner c'est répéter — les ordinateurs commencent les décomptes à partir de 0 !</p></div> - </li> - <li>Notez qu'un tableau à l'intérieur d'un tableau est appelé un tableau multidimensionnel. Vous accédez à un des éléments de ce tableau interne en chaînant deux paires de crochets. Par exemple, pour avoir accès à l'un des éléments (le troisième) du tableau élément du tableau <code>random</code> (voir la section précédente), vous pouvez écrire quelque chose comme :</li> - <li> - <pre class="brush: js">random[2][2];</pre> - </li> - <li>Poursuivez et faites quelques autres modifications dans les exemples de tableaux avant de poursuivre.</li> -</ol> +3. Notez qu'un tableau à l'intérieur d'un tableau est appelé un tableau multidimensionnel. Vous accédez à un des éléments de ce tableau interne en chaînant deux paires de crochets. Par exemple, pour avoir accès à l'un des éléments (le troisième) du tableau élément du tableau `random` (voir la section précédente), vous pouvez écrire quelque chose comme : +4. ```js + random[2][2]; + ``` +5. Poursuivez et faites quelques autres modifications dans les exemples de tableaux avant de poursuivre. -<h3 id="Trouver_la_taille_dun_tableau">Trouver la taille d'un tableau</h3> +### Trouver la taille d'un tableau -<p>Vous pouvez trouver la taille d'un tableau (le nombre d'éléments qu'il comporte) de la même façon que vous obtenez la taille (en caractères) d'un chaîne — avec la propriété {{jsxref("Array.prototype.length","length")}}. Essayez :</p> +Vous pouvez trouver la taille d'un tableau (le nombre d'éléments qu'il comporte) de la même façon que vous obtenez la taille (en caractères) d'un chaîne — avec la propriété {{jsxref("Array.prototype.length","length")}}. Essayez : -<pre class="brush: js">sequence.length; -// renvoie 7</pre> +```js +sequence.length; +// renvoie 7 +``` -<p>Il y a d'autres usages, mais le plus courant permet de dire à une boucle de poursuivre jusqu'à ce que tous les éléments du tableau aient été passés en revue. Ainsi, par exemple :</p> +Il y a d'autres usages, mais le plus courant permet de dire à une boucle de poursuivre jusqu'à ce que tous les éléments du tableau aient été passés en revue. Ainsi, par exemple : -<pre class="brush: js">let sequence = [1, 1, 2, 3, 5, 8, 13]; -for (var i = 0; i < sequence.length; i++) { +```js +let sequence = [1, 1, 2, 3, 5, 8, 13]; +for (var i = 0; i < sequence.length; i++) { console.log(sequence[i]); -}</pre> +} +``` + +Vous en apprendrez plus sur les boucles dans un prochain article, mais, en résumé, ce code dit : + +1. Commencer la boucle à l'élément 0 du tableau. +2. Arrêter de tourner quand le dernier élément du tableau sera atteint. Cela fonctionne pour n'importe quelle dimension de tableau ; dans notre cas, on sortira de la boucle à l'élément 7 (c'est bon, car le dernier élément — que nous souhaitons que la boucle traite — est le 6). +3. Afficher chaque élément sur la console de l'explorateur avec` console.log()`. + +## Quelques méthodes utiles pour les tableaux + +Dans ce paragraphe nous examinerons quelques méthodes de tableaux à connaître. Elles permettent de scinder des chaînes en éléments de tableau et inversement, et d'ajouter de nouveaux éléments dans des tableaux. + +### Conversions entre chaînes et tableaux + +Souvent, vous serez confronté à des données brutes contenues dans une longue chaîne de caractères, et vous voudrez peut-être en extraire les éléments utiles sous une forme plus pratique pour en faire quelque chose, comme les afficher dans un tableau de données. Pour ce faire, nous pouvons utiliser la méthode {{jsxref ("String. prototype. prototype. split ()","split ()")}}. Dans sa formulation la plus simple, elle prend un seul paramètre, le caractère servant de séparateur ; elle renverra les sous-chaînes entre séparateurs en tant qu'éléments d'un tableau. + +> **Note :** D'accord, techniquement parlant c'est une méthode de chaîne, et non une méthode de tableau, mais nous la mettons dans le chapitre des tableaux car elle est bien à sa place ici. + +1. Servons‑nous en et voyons comment elle fonctionne. D'abord créons une chaîne dans la console : + + ```js + let myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle'; + ``` + +2. Scindons‑la à chaque virgule : + + ```js + let myArray = myData.split(','); + myArray; + ``` + +3. Pour terminer, trouvons la taille du nouveau tableau et retrouvons quelques‑uns de ses éléments : + + ```js + myArray.length; + myArray[0]; // le premier élément du tableau + myArray[1]; // le deuxième élément du tableau + myArray[myArray.length-1]; // le dernier élément du tableau + ``` + +4. Vous pouvez également faire le contraire avec la méthode {{jsxref("Array.prototype.join()","join()")}}. Essayons : + + ```js + let myNewString = myArray.join(','); + myNewString; + ``` + +5. Une autre façon de convertir un tableau en chaîne consiste à se servir de la méthode {{jsxref("Array.prototype.toString()","toString()")}}. `toString()` est plus simple au plan des arguments que `join()`, car elle ne prend pas de paramètre, mais elle est plus limitée. Avec `join()` vous pouvez diversifier les séparateurs (essayez de lancer la commande du point 4 avec un caractère autre que la virgule). + + ```js + let dogNames = ["Rocket","Flash","Bella","Slugger"]; + dogNames.toString(); //Rocket,Flash,Bella,Slugger + ``` + +### Ajout et suppression d'éléments de tableau + +Nous n'avons pas encore parlé d'ajout et de suppression d'éléments de tableau — allons‑y. Nous utiliserons le tableau `myArray` dont nous nous sommes servis à la fin de la dernière section. Si vous n'avez pas entré les commandes de cette section dans la console, il est nécessaire de créer d'abord le tableau : + +```js +let myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle']; +``` -<p>Vous en apprendrez plus sur les boucles dans un prochain article, mais, en résumé, ce code dit :</p> +Premièrement, pour ajouter ou supprimer un élément à la fin du tableau, vous pouvez respectivement utiliser {{jsxref("Array.prototype.push()","push()")}} et {{jsxref("Array.prototype.pop()","pop()")}}. -<ol> - <li>Commencer la boucle à l'élément 0 du tableau.</li> - <li>Arrêter de tourner quand le dernier élément du tableau sera atteint. Cela fonctionne pour n'importe quelle dimension de tableau ; dans notre cas, on sortira de la boucle à l'élément 7 (c'est bon, car le dernier élément — que nous souhaitons que la boucle traite — est le 6).</li> - <li>Afficher chaque élément sur la console de l'explorateur avec<code> <a href="/fr/docs/Web/API/Console/log">console.log()</a></code>.</li> -</ol> +1. Voyons `push()` d'abord — notez que vous devez mettre en paramètre les éléments que vous souhaitez ajouter à la fin du tableau. Essayez ceci : -<h2 id="Quelques_méthodes_utiles_pour_les_tableaux">Quelques méthodes utiles pour les tableaux</h2> + ```js + myArray.push('Cardiff'); + myArray; + myArray.push('Bradford', 'Brighton'); + myArray; + ``` -<p>Dans ce paragraphe nous examinerons quelques méthodes de tableaux à connaître. Elles permettent de scinder des chaînes en éléments de tableau et inversement, et d'ajouter de nouveaux éléments dans des tableaux.</p> +2. La taille du tableau modifié est renvoyée quand l'appel de la méthode est terminé. Si vous voulez enregistrer la taille du nouveau tableau dans une variable, vous pouvez écrire quelque chose comme ceci : -<h3 id="Conversions_entre_chaînes_et_tableaux">Conversions entre chaînes et tableaux</h3> + ```js + let newLength = myArray.push('Bristol'); + myArray; + newLength; + ``` -<p>Souvent, vous serez confronté à des données brutes contenues dans une longue chaîne de caractères, et vous voudrez peut-être en extraire les éléments utiles sous une forme plus pratique pour en faire quelque chose, comme les afficher dans un tableau de données. Pour ce faire, nous pouvons utiliser la méthode {{jsxref ("String. prototype. prototype. split ()","split ()")}}. Dans sa formulation la plus simple, elle prend un seul paramètre, le caractère servant de séparateur ; elle renverra les sous-chaînes entre séparateurs en tant qu'éléments d'un tableau.</p> +3. Supprimer le dernier élément de la liste est très simple : il suffit de lancer `pop()` sur celle‑ci. Essayez : + + ```js + myArray.pop(); + ``` + +4. L'élément supprimé est renvoyé à la fin de l'appel de la méthode. Également : + + ```js + let removedItem = myArray.pop(); + myArray; + removedItem; + ``` + +{{jsxref("Array.prototype.unshift()","unshift()")}} et {{jsxref("Array.prototype.shift()","shift()")}} fonctionnent exactement de la même manière, excepté qu'il travaillent sur la tête du tableau au lieu de la queue. + +1. D'abord `unshift()` — essayez : + + ```js + myArray.unshift('Edinburgh'); + myArray; + ``` + +2. Maintenant `shift()` — essayez ! + + ```js + let removedItem = myArray.shift(); + myArray; + removedItem; + ``` + +## Activité : affichons les produits + +Revenons à l'exemple que nous avons décrit plus haut — afficher les noms des produits et leurs prix pour un envoi, puis faire le total des prix et l'afficher à la fin de la liste. Dans l'exemple modifiable ci‑dessous, il y a des commentaires numérotés — chacun d'entre eux marque l'emplacement où vous devez ajouter quelque chose au code. Voici : + +1. Sous le commentaire `// number 1` il y a un certain nombre de chaînes de caractères, chacune précise le nom d'un produit et son prix séparé par deux‑points. Placez‑les dans un tableau ; enregistrez‑le sous le nom `products`. +2. Sur la même ligne que le commentaire `// number 2` se trouve le début d'une boucle. Dans cette ligne nous avons actuellement `i <= 0`, test conditionnel qui fait que la [ boucle](/fr/docs/Learn/JavaScript/First_steps/A_first_splash#loops) stoppe immédiatement, car ce test dit « stopper dès que `i` est inférieur ou égal à 0 » et `i` part de 0. Remplacez ce test par un qui n'arrêtera pas la boucle tant que `i` sera inférieur à la taille du tableau `products`. +3. Au dessous du commentaire `// number 3` nous voudrions que vous écriviez une ligne de code qui scinde l'élément courant du tableau (`nom:prix`) en deux éléments distincts, un contenant uniquement le nom, l'autre uniquement le prix. Si vous nous ne savez pas trop comment faire, revoyez l'article relatif aux [Méthodes utiles pour les chaînes de caractères](/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods) pour vous aider, ou même mieux, regardez la section {{anch("Converting between strings and arrays")}} de cet article. +4. En plus des lignes de code ci‑dessus, vous aurez aussi à convertir les prix de chaîne de caractères en chiffres. Si vous ne vous souvenez pas comment faire, revoyez le [premier article à propos des chaînes](/fr/docs/Learn/JavaScript/First_steps/Strings#numbers_versus_strings). +5. Il y a une variable nommée `total` créée et initialisée à la valeur de 0 en tête du code. Dans la boucle (sous `// number 4`) ajoutez une ligne qui ajoute à ce total le prix de l'article courant à chaque itération de la boucle, de sorte que à la fin du code le prix total soit correctement inscrit sur l'envoi. Vous pourriez avoir besoin d'un [opérateur d'assignation](/fr/docs/Learn/JavaScript/First_steps/Math#assignment_operators) pour faire cela ;-). +6. Nous souhaitons que vous modifiez la ligne au‑dessous de `// number 5` de sorte que la variable `itemText` soit égale à « nom actuel de l'élément — $prix actuel de l'élément », par exemple « Shoes — $23.99 » dans chaque cas, de façon à ce qu'une information correcte soit affichée sur l'envoi. Il s'agit d'une simple concaténation de chaînes de caractères, chose qui doit vous être familière. + +```html hidden +<div class="output" style="min-height: 150px;"> + +<ul> + +</ul> + +<p></p> -<div class="note"> -<p><strong>Note :</strong> D'accord, techniquement parlant c'est une méthode de chaîne, et non une méthode de tableau, mais nous la mettons dans le chapitre des tableaux car elle est bien à sa place ici.</p> </div> -<ol> - <li>Servons‑nous en et voyons comment elle fonctionne. D'abord créons une chaîne dans la console : - <pre class="brush: js">let myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';</pre> - </li> - <li>Scindons‑la à chaque virgule : - <pre class="brush: js">let myArray = myData.split(','); -myArray;</pre> - </li> - <li>Pour terminer, trouvons la taille du nouveau tableau et retrouvons quelques‑uns de ses éléments : - <pre class="brush: js">myArray.length; -myArray[0]; // le premier élément du tableau -myArray[1]; // le deuxième élément du tableau -myArray[myArray.length-1]; // le dernier élément du tableau</pre> - </li> - <li>Vous pouvez également faire le contraire avec la méthode {{jsxref("Array.prototype.join()","join()")}}. Essayons : - <pre class="brush: js">let myNewString = myArray.join(','); -myNewString;</pre> - </li> - <li>Une autre façon de convertir un tableau en chaîne consiste à se servir de la méthode {{jsxref("Array.prototype.toString()","toString()")}}. <code>toString()</code> est plus simple au plan des arguments que <code>join()</code>, car elle ne prend pas de paramètre, mais elle est plus limitée. Avec <code>join()</code> vous pouvez diversifier les séparateurs (essayez de lancer la commande du point 4 avec un caractère autre que la virgule). - <pre class="brush: js">let dogNames = ["Rocket","Flash","Bella","Slugger"]; -dogNames.toString(); //Rocket,Flash,Bella,Slugger</pre> - </li> -</ol> - -<h3 id="Ajout_et_suppression_déléments_de_tableau">Ajout et suppression d'éléments de tableau</h3> - -<p>Nous n'avons pas encore parlé d'ajout et de suppression d'éléments de tableau — allons‑y. Nous utiliserons le tableau <code>myArray</code> dont nous nous sommes servis à la fin de la dernière section. Si vous n'avez pas entré les commandes de cette section dans la console, il est nécessaire de créer d'abord le tableau :</p> - -<pre class="brush: js">let myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle'];</pre> - -<p>Premièrement, pour ajouter ou supprimer un élément à la fin du tableau, vous pouvez respectivement utiliser {{jsxref("Array.prototype.push()","push()")}} et {{jsxref("Array.prototype.pop()","pop()")}}.</p> - -<ol> - <li>Voyons <code>push()</code> d'abord — notez que vous devez mettre en paramètre les éléments que vous souhaitez ajouter à la fin du tableau. Essayez ceci : - - <pre class="brush: js">myArray.push('Cardiff'); -myArray; -myArray.push('Bradford', 'Brighton'); -myArray; -</pre> - </li> - <li>La taille du tableau modifié est renvoyée quand l'appel de la méthode est terminé. Si vous voulez enregistrer la taille du nouveau tableau dans une variable, vous pouvez écrire quelque chose comme ceci : - <pre class="brush: js">let newLength = myArray.push('Bristol'); -myArray; -newLength;</pre> - </li> - <li>Supprimer le dernier élément de la liste est très simple : il suffit de lancer <code>pop()</code> sur celle‑ci. Essayez : - <pre class="brush: js">myArray.pop();</pre> - </li> - <li>L'élément supprimé est renvoyé à la fin de l'appel de la méthode. Également : - <pre class="brush: js">let removedItem = myArray.pop(); -myArray; -removedItem;</pre> - </li> -</ol> - -<p>{{jsxref("Array.prototype.unshift()","unshift()")}} et {{jsxref("Array.prototype.shift()","shift()")}} fonctionnent exactement de la même manière, excepté qu'il travaillent sur la tête du tableau au lieu de la queue.</p> - -<ol> - <li>D'abord <code>unshift()</code> — essayez : - - <pre class="brush: js">myArray.unshift('Edinburgh'); -myArray;</pre> - </li> - <li>Maintenant <code>shift()</code> — essayez ! - <pre class="brush: js">let removedItem = myArray.shift(); -myArray; -removedItem;</pre> - </li> -</ol> - -<h2 id="Activité_affichons_les_produits">Activité : affichons les produits</h2> - -<p>Revenons à l'exemple que nous avons décrit plus haut — afficher les noms des produits et leurs prix pour un envoi, puis faire le total des prix et l'afficher à la fin de la liste. Dans l'exemple modifiable ci‑dessous, il y a des commentaires numérotés — chacun d'entre eux marque l'emplacement où vous devez ajouter quelque chose au code. Voici :</p> - -<ol> - <li>Sous le commentaire <code>// number 1</code> il y a un certain nombre de chaînes de caractères, chacune précise le nom d'un produit et son prix séparé par deux‑points. Placez‑les dans un tableau ; enregistrez‑le sous le nom <code>products</code>.</li> - <li>Sur la même ligne que le commentaire <code>// number 2</code> se trouve le début d'une boucle. Dans cette ligne nous avons actuellement <code>i <= 0</code>, test conditionnel qui fait que la <a href="/fr/docs/Learn/JavaScript/First_steps/A_first_splash#loops"> boucle</a> stoppe immédiatement, car ce test dit « stopper dès que <code>i</code> est inférieur ou égal à 0 » et <code>i</code> part de 0. Remplacez ce test par un qui n'arrêtera pas la boucle tant que <code>i</code> sera inférieur à la taille du tableau <code>products</code>.</li> - <li>Au dessous du commentaire <code>// number 3</code> nous voudrions que vous écriviez une ligne de code qui scinde l'élément courant du tableau (<code>nom:prix</code>) en deux éléments distincts, un contenant uniquement le nom, l'autre uniquement le prix. Si vous nous ne savez pas trop comment faire, revoyez l'article relatif aux <a href="/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods">Méthodes utiles pour les chaînes de caractères</a> pour vous aider, ou même mieux, regardez la section {{anch("Converting between strings and arrays")}} de cet article.</li> - <li>En plus des lignes de code ci‑dessus, vous aurez aussi à convertir les prix de chaîne de caractères en chiffres. Si vous ne vous souvenez pas comment faire, revoyez le <a href="/fr/docs/Learn/JavaScript/First_steps/Strings#numbers_versus_strings">premier article à propos des chaînes</a>.</li> - <li>Il y a une variable nommée <code>total</code> créée et initialisée à la valeur de 0 en tête du code. Dans la boucle (sous <code>// number 4</code>) ajoutez une ligne qui ajoute à ce total le prix de l'article courant à chaque itération de la boucle, de sorte que à la fin du code le prix total soit correctement inscrit sur l'envoi. Vous pourriez avoir besoin d'un <a href="/fr/docs/Learn/JavaScript/First_steps/Math#assignment_operators">opérateur d'assignation</a> pour faire cela ;-).</li> - <li>Nous souhaitons que vous modifiez la ligne au‑dessous de <code>// number 5</code> de sorte que la variable <code>itemText</code> soit égale à « nom actuel de l'élément — $prix actuel de l'élément », par exemple « Shoes — $23.99 » dans chaque cas, de façon à ce qu'une information correcte soit affichée sur l'envoi. Il s'agit d'une simple concaténation de chaînes de caractères, chose qui doit vous être familière.</li> -</ol> - -<pre class="brush: html hidden"><div class="output" style="min-height: 150px;"> - -<ul> - -</ul> - -<p></p> - -</div> - -<textarea id="code" class="playable-code" style="height: 370px;"> +<textarea id="code" class="playable-code" style="height: 370px;"> var list = document.querySelector('.output ul'); var totalBox = document.querySelector('.output p'); var total = 0; @@ -335,7 +367,7 @@ totalBox.textContent = ''; 'Pantalons:31.99' 'Chaussures:23.99'; -for (var i = 0; i <= 0; i++) { // number 2 +for (var i = 0; i <= 0; i++) { // number 2 // number 3 // number 4 @@ -349,15 +381,16 @@ for (var i = 0; i <= 0; i++) { // number 2 } totalBox.textContent = 'Total: $' + total.toFixed(2); -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: js hidden">var textarea = document.getElementById('code'); +```js hidden +var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; @@ -376,42 +409,39 @@ solution.addEventListener('click', function() { updateCode(); }); -var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar totalBox = document.querySelector(\'.output p\');\nvar total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nvar products = [\'Underpants:6.99\',\n \'Socks:5.99\',\n \'T-shirt:14.99\',\n \'Trousers:31.99\',\n \'Shoes:23.99\'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(\':\');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'Total: $\' + total.toFixed(2);'; +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar totalBox = document.querySelector(\'.output p\');\nvar total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nvar products = [\'Underpants:6.99\',\n \'Socks:5.99\',\n \'T-shirt:14.99\',\n \'Trousers:31.99\',\n \'Shoes:23.99\'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(\':\');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'Total: $\' + total.toFixed(2);'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Activité_affichons_les_produits', '100%', 600) }}</p> +{{ EmbedLiveSample('Activité_affichons_les_produits', '100%', 600) }} -<h2 id="Activité_Top_5_des_recherches">Activité : Top 5 des recherches</h2> +## Activité : Top 5 des recherches -<p>Une bonne utilisation des méthodes de tableaux comme {{jsxref("Array.prototype.push()","push()")}} et {{jsxref("Array.prototype.pop()","pop()")}} permet de conserver un enregistrement des éléments actuellement actifs dans une application web. Dans une scène animée, par exemple, vous pouvez avoir un tableau d'objets représentant les graphiques d'arrière-plan actuellement affichés, et vous pouvez n'en vouloir que 50 à la fois, pour des raisons de performance ou d'encombrement. Chaque fois que de nouveaux objets sont créés et ajoutés au tableau, les plus anciens peuvent être supprimés du tableau pour n'en conserver que le nombre voulu.</p> +Une bonne utilisation des méthodes de tableaux comme {{jsxref("Array.prototype.push()","push()")}} et {{jsxref("Array.prototype.pop()","pop()")}} permet de conserver un enregistrement des éléments actuellement actifs dans une application web. Dans une scène animée, par exemple, vous pouvez avoir un tableau d'objets représentant les graphiques d'arrière-plan actuellement affichés, et vous pouvez n'en vouloir que 50 à la fois, pour des raisons de performance ou d'encombrement. Chaque fois que de nouveaux objets sont créés et ajoutés au tableau, les plus anciens peuvent être supprimés du tableau pour n'en conserver que le nombre voulu. -<p>Dans cet exemple nous allons montrer une utilisation beaucoup plus simple — ici, nous allons vous fournir un site de recherche fictif, avec une boîte de recherche. Voici l'idée : quand un terme est entré dans la boîte de recherche, les 5 précédents termes entrés sont affichés dans la liste. Quand le nombre de termes dépasse 5, le dernier terme est supprimé chaque fois qu'un nouveau terme est ajouté ; ainsi, le 5 termes précédents sont toujours affichés.</p> +Dans cet exemple nous allons montrer une utilisation beaucoup plus simple — ici, nous allons vous fournir un site de recherche fictif, avec une boîte de recherche. Voici l'idée : quand un terme est entré dans la boîte de recherche, les 5 précédents termes entrés sont affichés dans la liste. Quand le nombre de termes dépasse 5, le dernier terme est supprimé chaque fois qu'un nouveau terme est ajouté ; ainsi, le 5 termes précédents sont toujours affichés. -<div class="note"> -<p><strong>Note :</strong> Dans une application réelle avec boîte de recherche, vous pourriez vraisemblablement cliquer sur un des termes de la liste pour revenir à la recherche précédente, et l'application afficherait les vrais résultats ! Mais pour le moment nous en resterons à quelque chose de simple.</p> -</div> +> **Note :** Dans une application réelle avec boîte de recherche, vous pourriez vraisemblablement cliquer sur un des termes de la liste pour revenir à la recherche précédente, et l'application afficherait les vrais résultats ! Mais pour le moment nous en resterons à quelque chose de simple. -<p>Pour terminer l'application, il vous faut :</p> +Pour terminer l'application, il vous faut : -<ol> - <li>Ajouter une ligne sous le commentaire <code>// number 1</code> pour ajouter la valeur qui vient d'être saisie dans la boîte au début du tableau. Cette valeur est récupérée avec <code>searchInput.value</code>.</li> - <li>Ajouter une ligne sous le commentaire <code>// number 2</code> pour supprimer la valeur en fin de liste du tableau.</li> -</ol> +1. Ajouter une ligne sous le commentaire `// number 1` pour ajouter la valeur qui vient d'être saisie dans la boîte au début du tableau. Cette valeur est récupérée avec `searchInput.value`. +2. Ajouter une ligne sous le commentaire `// number 2` pour supprimer la valeur en fin de liste du tableau. -<pre class="brush: html hidden"><div class="output" style="min-height: 150px;"> +```html hidden +<div class="output" style="min-height: 150px;"> -<input type="text"><button>Search</button> +<input type="text"><button>Search</button> -<ul> +<ul> -</ul> +</ul> -</div> +</div> -<textarea id="code" class="playable-code" style="height: 370px;"> +<textarea id="code" class="playable-code" style="height: 370px;"> var list = document.querySelector('.output ul'); var searchInput = document.querySelector('.output input'); var searchBtn = document.querySelector('.output button'); @@ -430,7 +460,7 @@ searchBtn.onclick = function() { list.innerHTML = ''; // loop through the array, and display all the search terms in the list - for (var i = 0; i < myHistory.length; i++) { + for (var i = 0; i < myHistory.length; i++) { itemText = myHistory[i]; var listItem = document.createElement('li'); listItem.textContent = itemText; @@ -438,7 +468,7 @@ searchBtn.onclick = function() { } // If the array length is 5 or more, remove the oldest search term - if (myHistory.length >= 5) { + if (myHistory.length >= 5) { // number 2 } @@ -448,15 +478,16 @@ searchBtn.onclick = function() { searchInput.focus(); } } -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: js hidden">var textarea = document.getElementById('code'); +```js hidden +var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; @@ -475,43 +506,39 @@ solution.addEventListener('click', function() { updateCode(); }); -var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar searchInput = document.querySelector(\'.output input\');\nvar searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar searchInput = document.querySelector(\'.output input\');\nvar searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Activité_Top_5_des_recherches', '100%', 600) }}</p> +{{ EmbedLiveSample('Activité_Top_5_des_recherches', '100%', 600) }} -<h2 id="Testez_vos_compétences_!">Testez vos compétences !</h2> +## Testez vos compétences ! -<p>Vous avez atteint la fin de cet article, mais vous souvenez-vous des informations les plus importantes ? Vous pouvez trouver d'autres tests pour vérifier que vous avez bien fixé ces connaissances avant de continuer — voir <a href="/fr/docs/Learn/JavaScript/First_steps/Test_your_skills:_Arrays">Test de compétences : les tableaux</a>.</p> +Vous avez atteint la fin de cet article, mais vous souvenez-vous des informations les plus importantes ? Vous pouvez trouver d'autres tests pour vérifier que vous avez bien fixé ces connaissances avant de continuer — voir [Test de compétences : les tableaux](/fr/docs/Learn/JavaScript/First_steps/Test_your_skills:_Arrays). -<h2 id="Conclusion">Conclusion</h2> +## Conclusion -<p>Après la lecture de cet article, vous conviendrez que les tableaux semblent fichtrement utiles ; vous les verrez un peu partout en JavaScript, souvent associés à des boucles pour appliquer la même action à chaque élément du tableau. Nous vous indiquerons toutes les bases utiles à savoir à propos des boucles dans le prochain module, mais pour l'instant, félicitations : prenez une pause bien méritée ; vous avez étudié tous les articles du module !</p> +Après la lecture de cet article, vous conviendrez que les tableaux semblent fichtrement utiles ; vous les verrez un peu partout en JavaScript, souvent associés à des boucles pour appliquer la même action à chaque élément du tableau. Nous vous indiquerons toutes les bases utiles à savoir à propos des boucles dans le prochain module, mais pour l'instant, félicitations : prenez une pause bien méritée ; vous avez étudié tous les articles du module ! -<p>La seule chose restant à faire est de procéder à l'évaluation de ce module pour tester votre compréhension de son contenu.</p> +La seule chose restant à faire est de procéder à l'évaluation de ce module pour tester votre compréhension de son contenu. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/JavaScript/Guide/Indexed_collections">Collections indexées</a> — un guide de niveau avancé à propos des tableaux et de leurs cousins, les tableaux typés.</li> - <li>{{jsxref("Array")}} — la page de référence de l'objet <code>Array</code> — pour un guide de référence détaillé à propos des fonctionnalités discutées dans cette page, et plus encore.</li> -</ul> +- [Collections indexées](/fr/docs/Web/JavaScript/Guide/Indexed_collections) — un guide de niveau avancé à propos des tableaux et de leurs cousins, les tableaux typés. +- {{jsxref("Array")}} — la page de référence de l'objet `Array` — pour un guide de référence détaillé à propos des fonctionnalités discutées dans cette page, et plus encore. -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</p> +{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}} -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript">What is JavaScript?</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/A_first_splash">A first splash into JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Variables">Storing the information you need — Variables</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Math">Basic math in JavaScript — numbers and operators</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Strings">Handling text — strings in JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator">Assessment: Silly story generator</a></li> -</ul> +- [What is JavaScript?](/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript) +- [A first splash into JavaScript](/fr/docs/Learn/JavaScript/First_steps/A_first_splash) +- [What went wrong? Troubleshooting JavaScript](/fr/docs/Learn/JavaScript/First_steps/What_went_wrong) +- [Storing the information you need — Variables](/fr/docs/Learn/JavaScript/First_steps/Variables) +- [Basic math in JavaScript — numbers and operators](/fr/docs/Learn/JavaScript/First_steps/Math) +- [Handling text — strings in JavaScript](/fr/docs/Learn/JavaScript/First_steps/Strings) +- [Useful string methods](/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods) +- [Arrays](/fr/docs/Learn/JavaScript/First_steps/Arrays) +- [Assessment: Silly story generator](/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator) diff --git a/files/fr/learn/javascript/first_steps/index.md b/files/fr/learn/javascript/first_steps/index.md index 8e093bebfb..03d1d7d9e4 100644 --- a/files/fr/learn/javascript/first_steps/index.md +++ b/files/fr/learn/javascript/first_steps/index.md @@ -15,56 +15,42 @@ tags: - Variables translation_of: Learn/JavaScript/First_steps --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}} -<p>Dans notre premier module consacré à JavaScript, nous allons tout d'abord répondre à des questions fondamentales comme « qu'est-ce que JavaScript ? », « à quoi ressemble-t-il ? » et « de quoi est-il capable ? ». Nous vous accompagnerons ensuite dans votre première expérience pratique consistant à écrire du code JavaScript. Après cela, nous examinerons en détail quelques briques de base, telles que les variables, les chaînes de caractères, les nombres, et les tableaux.</p> +Dans notre premier module consacré à JavaScript, nous allons tout d'abord répondre à des questions fondamentales comme « qu'est-ce que JavaScript ? », « à quoi ressemble-t-il ? » et « de quoi est-il capable ? ». Nous vous accompagnerons ensuite dans votre première expérience pratique consistant à écrire du code JavaScript. Après cela, nous examinerons en détail quelques briques de base, telles que les variables, les chaînes de caractères, les nombres, et les tableaux. -<h2 id="Prérequis"><strong>Prérequis</strong></h2> +## **Prérequis** -<p>Avant d'entamer ce module, vous n'avez besoin d'aucune connaissance préalable en JavaScript, mais vous devriez être familier avec HTML et CSS. Nous vous conseillons de lire les modules suivants avant d'aller plus loin :</p> +Avant d'entamer ce module, vous n'avez besoin d'aucune connaissance préalable en JavaScript, mais vous devriez être familier avec HTML et CSS. Nous vous conseillons de lire les modules suivants avant d'aller plus loin : -<ul> - <li><a href="/fr/Apprendre/HTML/Introduction_%C3%A0_HTML">Commencer avec le Web</a> (qui inclut une <a href="/fr/docs/Learn/Getting_started_with_the_web/JavaScript_basics">présentation basique de JavaScript</a>).</li> - <li><a href="/fr/docs/Web/Guide/HTML/Introduction">Introduction au langage HTML</a>.</li> - <li><a href="/fr/Apprendre/CSS/Introduction_%C3%A0_CSS">Introduction au langage CSS</a>.</li> -</ul> +- [Commencer avec le Web](/fr/Apprendre/HTML/Introduction_%C3%A0_HTML) (qui inclut une [présentation basique de JavaScript](/fr/docs/Learn/Getting_started_with_the_web/JavaScript_basics)). +- [Introduction au langage HTML](/fr/docs/Web/Guide/HTML/Introduction). +- [Introduction au langage CSS](/fr/Apprendre/CSS/Introduction_%C3%A0_CSS). -<div class="note"> -<p><strong>Note :</strong> Si vous travaillez depuis un ordinateur, une tablette ou depuis un autre appareil sur lequel vous ne pouvez pas créer vos propres fichiers, vous pourrez tester la plupart des exemples en ligne grâce à des outils comme <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> -</div> +> **Note :** Si vous travaillez depuis un ordinateur, une tablette ou depuis un autre appareil sur lequel vous ne pouvez pas créer vos propres fichiers, vous pourrez tester la plupart des exemples en ligne grâce à des outils comme [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/). -<h2 id="Guides">Guides</h2> +## Guides -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript">Qu'est-ce que JavaScript ?</a></dt> - <dd>Bienvenue dans le cours de JavaScript pour débutants proposé par MDN ! Dans ce premier article, nous aborderons JavaScript sous un angle général afin de comprendre ce qu'il est et à quoi il sert. Nous nous assurerons ici que vous cernez bien le but premier du langage.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/A_first_splash">Notre premier code JavaScript</a></dt> - <dd> - <p>Maintenant que vous en savez un peu plus sur la partie théorique de JavaScript et sur ce que vous pouvez réaliser avec, nous allons poursuivre avec un cours accéléré sur les fonctionnalités de base du langage par le biais d'un tutoriel axé sur la pratique. Vous développerez ici, pas à pas, un jeu simple consistant à faire deviner un nombre.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/What_went_wrong">Qu'est-ce qui n'a pas fonctionné ? Déboguer du code JavaScript</a></dt> - <dd> - <p>Quand vous développiez le jeu de devinette dans le cadre du tutoriel précédent, vous avez pu constater que notre programme ne fonctionnait pas. Pas de panique — cet article est là pour vous éviter de vous arracher les cheveux sur de tels problèmes en vous donnant quelques conseils simples sur la manière de trouver et résoudre les erreurs dans vos programmes JavaScript.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/Variables">Stocker les informations dont vous avez besoin — les variables</a></dt> - <dd> - <p>Après avoir lu les articles précédents, vous devriez maintenant mieux comprendre ce qu'est JavaScript, ce qu'il peut faire pour vous, comment l'utiliser de pair avec d'autres technologies du Web, et à quoi ressemblent ses principales fonctionnalités d'un point de vue global. Dans cet article, nous allons aborder les véritables fondements, en présentant l'une des pierres angulaires du langage : les variables.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/Math">Mathématiques de base en JavaScript — nombres et opérateurs</a></dt> - <dd>À ce stade du cours, nous allons parler de mathématiques en JavaScript, à savoir comment combiner des opérateurs arithmétiques avec d'autres fonctionnalités du langage pour arriver à nos fins.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/Strings">Gérer du texte — les chaînes de caractères en JavaScript</a></dt> - <dd>Attaquons-nous maintenant aux chaînes de caractères — le nom savant désignant en programmation des portions de texte. Dans cet article, nous allons voir les bases que vous devez impérativement connaître lors de votre apprentissage de JavaScript, comme la création de chaînes, l'échappement de caractères et la jonction de plusieurs chaînes.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/methode_chaine_utile">Méthodes utiles pour les chaînes de caractères</a></dt> - <dd>Maintenant que nous avons vu les bases relatives aux chaînes de catactères, passons à la vitesse supérieure et regardons ce que nous pouvons faire de plus poussé avec lesdites chaînes grâce aux méthodes natives, comme par exemple déterminer la longueur d'un texte, joindre et séparer des chaînes, remplacer un caractère par un autre, et bien plus encore.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/tableaux">Les tableaux</a></dt> - <dd>Dans le dernier article de ce module, nous allons nous pencher sur les tableaux — un moyen ingénieux de stocker une liste d'éléments dans une unique variable. Ici nous allons voir en quoi cela est pratique, puis nous verrons entre autres comment créer un tableau et comment récupérer, ajouter et supprimer des éléments stockés.</dd> -</dl> +- [Qu'est-ce que JavaScript ?](/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript) + - : Bienvenue dans le cours de JavaScript pour débutants proposé par MDN ! Dans ce premier article, nous aborderons JavaScript sous un angle général afin de comprendre ce qu'il est et à quoi il sert. Nous nous assurerons ici que vous cernez bien le but premier du langage. +- [Notre premier code JavaScript](/fr/docs/Learn/JavaScript/First_steps/A_first_splash) + - : Maintenant que vous en savez un peu plus sur la partie théorique de JavaScript et sur ce que vous pouvez réaliser avec, nous allons poursuivre avec un cours accéléré sur les fonctionnalités de base du langage par le biais d'un tutoriel axé sur la pratique. Vous développerez ici, pas à pas, un jeu simple consistant à faire deviner un nombre. +- [Qu'est-ce qui n'a pas fonctionné ? Déboguer du code JavaScript](/fr/docs/Learn/JavaScript/First_steps/What_went_wrong) + - : Quand vous développiez le jeu de devinette dans le cadre du tutoriel précédent, vous avez pu constater que notre programme ne fonctionnait pas. Pas de panique — cet article est là pour vous éviter de vous arracher les cheveux sur de tels problèmes en vous donnant quelques conseils simples sur la manière de trouver et résoudre les erreurs dans vos programmes JavaScript. +- [Stocker les informations dont vous avez besoin — les variables](/fr/docs/Learn/JavaScript/First_steps/Variables) + - : Après avoir lu les articles précédents, vous devriez maintenant mieux comprendre ce qu'est JavaScript, ce qu'il peut faire pour vous, comment l'utiliser de pair avec d'autres technologies du Web, et à quoi ressemblent ses principales fonctionnalités d'un point de vue global. Dans cet article, nous allons aborder les véritables fondements, en présentant l'une des pierres angulaires du langage : les variables. +- [Mathématiques de base en JavaScript — nombres et opérateurs](/fr/docs/Learn/JavaScript/First_steps/Math) + - : À ce stade du cours, nous allons parler de mathématiques en JavaScript, à savoir comment combiner des opérateurs arithmétiques avec d'autres fonctionnalités du langage pour arriver à nos fins. +- [Gérer du texte — les chaînes de caractères en JavaScript](/fr/docs/Learn/JavaScript/First_steps/Strings) + - : Attaquons-nous maintenant aux chaînes de caractères — le nom savant désignant en programmation des portions de texte. Dans cet article, nous allons voir les bases que vous devez impérativement connaître lors de votre apprentissage de JavaScript, comme la création de chaînes, l'échappement de caractères et la jonction de plusieurs chaînes. +- [Méthodes utiles pour les chaînes de caractères](/fr/docs/Learn/JavaScript/First_steps/methode_chaine_utile) + - : Maintenant que nous avons vu les bases relatives aux chaînes de catactères, passons à la vitesse supérieure et regardons ce que nous pouvons faire de plus poussé avec lesdites chaînes grâce aux méthodes natives, comme par exemple déterminer la longueur d'un texte, joindre et séparer des chaînes, remplacer un caractère par un autre, et bien plus encore. +- [Les tableaux](/fr/docs/Learn/JavaScript/First_steps/tableaux) + - : Dans le dernier article de ce module, nous allons nous pencher sur les tableaux — un moyen ingénieux de stocker une liste d'éléments dans une unique variable. Ici nous allons voir en quoi cela est pratique, puis nous verrons entre autres comment créer un tableau et comment récupérer, ajouter et supprimer des éléments stockés. -<h2 id="Auto-évaluation">Auto-évaluation</h2> +## Auto-évaluation -<p>L'auto-évaluation suivante teste votre compréhension des bases de JavaScript abordées dans le guide ci-dessus.</p> +L'auto-évaluation suivante teste votre compréhension des bases de JavaScript abordées dans le guide ci-dessus. -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator">Génerateur d'histoires absurdes</a></dt> - <dd>Dans le cadre de cette évaluation, votre tâche sera d'utiliser les connaissances que vous avez apprises dans les articles de ce module et de les appliquer pour créer une appli ludique qui génère aléatoirement des histoires absurdes. Amusez-vous bien !</dd> -</dl> +- [Génerateur d'histoires absurdes](/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator) + - : Dans le cadre de cette évaluation, votre tâche sera d'utiliser les connaissances que vous avez apprises dans les articles de ce module et de les appliquer pour créer une appli ludique qui génère aléatoirement des histoires absurdes. Amusez-vous bien ! diff --git a/files/fr/learn/javascript/first_steps/math/index.md b/files/fr/learn/javascript/first_steps/math/index.md index bdfdda9e64..33e7c0acda 100644 --- a/files/fr/learn/javascript/first_steps/math/index.md +++ b/files/fr/learn/javascript/first_steps/math/index.md @@ -17,402 +17,341 @@ tags: - modulo translation_of: Learn/JavaScript/First_steps/Math --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</div> - -<p>À ce point du didacticiel, nous parlerons de « mathématiques en JavaScript » — comment utiliser les {{Glossary("Operator","operators")}} et autres fonctionnalités pour manier avec succès les nombres pour faire nos bricolages.</p> +À ce point du didacticiel, nous parlerons de « mathématiques en JavaScript » — comment utiliser les {{Glossary("Operator","operators")}} et autres fonctionnalités pour manier avec succès les nombres pour faire nos bricolages. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Vocabulaire courant de l'informatique, bases de HTML et CSS, compréhension de ce que fait JavaScript.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Se familiariser avec les bases des maths en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Vocabulaire courant de l'informatique, bases de HTML et CSS, + compréhension de ce que fait JavaScript. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Se familiariser avec les bases des maths en JavaScript.</td> + </tr> + </tbody> </table> -<h2 id="Tout_le_monde_aime_les_maths">Tout le monde aime les maths</h2> +## Tout le monde aime les maths + +Mouais, peut‑être pas. Certains parmi nous aiment les maths, d'autres les détestent depuis qu'il leur a fallu apprendre les tables de multiplication et les longues divisions à l'école, d'autres se situent entre les deux. Mais personne ne peut nier que les mathématiques sont une connaissance fondamentale dont il n'est pas possible de se passer. Cela devient particulièrement vrai lorsque nous apprenons à programmer en JavaScript (ou tout autre langage d'ailleurs) — une grande part de ce que nous faisons reposant en effet sur le traitement de données numériques, le calcul de nouvelles valeurs, etc. ; vous ne serez donc pas étonné d'apprendre que JavaScript dispose d'un ensemble complet de fonctions mathématiques. + +Cet article ne traite que des éléments de base nécessaires pour débuter. -<p>Mouais, peut‑être pas. Certains parmi nous aiment les maths, d'autres les détestent depuis qu'il leur a fallu apprendre les tables de multiplication et les longues divisions à l'école, d'autres se situent entre les deux. Mais personne ne peut nier que les mathématiques sont une connaissance fondamentale dont il n'est pas possible de se passer. Cela devient particulièrement vrai lorsque nous apprenons à programmer en JavaScript (ou tout autre langage d'ailleurs) — une grande part de ce que nous faisons reposant en effet sur le traitement de données numériques, le calcul de nouvelles valeurs, etc. ; vous ne serez donc pas étonné d'apprendre que JavaScript dispose d'un ensemble complet de fonctions mathématiques.</p> +### Types de nombres -<p>Cet article ne traite que des éléments de base nécessaires pour débuter.</p> +En programmation, même l'ordinaire système des nombres décimaux que nous connaissons tous si bien est plus compliqué qu'on ne pourrait le croire. Nous utilisons divers termes pour décrire différents types de nombres décimaux, par exemple : -<h3 id="Types_de_nombres">Types de nombres</h3> +- **Entier :** (_Integer_ en anglais) c'est un nombre sans partie fractionnaire, comme son nom l'indique, par exemple 10, 400 ou -5 +- **Nombre à virgule flottante :** (_float_ en anglais) il a un **point** de séparation entre la partie entière et la partie fractionnaire (là où en France nous mettons une virgule), par exemple 12**.**5 et 56**.**7786543 +- **Doubles** : (pour double précision) ce sont des nombres à virgule flottante de précision supérieure aux précédents (on les dit plus précis en raison du plus grand nombre de décimales possibles). -<p>En programmation, même l'ordinaire système des nombres décimaux que nous connaissons tous si bien est plus compliqué qu'on ne pourrait le croire. Nous utilisons divers termes pour décrire différents types de nombres décimaux, par exemple :</p> +Nous disposons même de plusieurs systèmes de numération ! Le décimal a pour base 10 (ce qui signifie qu'il se sert de chiffres entre 0 et 9 dans chaque rang), mais il en existe d'autres : -<ul> - <li><strong>Entier :</strong> (<em>Integer </em>en anglais) c'est un nombre sans partie fractionnaire, comme son nom l'indique, par exemple 10, 400 ou -5</li> - <li><strong>Nombre à virgule flottante : </strong>(<em>float </em>en anglais) il a un <strong>point</strong> de séparation entre la partie entière et la partie fractionnaire (là où en France nous mettons une virgule), par exemple 12<strong>.</strong>5 et 56<strong>.</strong>7786543</li> - <li><strong>Doubles</strong> : (pour double précision) ce sont des nombres à virgule flottante de précision supérieure aux précédents (on les dit plus précis en raison du plus grand nombre de décimales possibles).</li> -</ul> +- **Binaire** — utilisé par le plus bas niveau de langage des ordinateurs, il est composé de 0 et de 1. +- **Octal** — de base 8, utilise les chiffres entre 0 et 7 dans chaque rang. +- **Hexadécimal** — de base 16, utilise les chiffres entre 0 et 9 puis les lettres de a à f dans chaque rang. Vous avez peut-être déjà rencontré ces nombres en définissant des couleurs dans les [CSS](/fr/docs/Learn/CSS/Introduction_to_CSS/Values_and_units#hexadecimal_values). -<p>Nous disposons même de plusieurs systèmes de numération ! Le décimal a pour base 10 (ce qui signifie qu'il se sert de chiffres entre 0 et 9 dans chaque rang), mais il en existe d'autres :</p> +**Avant que votre cervelle ne se mette à bouillir, stop !** Pour commencer, nous ne nous intéresserons qu'aux nombres décimaux dans ce cours ; vous aurez rarement besoin de vous servir des autres types, peut-être même jamais. -<ul> - <li><strong>Binaire</strong> — utilisé par le plus bas niveau de langage des ordinateurs, il est composé de 0 et de 1.</li> - <li><strong>Octal</strong> — de base 8, utilise les chiffres entre 0 et 7 dans chaque rang.</li> - <li><strong>Hexadécimal</strong> — de base 16, utilise les chiffres entre 0 et 9 puis les lettres de a à f dans chaque rang. Vous avez peut-être déjà rencontré ces nombres en définissant des couleurs dans les <a href="/fr/docs/Learn/CSS/Introduction_to_CSS/Values_and_units#hexadecimal_values">CSS</a>.</li> -</ul> +L'autre bonne nouvelle, c'est que contrairement à d'autres langages de programmation, JavaScript n'a qu'un seul type de donnée pour les nombres, vous l'avez deviné : {{jsxref("Number")}}. Cela signifie que, en JavaScript, quels que soient les types de nombre avec lesquels vous travaillerez, vous les manipulerez tous exactement de la même façon. -<p><strong>Avant que votre cervelle ne se mette à bouillir, stop !</strong> Pour commencer, nous ne nous intéresserons qu'aux nombres décimaux dans ce cours ; vous aurez rarement besoin de vous servir des autres types, peut-être même jamais.</p> +### Ce ne sont que des nombres pour moi -<p>L'autre bonne nouvelle, c'est que contrairement à d'autres langages de programmation, JavaScript n'a qu'un seul type de donnée pour les nombres, vous l'avez deviné : {{jsxref("Number")}}. Cela signifie que, en JavaScript, quels que soient les types de nombre avec lesquels vous travaillerez, vous les manipulerez tous exactement de la même façon.</p> +Amusons‑nous avec quelques chiffres pour nous familiariser avec la syntaxe de base dont nous aurons besoin. Entrez les commandes listées ci-dessous dans la [console JavaScript des outils de développement](/fr/docs/Learn/Common_questions/What_are_browser_developer_tools), ou utilisez la simple console intégrée que vous voyez ci-dessous si vous préférez. -<h3 id="Ce_ne_sont_que_des_nombres_pour_moi">Ce ne sont que des nombres pour moi</h3> +{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/variables/index.html", '100%', 300)}} -<p>Amusons‑nous avec quelques chiffres pour nous familiariser avec la syntaxe de base dont nous aurons besoin. Entrez les commandes listées ci-dessous dans la <a href="/fr/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript des outils de développement</a>, ou utilisez la simple console intégrée que vous voyez ci-dessous si vous préférez.</p> +**[Ouvrir la console dans une nouvelle fenêtre](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/)** -<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/variables/index.html", '100%', 300)}}</p> +1. Premièrement, déclarons une paire de variables et initialisons‑les respectivement avec un entier et un nombre avec des décimales, puis saisissons les noms des variables à nouveau pour vérifier que tout est correct : -<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/">Ouvrir la console dans une nouvelle fenêtre</a></strong></p> + ```js + var myInt = 5; + var myFloat = 6.667; + myInt; + myFloat; + ``` -<ol> - <li>Premièrement, déclarons une paire de variables et initialisons‑les respectivement avec un entier et un nombre avec des décimales, puis saisissons les noms des variables à nouveau pour vérifier que tout est correct : - <pre class="brush: js">var myInt = 5; -var myFloat = 6.667; -myInt; -myFloat;</pre> - </li> - <li>Les nombres sont saisis sans guillemets — essayez de déclarer et initialiser deux ou trois variables de plus contenant des nombres avant de continuer.</li> - <li>Maintenant vérifions que les deux variables d'origine sont du même type de donnée. En JavaScript, l'opérateur nommé {{jsxref("Operators/typeof", "typeof")}} est prévu pour cela. Entrez les deux lignes ci‑dessous comme indiqué :</li> - <li> - <pre class="brush: js">typeof myInt; -typeof myFloat;</pre> - </li> - <li><code>"number"</code> est renvoyé dans les deux cas — cela nous facilite les choses quand nous avons des nombres différents de types variés et que nous avons à les traiter de diverses façons. Ouf !</li> -</ol> +2. Les nombres sont saisis sans guillemets — essayez de déclarer et initialiser deux ou trois variables de plus contenant des nombres avant de continuer. +3. Maintenant vérifions que les deux variables d'origine sont du même type de donnée. En JavaScript, l'opérateur nommé {{jsxref("Operators/typeof", "typeof")}} est prévu pour cela. Entrez les deux lignes ci‑dessous comme indiqué : +4. ```js + typeof myInt; + typeof myFloat; + ``` +5. `"number"` est renvoyé dans les deux cas — cela nous facilite les choses quand nous avons des nombres différents de types variés et que nous avons à les traiter de diverses façons. Ouf ! -<h3 id="Méthodes_de_nombres_utiles">Méthodes de nombres utiles</h3> +### Méthodes de nombres utiles -<p>L'objet <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number">Number</a></code> , une instance qui représente tous les nombres standards que vous utiliserez dans votre JavaScript, a de nombreuses méthodes disponibles pour vous permettre de manipuler les nombres. Nous ne les étudierons pas tous en détail dans cet article car nous voulons qu'il reste une simple introduction et nous verrons seulement les bases essentielles pour le moment; cependant, une fois que vous aurez lu ce module plusieurs fois, il pourra être utile de visiter les pages de référence d'objet et d'en apprendre plus sur ce qui est disponible.</p> +L'objet [`Number`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Number) , une instance qui représente tous les nombres standards que vous utiliserez dans votre JavaScript, a de nombreuses méthodes disponibles pour vous permettre de manipuler les nombres. Nous ne les étudierons pas tous en détail dans cet article car nous voulons qu'il reste une simple introduction et nous verrons seulement les bases essentielles pour le moment; cependant, une fois que vous aurez lu ce module plusieurs fois, il pourra être utile de visiter les pages de référence d'objet et d'en apprendre plus sur ce qui est disponible. -<p>Par exemple, pour arrondir votre nombre avec un nombre fixe de décimales, utilisez la méthode <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed">toFixed()</a></code>. Tapez les lignes suivantes dans la <a href="/fr/docs/Tools/Web_Console">console de votre navigateur</a>:</p> +Par exemple, pour arrondir votre nombre avec un nombre fixe de décimales, utilisez la méthode [`toFixed()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed). Tapez les lignes suivantes dans la [console de votre navigateur](/fr/docs/Tools/Web_Console): -<pre class="brush: js">let lotsOfDecimal = 1.766584958675746364; +```js +let lotsOfDecimal = 1.766584958675746364; lotsOfDecimal; let twoDecimalPlaces = lotsOfDecimal.toFixed(2); -twoDecimalPlaces;</pre> +twoDecimalPlaces; +``` -<h3 id="Convertir_en_type_de_données_numérique">Convertir en type de données numérique</h3> +### Convertir en type de données numérique -<p>Parfois vous pourriez finir avec un nombre stocké de type "string", ce qui rendra difficile le fait d'effectuer un calcul avec. Ca arrive le plus souvent lorsqu'une donnée est entrée dans une entrée de <a href="/fr/docs/Learn/Forms">formulaire</a>, et le <a href="/fr/docs/Web/HTML/Element/Input/text">type de donnée entré est du texte</a>. Il éxiste une façon de résoudre ce problème — passer la valeur de "string" dans le constructeur <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number/Number">Number()</a></code> pour retourner une version numérique de la même valeur.</p> +Parfois vous pourriez finir avec un nombre stocké de type "string", ce qui rendra difficile le fait d'effectuer un calcul avec. Ca arrive le plus souvent lorsqu'une donnée est entrée dans une entrée de [formulaire](/fr/docs/Learn/Forms), et le [type de donnée entré est du texte](/fr/docs/Web/HTML/Element/Input/text). Il éxiste une façon de résoudre ce problème — passer la valeur de "string" dans le constructeur [`Number()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Number/Number) pour retourner une version numérique de la même valeur. -<p>Par exemple, essayez de taper ces lignes dans votre console:</p> +Par exemple, essayez de taper ces lignes dans votre console: -<pre class="brush: js">let myNumber = '74'; -myNumber + 3;</pre> +```js +let myNumber = '74'; +myNumber + 3; +``` -<p>Vous obtenez le résultat 743, et non pas 77, car <code>myNumber</code> est en fait défini en tant que "string". Vous pouvez tester en tapant la ligne suivante:</p> +Vous obtenez le résultat 743, et non pas 77, car `myNumber` est en fait défini en tant que "string". Vous pouvez tester en tapant la ligne suivante: -<pre class="brush: js">typeof myNumber;</pre> +```js +typeof myNumber; +``` -<p>Pour réparer le calcul, vous pouvez faire ceci:</p> +Pour réparer le calcul, vous pouvez faire ceci: -<pre class="brush: js">Number(myNumber) + 3;</pre> +```js +Number(myNumber) + 3; +``` -<h2 id="Opérateurs_arithmétiques">Opérateurs arithmétiques</h2> +## Opérateurs arithmétiques -<p>Ce sont les opérateurs de base pour effectuer diverses opérations :</p> +Ce sont les opérateurs de base pour effectuer diverses opérations : <table class="standard-table"> - <thead> - <tr> - <th scope="col">Operateur</th> - <th scope="col">Nom</th> - <th scope="col">But</th> - <th scope="col">Exemple</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>+</code></td> - <td>Addition</td> - <td>Ajoute deux nombres.</td> - <td><code>6 + 9</code></td> - </tr> - <tr> - <td><code>-</code></td> - <td>Soustraction</td> - <td>Soustrait le nombre de droite de celui de gauche.</td> - <td><code>20 - 15</code></td> - </tr> - <tr> - <td><code>*</code></td> - <td>Multiplication</td> - <td>Multiplie les deux nombrer.</td> - <td><code>3 * 7</code></td> - </tr> - <tr> - <td><code>/</code></td> - <td>Division</td> - <td>Divise le nombre de gauche par celui de droite.</td> - <td><code>10 / 5</code></td> - </tr> - <tr> - <td><code>%</code></td> - <td> - <p>Reste (quelquefois nommé modulo)</p> - </td> - <td> - <p>Renvoie le reste de la division du nombre de gauche par celui de droite.</p> - </td> - <td><code>8 % 3</code> (renvoie 2, car 3 est contenu 2 fois dans 8, et il reste 2.)</td> - </tr> - </tbody> + <thead> + <tr> + <th scope="col">Operateur</th> + <th scope="col">Nom</th> + <th scope="col">But</th> + <th scope="col">Exemple</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Addition</td> + <td>Ajoute deux nombres.</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Soustraction</td> + <td>Soustrait le nombre de droite de celui de gauche.</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplication</td> + <td>Multiplie les deux nombrer.</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>Division</td> + <td>Divise le nombre de gauche par celui de droite.</td> + <td><code>10 / 5</code></td> + </tr> + <tr> + <td><code>%</code></td> + <td><p>Reste (quelquefois nommé modulo)</p></td> + <td> + <p> + Renvoie le reste de la division du nombre de gauche par celui de + droite. + </p> + </td> + <td> + <code>8 % 3</code> (renvoie 2, car 3 est contenu 2 fois dans 8, et il + reste 2.) + </td> + </tr> + </tbody> </table> -<div class="note"> -<p><strong>Note :</strong> Quelquefois les nombres impliqués dans des opérations sont nommés {{Glossary("Operand", "operands")}}.</p> -</div> +> **Note :** Quelquefois les nombres impliqués dans des opérations sont nommés {{Glossary("Operand", "operands")}}. + +Nous n'avons certainement pas besoin de vous apprendre les quatre opérations, mais ce serait bien de tester si vous avez bien compris la syntaxe. Entrez les exemples ci‑dessous dans la [console des outils de développement JavaScript](/fr/docs/Learn/Common_questions/What_are_browser_developer_tools) ou servez vous de la console intégrée plus haut, comme vous préférez, pour vous familiariser avec la syntaxe. + +1. Essayez de saisir quelques exemples simples de votre cru, comme : + + ```js + 10 + 7 + 9 * 8 + 60 % 3 + ``` -<p>Nous n'avons certainement pas besoin de vous apprendre les quatre opérations, mais ce serait bien de tester si vous avez bien compris la syntaxe. Entrez les exemples ci‑dessous dans la <a href="/fr/docs/Learn/Common_questions/What_are_browser_developer_tools">console des outils de développement JavaScript</a> ou servez vous de la console intégrée plus haut, comme vous préférez, pour vous familiariser avec la syntaxe.</p> +2. Déclarez et initialisez quelques variables, puis utilisez‑les dans des opérations — les variables se comporteront exactement comme les valeurs qu'elles contiennent pour les besoins de l'opération. Par exemple : -<ol> - <li>Essayez de saisir quelques exemples simples de votre cru, comme : - <pre class="brush: js">10 + 7 -9 * 8 -60 % 3</pre> - </li> - <li>Déclarez et initialisez quelques variables, puis utilisez‑les dans des opérations — les variables se comporteront exactement comme les valeurs qu'elles contiennent pour les besoins de l'opération. Par exemple : - <pre class="brush: js">var num1 = 10; -var num2 = 50; -9 * num1; -num2 / num1;</pre> - </li> - <li>Pour terminer cette partie, entrez quelques expressions plus compliquées, comme : - <pre class="brush: js">5 + 10 * 3; -num2 % 9 * num1; -num2 + num1 / 8 + 2;</pre> - </li> -</ol> + ```js + var num1 = 10; + var num2 = 50; + 9 * num1; + num2 / num1; + ``` -<p>Certaines opérations de cet ensemble ne vous renvoient peut-être pas le résultat attendu ; le paragraphe qui suit vous explique pourquoi.</p> +3. Pour terminer cette partie, entrez quelques expressions plus compliquées, comme : -<h3 id="Priorité_des_opérateurs">Priorité des opérateurs</h3> + ```js + 5 + 10 * 3; + num2 % 9 * num1; + num2 + num1 / 8 + 2; + ``` -<p>Revenons sur le dernier exemple ci‑dessus, en supposant que <code>num2</code> contient la valeur 50 et <code>num1</code> contient 10 (comme défini plus haut) :</p> +Certaines opérations de cet ensemble ne vous renvoient peut-être pas le résultat attendu ; le paragraphe qui suit vous explique pourquoi. -<pre class="brush: js">num2 + num1 / 8 + 2;</pre> +### Priorité des opérateurs -<p>En tant qu'humain, vous pouvez lire « <em>50 plus 10 égale 60 »</em>, puis « <em>8 plus 2 égale 10 »</em> et finalement « <em>60 divisé par 10 égale 6 »</em>.</p> +Revenons sur le dernier exemple ci‑dessus, en supposant que `num2` contient la valeur 50 et `num1` contient 10 (comme défini plus haut) : -<p>Mais le navigateur <em>calcule « 10 sur 8 égale 1.25 »</em>, puis « <em>50 plus 1.25 plus 2 égale 53.25 »</em>.</p> +```js +num2 + num1 / 8 + 2; +``` -<p>Cela est dû aux <strong>priorités entre opérateurs</strong> — certains sont appliqués avant d'autres dans une opération (on parle d'une expression en programmation). En JavaScript, la priorité des opérateurs est identique à celle enseignée à l'école — Multiplication et Division sont toujours effectuées en premier, suivies d'Addition et Soustraction (le calcul est toujours exécuté de la gauche vers la droite).</p> +En tant qu'humain, vous pouvez lire « *50 plus 10 égale 60 »*, puis « *8 plus 2 égale 10 »* et finalement « *60 divisé par 10 égale 6 »*. -<p>Si vous voulez contourner les règles de priorité des opérateurs, vous pouvez mettre entre parenthèses les parties que vous souhaitez voir calculées en premier. Pour obtenir un résultat égal à 6, nous devons donc écrire :</p> +Mais le navigateur _calcule « 10 sur 8 égale 1.25 »_, puis « *50 plus 1.25 plus 2 égale 53.25 »*. -<pre class="brush: js">(num2 + num1) / (8 + 2);</pre> +Cela est dû aux **priorités entre opérateurs** — certains sont appliqués avant d'autres dans une opération (on parle d'une expression en programmation). En JavaScript, la priorité des opérateurs est identique à celle enseignée à l'école — Multiplication et Division sont toujours effectuées en premier, suivies d'Addition et Soustraction (le calcul est toujours exécuté de la gauche vers la droite). -<p>Essayez-le et voyez.</p> +Si vous voulez contourner les règles de priorité des opérateurs, vous pouvez mettre entre parenthèses les parties que vous souhaitez voir calculées en premier. Pour obtenir un résultat égal à 6, nous devons donc écrire : -<div class="note"> -<p><strong>Note :</strong> La liste complète de tous les opérateurs JavaScript et leur priorité peut être trouvée dans <a href="/fr/docs/Web/JavaScript/Guide/Expressions_and_Operators#operator_precedence">Expressions and operators</a>.</p> -</div> +```js +(num2 + num1) / (8 + 2); +``` -<h2 id="Opérateurs_dincrémentation_et_de_décrémentation">Opérateurs d'incrémentation et de décrémentation</h2> +Essayez-le et voyez. -<p>Quelquefois vous aurez besoin d'ajouter ou retrancher 1 à une valeur de variable de manière répétitive. On effectue commodément cette opération à l'aide des opérateurs d'incrémentation (<code>++</code>) ou de décrementation (<code>--</code>). Nous nous sommes servis de <code>++</code> dans le jeu « Devinez le nombre » dans notre article <a href="/fr/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash">Première plongée dans le JavaScript</a> pour ajouter 1 à la variable <code>guessCount</code> pour décompter le nombre de suppositions restantes après chaque tour.</p> +> **Note :** La liste complète de tous les opérateurs JavaScript et leur priorité peut être trouvée dans [Expressions and operators](/fr/docs/Web/JavaScript/Guide/Expressions_and_Operators#operator_precedence). -<pre class="brush: js">guessCount++;</pre> +## Opérateurs d'incrémentation et de décrémentation -<div class="note"> -<p><strong>Note :</strong> Ces opérateurs sont couramment utilisés dans des <a href="/fr/docs/Web/JavaScript/Guide/Loops_and_iteration">boucles ;</a> nous les verrons plus loin dans ce cours. Par exemple, disons que vous voulez parcourir une liste de prix et ajouter les taxes à chacun. Vous utiliserez une boucle pour obtenir chaque valeur une à une et exécuterez le calcul voulu pour ajouter les taxes à chacune. L'incrément s'utilise pour aller à la valeur suivante. Nous avons mis un exemple concret montrant comment faire — voyez‑le tout de suite, examinez le code source et notez les opérateurs d'incrémentation ! Nous reverrons les boucles en détail plus loin dans ce cours.</p> -</div> +Quelquefois vous aurez besoin d'ajouter ou retrancher 1 à une valeur de variable de manière répétitive. On effectue commodément cette opération à l'aide des opérateurs d'incrémentation (`++`) ou de décrementation (`--`). Nous nous sommes servis de `++` dans le jeu « Devinez le nombre » dans notre article [Première plongée dans le JavaScript](/fr/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash) pour ajouter 1 à la variable `guessCount` pour décompter le nombre de suppositions restantes après chaque tour. -<p>Jouons avec ces opérateurs dans la console. Notez d'abord qu'il n'est pas possible de les appliquer directement à un nombre, ce qui peut paraître étrange, mais cet opérateur assigne à une variable une nouvelle valeur mise à jour, il n'agit pas sur la valeur elle‑même. Ce qui suit renvoie une erreur :</p> +```js +guessCount++; +``` -<pre class="brush: js">3++;</pre> +> **Note :** Ces opérateurs sont couramment utilisés dans des [boucles ;](/fr/docs/Web/JavaScript/Guide/Loops_and_iteration) nous les verrons plus loin dans ce cours. Par exemple, disons que vous voulez parcourir une liste de prix et ajouter les taxes à chacun. Vous utiliserez une boucle pour obtenir chaque valeur une à une et exécuterez le calcul voulu pour ajouter les taxes à chacune. L'incrément s'utilise pour aller à la valeur suivante. Nous avons mis un exemple concret montrant comment faire — voyez‑le tout de suite, examinez le code source et notez les opérateurs d'incrémentation ! Nous reverrons les boucles en détail plus loin dans ce cours. -<p>Vous ne pouvez donc incrémenter qu'une variable déjà existante. Essayez ceci :</p> +Jouons avec ces opérateurs dans la console. Notez d'abord qu'il n'est pas possible de les appliquer directement à un nombre, ce qui peut paraître étrange, mais cet opérateur assigne à une variable une nouvelle valeur mise à jour, il n'agit pas sur la valeur elle‑même. Ce qui suit renvoie une erreur : -<pre class="brush: js">var num1 = 4; -num1++;</pre> +```js +3++; +``` -<p>Ok, curieuse la ligne 2 ! En écrivant cela, elle renvoie la valeur 4 — c'est dû au fait que l'explorateur renvoie la valeur courante, <em>puis</em> incrémente la variable. Vous constaterez qu'elle a bien été incrémentée si vous demandez de la revoir :</p> +Vous ne pouvez donc incrémenter qu'une variable déjà existante. Essayez ceci : -<pre class="brush: js">num1;</pre> +```js +var num1 = 4; +num1++; +``` -<p>C'est pareil avec <code>--</code> : essayez ce qui suit</p> +Ok, curieuse la ligne 2 ! En écrivant cela, elle renvoie la valeur 4 — c'est dû au fait que l'explorateur renvoie la valeur courante, _puis_ incrémente la variable. Vous constaterez qu'elle a bien été incrémentée si vous demandez de la revoir : -<pre class="brush: js">var num2 = 6; +```js +num1; +``` + +C'est pareil avec `--` : essayez ce qui suit + +```js +var num2 = 6; num2--; -num2;</pre> +num2; +``` -<div class="note"> -<p><strong>Note :</strong> En mettant l'opérateur avant la variable au lieu d'après, le navigateur agira dans l'ordre inverse — incrément/décrément de la variable <em>puis</em> renvoi de la valeur — . Essayez les exemples plus haut, mais cette fois avec <code>++num1</code> et <code>--num2</code>.</p> -</div> +> **Note :** En mettant l'opérateur avant la variable au lieu d'après, le navigateur agira dans l'ordre inverse — incrément/décrément de la variable _puis_ renvoi de la valeur — . Essayez les exemples plus haut, mais cette fois avec `++num1` et `--num2`. -<h2 id="Opérateurs_dassignation">Opérateurs d'assignation</h2> +## Opérateurs d'assignation -<p>Les opérateurs d'assignation sont ceux qui fixent la valeur d'une variable. Nous avons déjà utilisé plusieurs fois le plus élémentaire, <code>=</code> — il donne à la variable de gauche la valeur indiquée à droite :</p> +Les opérateurs d'assignation sont ceux qui fixent la valeur d'une variable. Nous avons déjà utilisé plusieurs fois le plus élémentaire, `=` — il donne à la variable de gauche la valeur indiquée à droite : -<pre class="brush: js">var x = 3; // x contient la valeur 3 +```js +var x = 3; // x contient la valeur 3 var y = 4; // y contient la valeur 4 -x = y; // x contient maintenant la même valeur que y, 4</pre> +x = y; // x contient maintenant la même valeur que y, 4 +``` -<p>Mais il existe des types plus complexes, qui procurent des raccourcis utiles pour un code plus propre et plus efficace. Les plus courants sont listés ici :</p> +Mais il existe des types plus complexes, qui procurent des raccourcis utiles pour un code plus propre et plus efficace. Les plus courants sont listés ici : -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Opérateur</th> - <th scope="col">Nom</th> - <th scope="col">But</th> - <th scope="col">Exemple</th> - <th scope="col">Raccourci pour</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>+=</code></td> - <td>Addition et assignation</td> - <td>Ajoute la valeur de droite à la valeur de la variable de gauche, puis renvoie la nouvelle valeur de la variable</td> - <td><code>x = 3;<br> - x += 4;</code></td> - <td><code>x = 3;<br> - x = x + 4;</code></td> - </tr> - <tr> - <td><code>-=</code></td> - <td>Soustraction et assignation</td> - <td>Soustrait la valeur de droite à la valeur de la variable de gauche, puis renvoie la nouvelle valeur de la variable</td> - <td><code>x = 6;<br> - x -= 3;</code></td> - <td><code>x = 6;<br> - x = x - 3;</code></td> - </tr> - <tr> - <td><code>*=</code></td> - <td>Multiplication et assignation</td> - <td>Multiplie la valeur de droite par la valeur de la variable de gauche, puis renvoie la nouvelle valeur de la variable</td> - <td><code>x = 2;<br> - x *= 3;</code></td> - <td><code>x = 2;<br> - x = x * 3;</code></td> - </tr> - <tr> - <td><code>/=</code></td> - <td>Division et assignation</td> - <td>Divise la valeur de la variable de gauche par la valeur de droite, puis renvoie la nouvelle valeur de la variable</td> - <td><code>x = 10;<br> - x /= 5;</code></td> - <td><code>x = 10;<br> - x = x / 5;</code></td> - </tr> - </tbody> -</table> +| Opérateur | Nom | But | Exemple | Raccourci pour | +| --------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------------- | +| `+=` | Addition et assignation | Ajoute la valeur de droite à la valeur de la variable de gauche, puis renvoie la nouvelle valeur de la variable | `x = 3; x += 4;` | `x = 3; x = x + 4;` | +| `-=` | Soustraction et assignation | Soustrait la valeur de droite à la valeur de la variable de gauche, puis renvoie la nouvelle valeur de la variable | `x = 6; x -= 3;` | `x = 6; x = x - 3;` | +| `*=` | Multiplication et assignation | Multiplie la valeur de droite par la valeur de la variable de gauche, puis renvoie la nouvelle valeur de la variable | `x = 2; x *= 3;` | `x = 2; x = x * 3;` | +| `/=` | Division et assignation | Divise la valeur de la variable de gauche par la valeur de droite, puis renvoie la nouvelle valeur de la variable | `x = 10; x /= 5;` | `x = 10; x = x / 5;` | -<p>Saisissez quelques uns de ces exemples dans la console pour avoir une idée de leur fonctionnement. Dans chaque cas, voyez si vous avez deviné la valeur avant de saisir la deuxième ligne.</p> +Saisissez quelques uns de ces exemples dans la console pour avoir une idée de leur fonctionnement. Dans chaque cas, voyez si vous avez deviné la valeur avant de saisir la deuxième ligne. -<p>Notez que vous pouvez opportunément utiliser une autre variable comme opérateur sur la droite de chaque expression, par exemple :</p> +Notez que vous pouvez opportunément utiliser une autre variable comme opérateur sur la droite de chaque expression, par exemple : -<pre class="brush: js">var x = 3; // x contient la valeur 3 +```js +var x = 3; // x contient la valeur 3 var y = 4; // y contient la valeur 4 -x *= y; // x contient maintenant la valeur 12</pre> +x *= y; // x contient maintenant la valeur 12 +``` -<div class="note"> -<p><strong>Note :</strong> Il y a des tas d'<a href="/fr/docs/Web/JavaScript/Guide/Expressions_and_Operators#assignment_operators">autres opérateurs d'assignation disponibles</a>, mais ceux‑ci sont les plus courants que vous devez les connaître dès maintenant.</p> -</div> +> **Note :** Il y a des tas d'[autres opérateurs d'assignation disponibles](/fr/docs/Web/JavaScript/Guide/Expressions_and_Operators#assignment_operators), mais ceux‑ci sont les plus courants que vous devez les connaître dès maintenant. -<h2 id="Apprentissage_actif_dimensionner_une_boîte_à_canevas">Apprentissage actif : dimensionner une boîte à canevas</h2> +## Apprentissage actif : dimensionner une boîte à canevas -<p>Dans cet exercice, vous allez manier quelques nombres et opérateurs pour changer la taille d'une boîte. La boîte est tracée à l'aide de l'API de navigateur nommée {{domxref("Canvas API", "", "", "true")}}. Pas besoin de savoir comment elle fonctionne — concentrez-vous simplement sur les mathématiques pour l'instant. Les largeur et hauteur de la boîte (en pixels) sont définies par les variables <code>x</code> et <code>y</code>, qui sont toutes deux initialisées avec la valeur 50.</p> +Dans cet exercice, vous allez manier quelques nombres et opérateurs pour changer la taille d'une boîte. La boîte est tracée à l'aide de l'API de navigateur nommée {{domxref("Canvas API", "", "", "true")}}. Pas besoin de savoir comment elle fonctionne — concentrez-vous simplement sur les mathématiques pour l'instant. Les largeur et hauteur de la boîte (en pixels) sont définies par les variables `x` et `y`, qui sont toutes deux initialisées avec la valeur 50. -<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 520)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 520)}} -<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html">Ouvrir dans une nouvelle fenêtre</a></strong></p> +**[Ouvrir dans une nouvelle fenêtre](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html)** -<p>Le code dans la boîte ci-desssus peut être modifié. Un commentaire signale les deux lignes suivantes, que vous devez mettre à jour pour faire en sorte que la boîte grossisse ou rétrécisse aux tailles données, en utilisant certains opérateurs et/ou valeurs dans chaque cas. Essayez ce qui suit en réinitialisant à chaque étape :</p> +Le code dans la boîte ci-desssus peut être modifié. Un commentaire signale les deux lignes suivantes, que vous devez mettre à jour pour faire en sorte que la boîte grossisse ou rétrécisse aux tailles données, en utilisant certains opérateurs et/ou valeurs dans chaque cas. Essayez ce qui suit en réinitialisant à chaque étape : -<ul> - <li>Modifier la ligne qui calcule x pour que la boîte conserve sa largeur de 50 pixels, mais que 50 soit calculé avec les nombres 43 et 7 ainsi qu'un opérateur arithmétique.</li> - <li>Modifier la ligne qui calcule y pour que la boîte prenne une hauteur de 75 pixels, mais que 75 ait été calculé avec les nombres 25 et 3 ainsi qu'un opérateur arithmétique.</li> - <li>Modifier la ligne qui calcule x pour que la boîte prenne une largeur de 250pixels, mais que 250 ait été calculé avec deux nombres ainsi que l'opérateur <strong>reste</strong> (modulo).</li> - <li>Modifier la ligne qui calcule y pour que la boîte prenne une hauteur de 150pixels, mais que 150 ait été calculé en utilisant 3 nombres et les opérateurs <strong>soustraction </strong>et <strong>division</strong>.</li> - <li>Modifier la ligne qui calcule x pour que la boîte prenne une largeur de 200pixels, mais que 200 ait été calculé en se servant du nombre 4 et d'un opérateur d'<strong>assignation</strong>.</li> - <li>Modifier la ligne qui calcule y pour que la boîte prenne une hauteur de 200 pixels, mais que 200 ait été calculé en utilisant les nombres 50 et 3 ainsi que les opérateurs <strong>multiplication</strong>, <strong>addition </strong>et <strong>assignation</strong>.</li> -</ul> +- Modifier la ligne qui calcule x pour que la boîte conserve sa largeur de 50 pixels, mais que 50 soit calculé avec les nombres 43 et 7 ainsi qu'un opérateur arithmétique. +- Modifier la ligne qui calcule y pour que la boîte prenne une hauteur de 75 pixels, mais que 75 ait été calculé avec les nombres 25 et 3 ainsi qu'un opérateur arithmétique. +- Modifier la ligne qui calcule x pour que la boîte prenne une largeur de 250pixels, mais que 250 ait été calculé avec deux nombres ainsi que l'opérateur **reste** (modulo). +- Modifier la ligne qui calcule y pour que la boîte prenne une hauteur de 150pixels, mais que 150 ait été calculé en utilisant 3 nombres et les opérateurs **soustraction** et **division**. +- Modifier la ligne qui calcule x pour que la boîte prenne une largeur de 200pixels, mais que 200 ait été calculé en se servant du nombre 4 et d'un opérateur d'**assignation**. +- Modifier la ligne qui calcule y pour que la boîte prenne une hauteur de 200 pixels, mais que 200 ait été calculé en utilisant les nombres 50 et 3 ainsi que les opérateurs **multiplication**, **addition** et **assignation**. -<p>Pas d'inquiétude si vous vous trompez. Vous pouvez toujours presser le bouton Reset et les choses fonctionneront à nouveau. Après avoir répondu correctement aux questions posées, amusez‑vous avec ce code ou définissez vous‑même les défis.</p> +Pas d'inquiétude si vous vous trompez. Vous pouvez toujours presser le bouton Reset et les choses fonctionneront à nouveau. Après avoir répondu correctement aux questions posées, amusez‑vous avec ce code ou définissez vous‑même les défis. -<h2 id="Opérateurs_de_comparaison">Opérateurs de comparaison</h2> +## Opérateurs de comparaison -<p>Parfois nous avons besoin d'exécuter des tests vrai/faux (true/false), puis d'agir en fonction du résultat — pour ce faire, nous utilisons des <strong>opérateurs de comparaison</strong>.</p> +Parfois nous avons besoin d'exécuter des tests vrai/faux (true/false), puis d'agir en fonction du résultat — pour ce faire, nous utilisons des **opérateurs de comparaison**. -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Operateur</th> - <th scope="col">Nom</th> - <th scope="col">But</th> - <th scope="col">Exemple</th> - </tr> - <tr> - <td><code>===</code></td> - <td>Égalité stricte</td> - <td>Teste si les valeurs de droite et de gauche sont identiques</td> - <td><code>5 === 2 + 4</code></td> - </tr> - <tr> - <td><code>!==</code></td> - <td>Non-égalité stricte</td> - <td>Teste si les valeurs de doite et de gauche ne sont pas identiques</td> - <td><code>5 !== 2 + 3</code></td> - </tr> - <tr> - <td><code><</code></td> - <td>Inférieur à</td> - <td>Teste si la valeur de gauche est plus petite que celle de droite.</td> - <td><code>10 < 6</code></td> - </tr> - <tr> - <td><code>></code></td> - <td>Supérieur à</td> - <td>Teste si la valeur de gauche est plus grande que celle de droite.</td> - <td><code>10 > 20</code></td> - </tr> - <tr> - <td><=</td> - <td>Inférieur ou égal à</td> - <td>Teste si la valeur de gauche est plus petite ou égale à celle de droite.</td> - <td><code>3 <= 2</code></td> - </tr> - <tr> - <td>>=</td> - <td>Supérieur ou égal à</td> - <td>Teste si la valeur de gauche est supérieure ou égale à celle de droite.</td> - <td><code>5 >= 4</code></td> - </tr> - </thead> -</table> +| Operateur | Nom | But | Exemple | +| --------- | ------------------- | ------------------------------------------------------------------------ | ------------- | +| `===` | Égalité stricte | Teste si les valeurs de droite et de gauche sont identiques | `5 === 2 + 4` | +| `!==` | Non-égalité stricte | Teste si les valeurs de doite et de gauche ne sont pas identiques | `5 !== 2 + 3` | +| `<` | Inférieur à | Teste si la valeur de gauche est plus petite que celle de droite. | `10 < 6` | +| `>` | Supérieur à | Teste si la valeur de gauche est plus grande que celle de droite. | `10 > 20` | +| <= | Inférieur ou égal à | Teste si la valeur de gauche est plus petite ou égale à celle de droite. | `3 <= 2` | +| >= | Supérieur ou égal à | Teste si la valeur de gauche est supérieure ou égale à celle de droite. | `5 >= 4` | -<div class="note"> -<p><strong>Note :</strong> Vous verrez peut‑être certaines personnes utiliser <code>==</code> et <code>!=</code> pour leurs test d'égalité ou non-égalité. Ces opérateurs sont valides en JavaScript, mais différents de <code>===</code>/<code>!==</code>. Les versions avec deux caractères testent si les valeurs sont les mêmes, mais pas si les types de données sont les mêmes. Les versions strictes à trois caractères testent à la fois l'égalité des valeurs <em>et</em> des types de données. Il y a moins d'erreurs avec les versions strictes, donc nous vous engageons à les utiliser dans tous les cas.</p> -</div> +> **Note :** Vous verrez peut‑être certaines personnes utiliser `==` et `!=` pour leurs test d'égalité ou non-égalité. Ces opérateurs sont valides en JavaScript, mais différents de `===`/`!==`. Les versions avec deux caractères testent si les valeurs sont les mêmes, mais pas si les types de données sont les mêmes. Les versions strictes à trois caractères testent à la fois l'égalité des valeurs _et_ des types de données. Il y a moins d'erreurs avec les versions strictes, donc nous vous engageons à les utiliser dans tous les cas. -<p>Si vous entrez certaines de ces valeurs dans une console, vous constaterez que toutes renvoient une valeur <code>true</code>/<code>false</code> — les booléens mentionnés dans l'article précédent. Ces opérateurs sont très utiles car il nous permettent de prendre des décisions dans le code, et ils sont utilisés chaque fois que nous avons besoin de faire un choix. Par exemple, les booléens s'utilisent pour :</p> +Si vous entrez certaines de ces valeurs dans une console, vous constaterez que toutes renvoient une valeur `true`/`false` — les booléens mentionnés dans l'article précédent. Ces opérateurs sont très utiles car il nous permettent de prendre des décisions dans le code, et ils sont utilisés chaque fois que nous avons besoin de faire un choix. Par exemple, les booléens s'utilisent pour : -<ul> - <li>Afficher l'étiquette textuelle ad-hoc sur un bouton selon qu'une fonctionnalité est active ou pas</li> - <li>Afficher un message de fin de jeu si un jeu est terminé ou un message de victoire si le jeu a été remporté</li> - <li>Afficher des remerciements saisonniers corrects selon la saison de vacances</li> - <li>Faire un zoom avant ou arrière sur une carte selon le niveau de zoom choisi</li> -</ul> +- Afficher l'étiquette textuelle ad-hoc sur un bouton selon qu'une fonctionnalité est active ou pas +- Afficher un message de fin de jeu si un jeu est terminé ou un message de victoire si le jeu a été remporté +- Afficher des remerciements saisonniers corrects selon la saison de vacances +- Faire un zoom avant ou arrière sur une carte selon le niveau de zoom choisi -<p>Nous verrons comment coder cette logique quand nous étudierons les directives conditionnelles dans un article ultérieur. Pour le moment, regardons un exemple rapide :</p> +Nous verrons comment coder cette logique quand nous étudierons les directives conditionnelles dans un article ultérieur. Pour le moment, regardons un exemple rapide : -<pre class="brush: html"><button>Démarrer la machine</button> -<p>La machine est arrêtée.</p> -</pre> +```html +<button>Démarrer la machine</button> +<p>La machine est arrêtée.</p> +``` -<pre class="brush: js">var btn = document.querySelector('button'); +```js +var btn = document.querySelector('button'); var txt = document.querySelector('p'); btn.addEventListener('click', updateBtn); @@ -425,26 +364,23 @@ function updateBtn() { btn.textContent = 'Démarrer la machine'; txt.textContent = 'La machine est arrêtée.'; } -}</pre> +} +``` -<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/conditional.html", '100%', 100)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/conditional.html", '100%', 100)}} -<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/conditional.html">Ouvrir dans une nouvelle fenêtre</a></strong></p> +**[Ouvrir dans une nouvelle fenêtre](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/conditional.html)** -<p>Vous pouvez voir l'utilisation de l'opérateur d'égalité stricte dans la fonction <code>updateBtn()</code>. Dans ce cas, nous ne testons pas si deux expressions mathématiques ont la même valeur — nous testons si le contenu textuel d'un bouton contient une certaine chaîne — mais c'est toujours le même principe. Si le bouton affiche « Démarrer la machine » quand on le presse, nous changeons son étiquette en « Arrêter la machine » et mettons à jour l'étiquette comme il convient. Si le bouton indique « Arrêter la machine » au moment de le presser, nous basculons l'étiquette à nouveau.</p> +Vous pouvez voir l'utilisation de l'opérateur d'égalité stricte dans la fonction `updateBtn()`. Dans ce cas, nous ne testons pas si deux expressions mathématiques ont la même valeur — nous testons si le contenu textuel d'un bouton contient une certaine chaîne — mais c'est toujours le même principe. Si le bouton affiche « Démarrer la machine » quand on le presse, nous changeons son étiquette en « Arrêter la machine » et mettons à jour l'étiquette comme il convient. Si le bouton indique « Arrêter la machine » au moment de le presser, nous basculons l'étiquette à nouveau. -<div class="note"> -<p><strong>Note :</strong> Un contrôle qui alterne entre deux états porte généralement le nom de <strong>toggle</strong> (bascule). Il bascule d'un état l'autre — allumé, éteint, etc.</p> -</div> +> **Note :** Un contrôle qui alterne entre deux états porte généralement le nom de **toggle** (bascule). Il bascule d'un état l'autre — allumé, éteint, etc. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Dans cet article, nous avons exposé les informations fondamentales concernant les nombres en JavaScript, à connaître absolument pour débuter convenablement. Vous verrez encore et encore des utilisations de nombres tout au long de cet introduction au JavaScript, prenons donc une pause pour le moment. Si vous êtes de ceux qui n'aiment pas les maths, vous noterez avec satisfaction que ce chapitre était vraiment très court.</p> +Dans cet article, nous avons exposé les informations fondamentales concernant les nombres en JavaScript, à connaître absolument pour débuter convenablement. Vous verrez encore et encore des utilisations de nombres tout au long de cet introduction au JavaScript, prenons donc une pause pour le moment. Si vous êtes de ceux qui n'aiment pas les maths, vous noterez avec satisfaction que ce chapitre était vraiment très court. -<p>Dans l'article suivant, nous étudierons le texte et les façons dont JavaScript nous permet de le manipuler.</p> +Dans l'article suivant, nous étudierons le texte et les façons dont JavaScript nous permet de le manipuler. -<div class="note"> -<p><strong>Note :</strong> Si les Maths vous plaisent et que vous souhaitez en savoir plus sur la manière dont elles sont implémentées en JavaScript, vous trouverez plus de précisions dans la section principale JavaScript du MDN. Une grande place est réservée dans ces articles aux <a href="/fr/docs/Web/JavaScript/Guide/Numbers_and_dates">Nombres et dates</a> et aux <a href="/fr/docs/Web/JavaScript/Guide/Expressions_and_Operators">Expressions et opérateurs</a>.</p> -</div> +> **Note :** Si les Maths vous plaisent et que vous souhaitez en savoir plus sur la manière dont elles sont implémentées en JavaScript, vous trouverez plus de précisions dans la section principale JavaScript du MDN. Une grande place est réservée dans ces articles aux [Nombres et dates](/fr/docs/Web/JavaScript/Guide/Numbers_and_dates) et aux [Expressions et opérateurs](/fr/docs/Web/JavaScript/Guide/Expressions_and_Operators). -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</p> +{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}} diff --git a/files/fr/learn/javascript/first_steps/silly_story_generator/index.md b/files/fr/learn/javascript/first_steps/silly_story_generator/index.md index 298aef0296..e8d8789c62 100644 --- a/files/fr/learn/javascript/first_steps/silly_story_generator/index.md +++ b/files/fr/learn/javascript/first_steps/silly_story_generator/index.md @@ -3,141 +3,123 @@ title: Générateur d'histoires absurdes slug: Learn/JavaScript/First_steps/Silly_story_generator translation_of: Learn/JavaScript/First_steps/Silly_story_generator --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> - -<p>Dans cette évaluation, vous aurez pour tâche d'utiliser les connaissances que vous avez apprises dans les articles de ce module et de les appliquer dans le but de créer une appli ludique qui génère des histoires absurdes au hasard. Amusez-vous bien !</p> +Dans cette évaluation, vous aurez pour tâche d'utiliser les connaissances que vous avez apprises dans les articles de ce module et de les appliquer dans le but de créer une appli ludique qui génère des histoires absurdes au hasard. Amusez-vous bien ! <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td> - <p>Avant de vous lancer dans cette évaluation, vous devez avoir déjà travaillé sur tous les articles de ce module.</p> - </td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td> - <p>Tester la compréhension des fondamentaux JavaScript tels que les variables, les nombres, les opérateurs, les chaînes de caractères et les tableaux.</p> - </td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + <p> + Avant de vous lancer dans cette évaluation, vous devez avoir déjà + travaillé sur tous les articles de ce module. + </p> + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + <p> + Tester la compréhension des fondamentaux JavaScript tels que les + variables, les nombres, les opérateurs, les chaînes de caractères et + les tableaux. + </p> + </td> + </tr> + </tbody> </table> -<h2 id="Point_de_départ">Point de départ</h2> +## Point de départ + +Pour commencer cette évaluation : + +- Allez [chercher le fichier HTML](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/index.html) d'exemple et enregistrez-en une copie locale sous le nom `index.html` dans un nouveau dossier quelque part sur votre ordinateur. Ce fichier contient également la CSS pour mettre en forme l'exemple qui l'accompagne. +- Allez sur la [page qui contient le texte brut](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/raw-text.txt) et gardez la fenêtre ouverte dans un onglet différent de votre navigateur. Vous en aurez besoin plus tard. + +> **Note :** Vous pouvez aussi utiliser un site tel que que [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/) pour votre évaluation. Vous pouvez copier-coller le HTML, CSS et JavaScript vers l'un de ces éditeurs en ligne. Si l'éditeur en ligne que vous utilisez ne propose pas d'onglet JavaScript séparé, n'hésitez pas à en intégrer un dans une balise `<script>` au sein de la page HTML. + +## Résumé du projet + +On vous a fourni du code HTML/CSS brut ainsi que quelques chaînes de caractères et fonctions JavaScript : vous devez écrire le code JavaScript nécessaire pour transformer ces éléments en un programme fonctionnel, qui fera les choses suivantes : + +- Générer une histoire absurde quand on appuie sur le bouton "Generate random story" (Générer une histoire au hasard). +- Remplacer dans l'histoire le nom par défaut "Bob" par un nom personnalisé, dans le cas où le champ "Enter custom name" (Entrer un nom personnalisé) a été complété avant que le bouton "Générer" soit déclenché. +- Convertir les unités de poids et de température par défaut (américaines) vers leurs équivalents britanniques si le boutton "radio UK" a été coché avant que le bouton "Générer" soit déclenché. +- Générer une nouvelle histoire absurde au hasard quand on appuie à nouveau sur le bouton (et encore une, et encore une...) + +Les captures d'écran suivantes montrent un exemple de ce que le programme terminé doit afficher : + + + +Pour vous faire une idée un peu plus précise, [jetez un œil à l'exemple terminé](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/assessment-finished/) (mais sans regarder le code source !) + +## Les étapes + +Les sections suivantes décrivent ce que vous devez faire : + +Installation basique : + +1. Créez un nouveau fichier nommé `main.js`, dans le même dossier que `index.html` file. +2. Appliquez le fichier JavaScript externe à votre code HTML en insérant une balise {{htmlelement("script")}} dans votre code HTML en référençant `main.js`. Mettez-la juste avant de refermer la balise `</body>`. + +Variables initiales et fonctions : + +1. Dans le fichier de texte brut, copiez tout le code présent sous le titre "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" et collez-le en haut du fichier `main`. Cela vous donne trois variables qui stockent les références respectivement vers le champ "Enter custom name", vers le bouton "Generate random story" (`randomize`), et vers la balise {{htmlelement("p")}} en bas du corps HTML dans lequel l'histoire sera copiée (`story`). Par ailleurs, vous avez une fonction appelée `randomValueFromArray() `qui prend une table, et qui renvoie au hasard l'un des éléments qu'elle contient. +2. Maintenant regardons la deuxième section du fichier de texte brut : "2. RAW TEXT STRINGS". Cette section contient des chaînes de caractères qui vont se comporter comme des entrées (_input_) dans notre program. L'idée est que vous intégriez ces variables internes dans `main.js`: + + 1. Stockez la première longue chaîne de caractères (string) dans la variable `storyText`. + 2. Stockez le premier groupe de trois strings dans le tableau `insertX`. + 3. Stockez le deuxième groupe de trois strings dans le tableau `insertY`. + 4. Stockez le troisième groupe de trois strings dans une tableau `insertZ`. + +Mettre en place le gestionnaire d'événements (_event handler_) et le squelette de la fonction : + +1. Retournez au fichier de texte brut. +2. Copiez le code qui se trouve sous le titre "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" et collez-le en bas de votre fichier `main.js` principal. Cela : + + - Ajoute un gestionnaire d'événements pour les clics à la variable `randomize` de telle sorte que quand on clique sur le bouton associé, la fonction `result()` se lance. + - Ajoute une définition partiellement complète de la fonction `result()` à votre code. Pour le reste de l'évaluation, vous compléterez des lignes au sein de cette fonction pour la compléter et la faire fonctionner correctement. + +Compléter la fonction `result()` : + +1. Créer une nouvelle variable nommée `newStory`, et fixer sa valeur pour qu'elle soit égale à `storyText`. C'est nécessaire pour que soit créée une nouvelle histoire au hasard à chaque fois qu'on appuiera sur le bouton "Generate" et que la fonction sera lancée. Si on apportait des modifications directement à `storyText`, on ne pourrait générer une nouvelle histoire qu'une seule fois. +2. Créer trois nouvelles variables nommées `xItem`, `yItem`, et `zItem`, et faites en sorte qu'elles soient égales au résultat de l'appel de `randomValueFromArray()` sur vos trois tables (le résultat dans chaque cas fera apparaître un élément au hasard en provenance de chacune des tables appelées). Par exemple, vous pouvez appeler la fonction et lui faire retourner une chaîne de caractères au hasard depuis `insertX` en écrivant `randomValueFromArray(insertX)`. +3. Ensuite nous allons remplacer les trois fichiers temporaires dans la chaîne `newStory` — `:insertx:`, `:inserty:`, et `:insertz:` — par les chaînes stockées dans `xItem`, `yItem`, and `zItem`. Ici, une méthode particulière de chaînes pourra vous aider : dans chaque cas, faites que l'appel à la méthode soit égal à `newStory`, de sorte qu'à chaque appel, `newStory` est égal à lui-même, mais avec les substitutions effectuées. Ainsi, à chaque fois qu'on appuiera sur le bouton, ces fichiers temporaires seront chacun remplacés par une chaîne de caractères absurdes au hasard. Pour information, la méthode en question remplace seulement la première séquence de sous-chaîne qu'elle trouve, donc vous devrez peut-être l'un des appels deux fois. +4. Dans le premier block `if`, ajoutez une autre méthode de remplacement de chaîne pour remplacer le nom 'Bob' que vous trouverez dans la chaîne `newStory` en tant que variable `name`. Dans ce block, on établit que "Si une valeur a été entrée dans le champ `customName` text input, on remplacera dans l'histoire le mot Bob par ce nom personnalisé". +5. Dans le deuxième block `if`, on vérifie que le bouton radio `uk` a été coché. Si c'est le cas, nous voulons convertir les valeurs de poids et de température de l'histoire. Les pounds et les farenheit deviennent des stones et des centigrades. Procédez comme suit : + + 1. Cherchez la formule pour convertir les pounds en stones et les fareinheit en centigrades. + 2. Dans la ligne qui définit la variable `weight` (poids), remplacez 300 par un calcul qui convertit 300 pounds en stones. Le tout englobé dans un `Math.round()` à la fin duquel vous concatenez `'stone'`. + 3. Dans la ligne qui définit la variable `temperature`, remplacez 94 par un calcul qui convertit 94 fahrenheit en centigrades. Le tout englobé dans un `Math.round()` à la fin duquel vous concatenez` 'centigrade'`. + 4. Juste sous la définition des deux variables, ajoutez deux lignes de remplacement de chaînes supplémentaires qui remplacent '94 farhenheit' par les contenus de la variable `temperature`, et '300 pounds' par les contenus de la variable `weight`. + +6. Enfin, dans l'antépénultième ligne de la fonction, faites en sorte que la propriété `textContent` de la variable `story` (qui référence le paragraphe) soit égale à `newStory`. + +## Trucs et astuces + +- Aucun besoin de modifier le code HTML, à part pour lui appliquer le JavaScript. +- Si vous n'êtes pas sûr que le JavaScript est correctement appliqué à votre HTML, essayez de supprimer temporairement tout le contenu du fichier JavaScript, et d'y ajouter un morceau très simple de code JavaScript dont vous savez qu'il aura un effet visible, puis sauvegardez et rafraîchissez. Par exemple, le morceau de code suivant fait que l'arrière plan de la balise {{htmlelement("html")}} devient rouge — donc toute la fenêtre du navigateur devrait devenir rouge si le JavaScript est correctement appliqué : +- ```js + document.querySelector('html').style.backgroundColor = 'red'; + ``` +- [Math.round()](/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/round) est une méthode JavaScript intégrée qui arrondit simplement le résultat d'un calcul à l'entier le plus proche. + +## Évaluation + +Si vous suivez cette évaluation dans le cadre d'un cours organisé, vous devriez pouvoir soumettre votre travail à votre enseignant/encadrant pour être évalué. Si vous êtes autodidacte, vous pouvez facilement obtenir le guide de notation en vous adressant à la mailing list [dev-mdc](https://lists.mozilla.org/listinfo/dev-mdc) ou au canal IRC [#mdn](irc://irc.mozilla.org/mdn) sur [Mozilla IRC](https://wiki.mozilla.org/IRC). Essayez de faire l'exercice d'abord — vous ne gagnez rien à tricher ! -<p>Pour commencer cette évaluation :</p> +{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}} -<ul> - <li>Allez <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/index.html">chercher le fichier HTML</a> d'exemple et enregistrez-en une copie locale sous le nom <code>index.html</code> dans un nouveau dossier quelque part sur votre ordinateur. Ce fichier contient également la CSS pour mettre en forme l'exemple qui l'accompagne.</li> - <li>Allez sur la <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/raw-text.txt">page qui contient le texte brut</a> et gardez la fenêtre ouverte dans un onglet différent de votre navigateur. Vous en aurez besoin plus tard.</li> -</ul> +## Dans ce module -<div class="note"> -<p><strong>Note :</strong> Vous pouvez aussi utiliser un site tel que que <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a> pour votre évaluation. Vous pouvez copier-coller le HTML, CSS et JavaScript vers l'un de ces éditeurs en ligne. Si l'éditeur en ligne que vous utilisez ne propose pas d'onglet JavaScript séparé, n'hésitez pas à en intégrer un dans une balise <code><script></code> au sein de la page HTML.</p> -</div> - -<h2 id="Résumé_du_projet">Résumé du projet</h2> - -<p>On vous a fourni du code HTML/CSS brut ainsi que quelques chaînes de caractères et fonctions JavaScript : vous devez écrire le code JavaScript nécessaire pour transformer ces éléments en un programme fonctionnel, qui fera les choses suivantes :</p> - -<ul> - <li>Générer une histoire absurde quand on appuie sur le bouton "Generate random story" (Générer une histoire au hasard).</li> - <li>Remplacer dans l'histoire le nom par défaut "Bob" par un nom personnalisé, dans le cas où le champ "Enter custom name" (Entrer un nom personnalisé) a été complété avant que le bouton "Générer" soit déclenché.</li> - <li>Convertir les unités de poids et de température par défaut (américaines) vers leurs équivalents britanniques si le boutton "radio UK" a été coché avant que le bouton "Générer" soit déclenché.</li> - <li>Générer une nouvelle histoire absurde au hasard quand on appuie à nouveau sur le bouton (et encore une, et encore une...)</li> -</ul> - -<p>Les captures d'écran suivantes montrent un exemple de ce que le programme terminé doit afficher :</p> - -<p><img alt="" src="assessment-1.png"></p> - -<p>Pour vous faire une idée un peu plus précise, <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/assessment-finished/">jetez un œil à l'exemple terminé</a> (mais sans regarder le code source !)</p> - -<h2 id="Les_étapes">Les étapes</h2> - -<p>Les sections suivantes décrivent ce que vous devez faire :</p> - -<p>Installation basique :</p> - -<ol> - <li>Créez un nouveau fichier nommé <code>main.js</code>, dans le même dossier que <code>index.html</code> file.</li> - <li>Appliquez le fichier JavaScript externe à votre code HTML en insérant une balise {{htmlelement("script")}} dans votre code HTML en référençant <code>main.js</code>. Mettez-la juste avant de refermer la balise <code></body></code>.</li> -</ol> - -<p>Variables initiales et fonctions :</p> - -<ol> - <li>Dans le fichier de texte brut, copiez tout le code présent sous le titre "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" et collez-le en haut du fichier <code>main</code>. Cela vous donne trois variables qui stockent les références respectivement vers le champ "Enter custom name", vers le bouton "Generate random story" (<code>randomize</code>), et vers la balise {{htmlelement("p")}} en bas du corps HTML dans lequel l'histoire sera copiée (<code>story</code>). Par ailleurs, vous avez une fonction appelée <code>randomValueFromArray() </code>qui prend une table, et qui renvoie au hasard l'un des éléments qu'elle contient.</li> - <li>Maintenant regardons la deuxième section du fichier de texte brut : "2. RAW TEXT STRINGS". Cette section contient des chaînes de caractères qui vont se comporter comme des entrées (<em>input</em>) dans notre program. L'idée est que vous intégriez ces variables internes dans <code>main.js</code>: - <ol> - <li>Stockez la première longue chaîne de caractères (string) dans la variable <code>storyText</code>.</li> - <li>Stockez le premier groupe de trois strings dans le tableau <code>insertX</code>.</li> - <li>Stockez le deuxième groupe de trois strings dans le tableau <code>insertY</code>.</li> - <li>Stockez le troisième groupe de trois strings dans une tableau <code>insertZ</code>.</li> - </ol> - </li> -</ol> - -<p>Mettre en place le gestionnaire d'événements (<em>event handler</em>) et le squelette de la fonction :</p> - -<ol> - <li>Retournez au fichier de texte brut.</li> - <li>Copiez le code qui se trouve sous le titre "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" et collez-le en bas de votre fichier <code>main.js</code> principal. Cela : - <ul> - <li>Ajoute un gestionnaire d'événements pour les clics à la variable <code>randomize</code> de telle sorte que quand on clique sur le bouton associé, la fonction <code>result()</code> se lance.</li> - <li>Ajoute une définition partiellement complète de la fonction <code>result()</code> à votre code. Pour le reste de l'évaluation, vous compléterez des lignes au sein de cette fonction pour la compléter et la faire fonctionner correctement.</li> - </ul> - </li> -</ol> - -<p>Compléter la fonction <code>result()</code> :</p> - -<ol> - <li>Créer une nouvelle variable nommée <code>newStory</code>, et fixer sa valeur pour qu'elle soit égale à <code>storyText</code>. C'est nécessaire pour que soit créée une nouvelle histoire au hasard à chaque fois qu'on appuiera sur le bouton "Generate" et que la fonction sera lancée. Si on apportait des modifications directement à <code>storyText</code>, on ne pourrait générer une nouvelle histoire qu'une seule fois.</li> - <li>Créer trois nouvelles variables nommées <code>xItem</code>, <code>yItem</code>, et <code>zItem</code>, et faites en sorte qu'elles soient égales au résultat de l'appel de <code>randomValueFromArray()</code> sur vos trois tables (le résultat dans chaque cas fera apparaître un élément au hasard en provenance de chacune des tables appelées). Par exemple, vous pouvez appeler la fonction et lui faire retourner une chaîne de caractères au hasard depuis <code>insertX</code> en écrivant <code>randomValueFromArray(insertX)</code>.</li> - <li>Ensuite nous allons remplacer les trois fichiers temporaires dans la chaîne <code>newStory</code> — <code>:insertx:</code>, <code>:inserty:</code>, et <code>:insertz:</code> — par les chaînes stockées dans <code>xItem</code>, <code>yItem</code>, and <code>zItem</code>. Ici, une méthode particulière de chaînes pourra vous aider : dans chaque cas, faites que l'appel à la méthode soit égal à <code>newStory</code>, de sorte qu'à chaque appel, <code>newStory</code> est égal à lui-même, mais avec les substitutions effectuées. Ainsi, à chaque fois qu'on appuiera sur le bouton, ces fichiers temporaires seront chacun remplacés par une chaîne de caractères absurdes au hasard. Pour information, la méthode en question remplace seulement la première séquence de sous-chaîne qu'elle trouve, donc vous devrez peut-être l'un des appels deux fois.</li> - <li>Dans le premier block <code>if</code>, ajoutez une autre méthode de remplacement de chaîne pour remplacer le nom 'Bob' que vous trouverez dans la chaîne <code>newStory</code> en tant que variable <code>name</code>. Dans ce block, on établit que "Si une valeur a été entrée dans le champ <code>customName</code> text input, on remplacera dans l'histoire le mot Bob par ce nom personnalisé".</li> - <li>Dans le deuxième block <code>if</code>, on vérifie que le bouton radio <code>uk</code> a été coché. Si c'est le cas, nous voulons convertir les valeurs de poids et de température de l'histoire. Les pounds et les farenheit deviennent des stones et des centigrades. Procédez comme suit : - <ol> - <li>Cherchez la formule pour convertir les pounds en stones et les fareinheit en centigrades.</li> - <li>Dans la ligne qui définit la variable <code>weight</code> (poids), remplacez 300 par un calcul qui convertit 300 pounds en stones. Le tout englobé dans un <code>Math.round()</code> à la fin duquel vous concatenez <code>'stone'</code>.</li> - <li>Dans la ligne qui définit la variable <code>temperature</code>, remplacez 94 par un calcul qui convertit 94 fahrenheit en centigrades. Le tout englobé dans un <code>Math.round()</code> à la fin duquel vous concatenez<code> 'centigrade'</code>.</li> - <li>Juste sous la définition des deux variables, ajoutez deux lignes de remplacement de chaînes supplémentaires qui remplacent '94 farhenheit' par les contenus de la variable <code>temperature</code>, et '300 pounds' par les contenus de la variable <code>weight</code>.</li> - </ol> - </li> - <li>Enfin, dans l'antépénultième ligne de la fonction, faites en sorte que la propriété <code>textContent</code> de la variable <code>story</code> (qui référence le paragraphe) soit égale à <code>newStory</code>.</li> -</ol> - -<h2 id="Trucs_et_astuces">Trucs et astuces</h2> - -<ul> - <li>Aucun besoin de modifier le code HTML, à part pour lui appliquer le JavaScript.</li> - <li>Si vous n'êtes pas sûr que le JavaScript est correctement appliqué à votre HTML, essayez de supprimer temporairement tout le contenu du fichier JavaScript, et d'y ajouter un morceau très simple de code JavaScript dont vous savez qu'il aura un effet visible, puis sauvegardez et rafraîchissez. Par exemple, le morceau de code suivant fait que l'arrière plan de la balise {{htmlelement("html")}} devient rouge — donc toute la fenêtre du navigateur devrait devenir rouge si le JavaScript est correctement appliqué :</li> - <li> - <pre class="brush: js">document.querySelector('html').style.backgroundColor = 'red';</pre> - </li> - <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/round">Math.round()</a> est une méthode JavaScript intégrée qui arrondit simplement le résultat d'un calcul à l'entier le plus proche.</li> -</ul> - -<h2 id="Évaluation">Évaluation</h2> - -<p>Si vous suivez cette évaluation dans le cadre d'un cours organisé, vous devriez pouvoir soumettre votre travail à votre enseignant/encadrant pour être évalué. Si vous êtes autodidacte, vous pouvez facilement obtenir le guide de notation en vous adressant à la mailing list <a href="https://lists.mozilla.org/listinfo/dev-mdc">dev-mdc</a> ou au canal IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> sur <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Essayez de faire l'exercice d'abord — vous ne gagnez rien à tricher !</p> - -<p>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> - -<h2 id="Dans_ce_module">Dans ce module</h2> - -<ul> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript">What is JavaScript?</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/A_first_splash">A first splash into JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Variables">Storing the information you need — Variables</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Math">Basic math in JavaScript — numbers and operators</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Strings">Handling text — strings in JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator">Assessment: Silly story generator</a></li> -</ul> +- [What is JavaScript?](/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript) +- [A first splash into JavaScript](/fr/docs/Learn/JavaScript/First_steps/A_first_splash) +- [What went wrong? Troubleshooting JavaScript](/fr/docs/Learn/JavaScript/First_steps/What_went_wrong) +- [Storing the information you need — Variables](/fr/docs/Learn/JavaScript/First_steps/Variables) +- [Basic math in JavaScript — numbers and operators](/fr/docs/Learn/JavaScript/First_steps/Math) +- [Handling text — strings in JavaScript](/fr/docs/Learn/JavaScript/First_steps/Strings) +- [Useful string methods](/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods) +- [Arrays](/fr/docs/Learn/JavaScript/First_steps/Arrays) +- [Assessment: Silly story generator](/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator) diff --git a/files/fr/learn/javascript/first_steps/strings/index.md b/files/fr/learn/javascript/first_steps/strings/index.md index 457cf98379..beaac08ec1 100644 --- a/files/fr/learn/javascript/first_steps/strings/index.md +++ b/files/fr/learn/javascript/first_steps/strings/index.md @@ -3,41 +3,46 @@ title: Gérer du texte — les chaînes de caractères en JavaScript slug: Learn/JavaScript/First_steps/Strings translation_of: Learn/JavaScript/First_steps/Strings --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</div> - -<p>Concentrons-nous maintenant sur les chaînes de caractères - c'est le nom donné à un segment de texte en programmation. Dans cet article, nous aborderons les aspects les plus communs des chaînes de caractères que vous devez vraiment connaître quand vous apprenez JavaScript, comme créer une chaîne de caractères, échapper des guillemets dans une chaîne ou encore concaténer des chaînes.</p> +Concentrons-nous maintenant sur les chaînes de caractères - c'est le nom donné à un segment de texte en programmation. Dans cet article, nous aborderons les aspects les plus communs des chaînes de caractères que vous devez vraiment connaître quand vous apprenez JavaScript, comme créer une chaîne de caractères, échapper des guillemets dans une chaîne ou encore concaténer des chaînes. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Connaissance de base en informatique, une compréhension basique de HTML et CSS et savoir ce qu'est JavaScript.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Devenir familier avec les fondamentaux pour manipuler les chaînes de caractères en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Connaissance de base en informatique, une compréhension basique de HTML + et CSS et savoir ce qu'est JavaScript. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Devenir familier avec les fondamentaux pour manipuler les chaînes de + caractères en JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Le_pouvoir_des_mots">Le pouvoir des mots</h2> +## Le pouvoir des mots -<p>Les mots ont beaucoup d'importance pour les humains — ils occupent une large part dans nos façons de communiquer. Comme le Web est un medium essentiellement fondé sur du texte conçu pour permettre aux hommes de communiquer et partager de l'information, il est utile de contrôler les mots qui y sont publiés. {{glossary("HTML")}} donne structure et sens au texte, {{glossary("CSS")}} en gère le style et JavaScript comporte une série de fonctionnalités pour manipuler les chaînes de caractères, créer des messages d'accueil personnalisés, afficher la bonne étiquette quand nécessaire, trier des termes dans l'ordre voulu, et bien d'autres choses encore.</p> +Les mots ont beaucoup d'importance pour les humains — ils occupent une large part dans nos façons de communiquer. Comme le Web est un medium essentiellement fondé sur du texte conçu pour permettre aux hommes de communiquer et partager de l'information, il est utile de contrôler les mots qui y sont publiés. {{glossary("HTML")}} donne structure et sens au texte, {{glossary("CSS")}} en gère le style et JavaScript comporte une série de fonctionnalités pour manipuler les chaînes de caractères, créer des messages d'accueil personnalisés, afficher la bonne étiquette quand nécessaire, trier des termes dans l'ordre voulu, et bien d'autres choses encore. -<p>À peu près tous les programmes que nous vous avons montrés jusqu'ici ont impliqué des manipulations de chaînes de caractères.</p> +À peu près tous les programmes que nous vous avons montrés jusqu'ici ont impliqué des manipulations de chaînes de caractères. -<h2 id="Chaînes_de_caractères_—_les_bases">Chaînes de caractères — les bases</h2> +## Chaînes de caractères — les bases -<p>À première vue, les chaînes se traitent de la même manière que les nombres ; mais si vous approfondissez la chose, vous commencerez à percevoir des différences notables. Entrons sur la console quelques lignes simples pour nous familiariser avec la chose. À propos de la console, nous en avons placé une ci‑dessous (vous pouvez <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">l'ouvrir</a> dans un onglet ou une fenêtre séparée, ou bien utiliser celle de <a href="/fr/docs/Learn/Common_questions/What_are_browser_developer_tools">l'explorateur, </a>comme vous préférez).</p> +À première vue, les chaînes se traitent de la même manière que les nombres ; mais si vous approfondissez la chose, vous commencerez à percevoir des différences notables. Entrons sur la console quelques lignes simples pour nous familiariser avec la chose. À propos de la console, nous en avons placé une ci‑dessous (vous pouvez [l'ouvrir](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html) dans un onglet ou une fenêtre séparée, ou bien utiliser celle de [l'explorateur, ](/fr/docs/Learn/Common_questions/What_are_browser_developer_tools)comme vous préférez). -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>JavaScript console</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> * { box-sizing: border-box; } @@ -85,14 +90,14 @@ translation_of: Learn/JavaScript/First_steps/Strings clear: both; } - </style> - </head> - <body> + </style> + </head> + <body> - </body> + </body> - <script> + <script> let geval = eval; function createInput() { let inputDiv = document.createElement('div'); @@ -100,12 +105,12 @@ translation_of: Learn/JavaScript/First_steps/Strings let inputForm = document.createElement('input'); inputDiv.setAttribute('class','input'); - inputPara.textContent = '>'; + inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); - if(document.querySelectorAll('div').length > 1) { + if(document.querySelectorAll('div').length > 1) { inputForm.focus(); } @@ -135,130 +140,176 @@ translation_of: Learn/JavaScript/First_steps/Strings createInput(); - </script> -</html></pre> - -<p>{{ EmbedLiveSample('Chaînes_de_caractères_—_les_bases', '100%', 300) }}</p> - -<h3 id="Créer_une_chaîne_de_texte">Créer une chaîne de texte</h3> - -<ol> - <li>Pour débuter, entrez les lignes suivantes : - <pre class="brush: js">let string = 'La révolution ne sera pas télévisée.'; -string;</pre> - Comme nous l'avons fait avec les nombres, nous déclarons une variable, l'initialisons avec une valeur de chaîne, puis renvoyons la valeur. La seule différence ici est que lorsque nous écrivons une chaîne, nous la mettons entre guillemets.</li> - <li>Si vous ne le faites pas, ou si vous oubliez un des guillemets, vous déclenchez une erreur. Essayez d'entrer une de ces lignes : - <pre class="brush: js example-bad">let badString = Voici un test; -let badString = 'Voici un test; -let badString = Voici un test';</pre> - Ces lignes de code ne fonctionnent pas parce que toute chaîne de texte qui n'est pas écrite entre guillemets est considérée comme un nom de variable, un nom de propriété, un mot réservé ou quelque chose de semblable. Quand l'interpréteur ne parvient pas à trouver la déclaration de ladite variable, une erreur est déclenchée (par ex. « missing ; before statement »). Si l'interpréteur voit le début d'une chaîne mais ne trouve pas sa fin, comme dans la ligne 2, il se plaint en émettant une erreur (avec « <em>unterminated string literal</em> »). Si votre programme produit de telles erreurs, revoyez‑le et vérifiez qu'aucun guillemet ne manque.</li> - <li>L'assertion suivante fonctionne si la variable <code>string</code> a été préalablement définie — essayez maintenant : - <pre class="brush: js">let badString = string; -badString;</pre> - <code>badString</code> est maintenant défini avec la même valeur que <code>string</code>.</li> -</ol> - -<h3 id="Guillemets_simples_vs_guillemets_doubles">Guillemets simples vs guillemets doubles</h3> - -<ol> - <li>En JavaScript, vous pouvez envelopper vos chaînes entre des guillemets simples ou doubles. Les deux expressions suivantes sont correctes : - <pre class="brush: js">let sgl = 'Guillemet simple.'; -let dbl = "Guillemets doubles."; -sgl; -dbl;</pre> - </li> - <li>Il y a une toute petite différence entre les deux, et celle que vous retenez relève de la préférence personnelle. Prenez-en une, et tenez‑vous y toutefois : du code avec des mises entre guillemets diversifiées peut amener des confusions, en particulier si vous utilisez les deux sortes dans la même chaîne ! Ce qui suit renvoie une erreur : - <pre class="brush: js example-bad">let badQuotes = 'Quoi sur Terre ?";</pre> - </li> - <li>L'interpréteur pensera que la chaîne n'a pas été fermée, car le type de guillemet autre ne servant pas à délimiter les chaînes peut y être employé. Par exemple, ces deux assertions sont valables : - <pre class="brush: js">let sglDbl = 'Mangeriez‑vous un "souper de poisson"?'; -let dblSgl = "J'ai le blues."; -sglDbl; -dblSgl;</pre> - </li> - <li>Bien entendu, vous ne pouvez pas inclure dans la chaîne le même type de guillemet que celui qui est utilisé pour la délimiter. Ce qui suit conduit à une erreur, car l'explorateur ne peut pas déterminer là où se termine la chaîne : - <pre class="brush: js example-bad">let bigmouth = 'Je n'ai pas eu droit à prendre place...';</pre> - Voilà qui nous amène naturellement au prochain sujet.</li> -</ol> - -<h3 id="Échappement_de_caractères_dans_une_chaîne">Échappement de caractères dans une chaîne</h3> - -<p>Pour corriger l'erreur dans notre ligne de code précédente, il nous suffit d'échapper au problème que pose le guillemet. « Échapper des caractères » signifie que nous les marquons de manière à ce qu'ils soient reconnus comme partie intégrante du texte, et non pas comme symbole de code. Dans JavaScript, nous le faisons en mettant une barre oblique inverse juste avant le caractère. Essayons :</p> - -<pre class="brush: js">let bigmouth = 'Je n\'ai pas eu droit à prendre place...'; -bigmouth;</pre> - -<p>Cela fonctionne à la perfection. Vous pouvez échapper d'autres caractères de la même manière, par ex. <code>\"</code>, et il y a certains codes spéciaux à côté. Voyez <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String#escape_notation">Notations d'échappement</a> pour plus de détails.</p> - -<h2 id="Concaténation_de_chaînes">Concaténation de chaînes</h2> - -<ol> - <li>Concaténer est un terme de programmation du genre chic qui signifie « attacher ensemble ». Pour attacher des chaînes en JavaScript, on utilise l'opérateur plus (+) , le même que l'on utilise pour ajouter deux nombres, mais dans ce contexte il fait quelque chose de différent. Voyons un exemple dans la console. - <pre class="brush: js">let one = 'Hello, '; -let two = 'comment allez‑vous ?'; -let joined = one + two; -joined;</pre> - Il en résulte que la variable nommée <code>joined</code> contient la valeur "Hello, comment allez‑vous ?".</li> - <li>Dans le dernier exemple, nous avons juste attaché deux chaînes ensemble, mais vous pouvez en attacher autant que vous voulez, pour autant que vous mettiez un signe <code>+</code> entre chacune. Essayez ceci : - <pre class="brush: js">let multiple = one + one + one + one + two; -multiple;</pre> - </li> - <li>Vous pouvez aussi mélanger des variables avec des vraies chaînes. Regardez : - <pre class="brush: js">let response = one + 'Je vais bien — et vous ' + two; -response;</pre> - </li> -</ol> - -<div class="note"> -<p><strong>Note :</strong> Quand vous entrez une chaîne dans votre code, entre guillemets simples ou doubles, on l'appelle <strong>chaîne littérale</strong>.</p> -</div> - -<h3 id="Concaténation_dans_un_contexte">Concaténation dans un contexte</h3> - -<p>Examinons une concaténation dans une action — voici un exemple tiré en amont de ce cours :</p> - -<pre class="brush: html"><button>Pressez‑moi</button></pre> - -<pre class="brush: js">let button = document.querySelector('button'); + </script> +</html> +``` + +{{ EmbedLiveSample('Chaînes_de_caractères_—_les_bases', '100%', 300) }} + +### Créer une chaîne de texte + +1. Pour débuter, entrez les lignes suivantes : + + ```js + let string = 'La révolution ne sera pas télévisée.'; + string; + ``` + + Comme nous l'avons fait avec les nombres, nous déclarons une variable, l'initialisons avec une valeur de chaîne, puis renvoyons la valeur. La seule différence ici est que lorsque nous écrivons une chaîne, nous la mettons entre guillemets. + +2. Si vous ne le faites pas, ou si vous oubliez un des guillemets, vous déclenchez une erreur. Essayez d'entrer une de ces lignes : + + ```js example-bad + let badString = Voici un test; + let badString = 'Voici un test; + let badString = Voici un test'; + ``` + + Ces lignes de code ne fonctionnent pas parce que toute chaîne de texte qui n'est pas écrite entre guillemets est considérée comme un nom de variable, un nom de propriété, un mot réservé ou quelque chose de semblable. Quand l'interpréteur ne parvient pas à trouver la déclaration de ladite variable, une erreur est déclenchée (par ex. « missing ; before statement »). Si l'interpréteur voit le début d'une chaîne mais ne trouve pas sa fin, comme dans la ligne 2, il se plaint en émettant une erreur (avec « *unterminated string literal* »). Si votre programme produit de telles erreurs, revoyez‑le et vérifiez qu'aucun guillemet ne manque. + +3. L'assertion suivante fonctionne si la variable `string` a été préalablement définie — essayez maintenant : + + ```js + let badString = string; + badString; + ``` + + `badString` est maintenant défini avec la même valeur que `string`. + +### Guillemets simples vs guillemets doubles + +1. En JavaScript, vous pouvez envelopper vos chaînes entre des guillemets simples ou doubles. Les deux expressions suivantes sont correctes : + + ```js + let sgl = 'Guillemet simple.'; + let dbl = "Guillemets doubles."; + sgl; + dbl; + ``` + +2. Il y a une toute petite différence entre les deux, et celle que vous retenez relève de la préférence personnelle. Prenez-en une, et tenez‑vous y toutefois : du code avec des mises entre guillemets diversifiées peut amener des confusions, en particulier si vous utilisez les deux sortes dans la même chaîne ! Ce qui suit renvoie une erreur : + + ```js example-bad + let badQuotes = 'Quoi sur Terre ?"; + ``` + +3. L'interpréteur pensera que la chaîne n'a pas été fermée, car le type de guillemet autre ne servant pas à délimiter les chaînes peut y être employé. Par exemple, ces deux assertions sont valables : + + ```js + let sglDbl = 'Mangeriez‑vous un "souper de poisson"?'; + let dblSgl = "J'ai le blues."; + sglDbl; + dblSgl; + ``` + +4. Bien entendu, vous ne pouvez pas inclure dans la chaîne le même type de guillemet que celui qui est utilisé pour la délimiter. Ce qui suit conduit à une erreur, car l'explorateur ne peut pas déterminer là où se termine la chaîne : + + ```js example-bad + let bigmouth = 'Je n'ai pas eu droit à prendre place...'; + ``` + + Voilà qui nous amène naturellement au prochain sujet. + +### Échappement de caractères dans une chaîne + +Pour corriger l'erreur dans notre ligne de code précédente, il nous suffit d'échapper au problème que pose le guillemet. « Échapper des caractères » signifie que nous les marquons de manière à ce qu'ils soient reconnus comme partie intégrante du texte, et non pas comme symbole de code. Dans JavaScript, nous le faisons en mettant une barre oblique inverse juste avant le caractère. Essayons : + +```js +let bigmouth = 'Je n\'ai pas eu droit à prendre place...'; +bigmouth; +``` + +Cela fonctionne à la perfection. Vous pouvez échapper d'autres caractères de la même manière, par ex. `\"`, et il y a certains codes spéciaux à côté. Voyez [Notations d'échappement](/fr/docs/Web/JavaScript/Reference/Global_Objects/String#escape_notation) pour plus de détails. + +## Concaténation de chaînes + +1. Concaténer est un terme de programmation du genre chic qui signifie « attacher ensemble ». Pour attacher des chaînes en JavaScript, on utilise l'opérateur plus (+) , le même que l'on utilise pour ajouter deux nombres, mais dans ce contexte il fait quelque chose de différent. Voyons un exemple dans la console. + + ```js + let one = 'Hello, '; + let two = 'comment allez‑vous ?'; + let joined = one + two; + joined; + ``` + + Il en résulte que la variable nommée `joined` contient la valeur "Hello, comment allez‑vous ?". + +2. Dans le dernier exemple, nous avons juste attaché deux chaînes ensemble, mais vous pouvez en attacher autant que vous voulez, pour autant que vous mettiez un signe `+` entre chacune. Essayez ceci : + + ```js + let multiple = one + one + one + one + two; + multiple; + ``` + +3. Vous pouvez aussi mélanger des variables avec des vraies chaînes. Regardez : + + ```js + let response = one + 'Je vais bien — et vous ' + two; + response; + ``` + +> **Note :** Quand vous entrez une chaîne dans votre code, entre guillemets simples ou doubles, on l'appelle **chaîne littérale**. + +### Concaténation dans un contexte + +Examinons une concaténation dans une action — voici un exemple tiré en amont de ce cours : + +```html +<button>Pressez‑moi</button> +``` + +```js +let button = document.querySelector('button'); button.onclick = function() { let name = prompt('Quel est votre nom ?'); alert('Hello ' + name + ', sympa de vous voir !'); -}</pre> - -<p>{{ EmbedLiveSample('Concaténation_dans_un_contexte', '100%', 50) }}</p> - -<p>Ici nous utilisons en ligne 4 la fonction {{domxref("Window.prompt()", "Window.prompt()")}}, qui demande à l'utilisateur de répondre à une question par l'intermédiaire d'une boîte de dialogue, puis qui stocke le texte entré dans une variable donnée — dans ce cas <code>name</code>. En ligne 5, nous nous servons de la fonction {{domxref("Window.alert()", "Window.alert()")}} pour afficher un dialogue contenant une chaîne assemblée à partir de deux chaînes littérales et de la variable <code>name</code>, par concaténation.</p> - -<h3 id="Nombres_vs_chaînes">Nombres vs chaînes</h3> - -<ol> - <li>Que se passe-t-il quand nous essayons d'additionner (ou concaténer) une chaîne et un nombre ? Essayons dans la console : - <pre class="brush: js">'Front ' + 242; -</pre> - Vous vous attendriez à déclencher une erreur, mais cela fonctionne parfaitement. Essayer de représenter une chaîne comme un nombre n'a vraiment aucun sens, mais représenter un nombre par une chaîne en a, donc le navigateur convertit adroitement le nombre en chaîne et concatène les deux chaînes.</li> - <li>Vous pouvez même faire cela avec deux nombres — vous forcez un nombre à devenir une chaîne en le mettant entre guillemets. Essayez ce qui suit (nous nous servons de l'opérateur <code>typeof</code> pour vérifier si la variable est un nombre ou une chaîne): - <pre class="brush: js">let myDate = '19' + '67'; -typeof myDate;</pre> - </li> - <li>Si vous avez une variable numérique que vous souhaitez convertir en chaîne sans autre modification, ou une variable numérique que vous voulez convertir en chaîne sans autre modification, vous pouvez utiliser les constructions suivantes : - <ul> - <li>L'objet {{jsxref("Number")}} convertit tout ce qui lui est passé en nombre, si c'est possible. Essayez : - <pre class="brush: js">let myString = '123'; -let myNum = Number(myString); -typeof myNum;</pre> - </li> - <li>D'autre part, tout nombre possède une méthode nommée <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number/toString">toString()</a></code> qui le convertit en chaîne équivalente. Essayez : - <pre class="brush: js">let myNum = 123; -let myString = myNum.toString(); -typeof myString;</pre> - </li> - </ul> - Ces constructions peuvent être vraiment utiles en certaines circonstances. Par exemple, si un utilisateur entre un nombre dans un champ texte d'un formulaire, c'est une chaîne. Mais si vous voulez ajouter ce nombre à autre chose, il est nécessaire qu'il soit du type <code>number</code>, donc vous pouvez le faire passer par la méthode <code>Number()</code> pour gérer cela. C'est exactement ce que nous avons fait dans le jeu <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html#L63">Devinez un nombre, à la ligne 63</a>.</li> -</ol> - -<h2 id="Conclusion">Conclusion</h2> - -<p>Voilà donc les bases de la manipulation des chaînes de caractères en JavaScript. Dans le prochain article, nous allons bâtir sur ces éléments en examinant certaines méthodes intégrées disponibles pour les chaînes de caractères dans JavaScript et en les utilisant pour mettre les chaînes de caractères dans la forme voulue.</p> - -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</p> +} +``` + +{{ EmbedLiveSample('Concaténation_dans_un_contexte', '100%', 50) }} + +Ici nous utilisons en ligne 4 la fonction {{domxref("Window.prompt()", "Window.prompt()")}}, qui demande à l'utilisateur de répondre à une question par l'intermédiaire d'une boîte de dialogue, puis qui stocke le texte entré dans une variable donnée — dans ce cas `name`. En ligne 5, nous nous servons de la fonction {{domxref("Window.alert()", "Window.alert()")}} pour afficher un dialogue contenant une chaîne assemblée à partir de deux chaînes littérales et de la variable `name`, par concaténation. + +### Nombres vs chaînes + +1. Que se passe-t-il quand nous essayons d'additionner (ou concaténer) une chaîne et un nombre ? Essayons dans la console : + + ```js + 'Front ' + 242; + ``` + + Vous vous attendriez à déclencher une erreur, mais cela fonctionne parfaitement. Essayer de représenter une chaîne comme un nombre n'a vraiment aucun sens, mais représenter un nombre par une chaîne en a, donc le navigateur convertit adroitement le nombre en chaîne et concatène les deux chaînes. + +2. Vous pouvez même faire cela avec deux nombres — vous forcez un nombre à devenir une chaîne en le mettant entre guillemets. Essayez ce qui suit (nous nous servons de l'opérateur `typeof` pour vérifier si la variable est un nombre ou une chaîne): + + ```js + let myDate = '19' + '67'; + typeof myDate; + ``` + +3. Si vous avez une variable numérique que vous souhaitez convertir en chaîne sans autre modification, ou une variable numérique que vous voulez convertir en chaîne sans autre modification, vous pouvez utiliser les constructions suivantes : + + - L'objet {{jsxref("Number")}} convertit tout ce qui lui est passé en nombre, si c'est possible. Essayez : + + ```js + let myString = '123'; + let myNum = Number(myString); + typeof myNum; + ``` + + - D'autre part, tout nombre possède une méthode nommée [`toString()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Number/toString) qui le convertit en chaîne équivalente. Essayez : + + ```js + let myNum = 123; + let myString = myNum.toString(); + typeof myString; + ``` + + Ces constructions peuvent être vraiment utiles en certaines circonstances. Par exemple, si un utilisateur entre un nombre dans un champ texte d'un formulaire, c'est une chaîne. Mais si vous voulez ajouter ce nombre à autre chose, il est nécessaire qu'il soit du type `number`, donc vous pouvez le faire passer par la méthode `Number()` pour gérer cela. C'est exactement ce que nous avons fait dans le jeu [Devinez un nombre, à la ligne 63](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html#L63). + +## Conclusion + +Voilà donc les bases de la manipulation des chaînes de caractères en JavaScript. Dans le prochain article, nous allons bâtir sur ces éléments en examinant certaines méthodes intégrées disponibles pour les chaînes de caractères dans JavaScript et en les utilisant pour mettre les chaînes de caractères dans la forme voulue. + +{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}} diff --git a/files/fr/learn/javascript/first_steps/test_your_skills_colon__arrays/index.md b/files/fr/learn/javascript/first_steps/test_your_skills_colon__arrays/index.md index a281723a68..6fd00343ae 100644 --- a/files/fr/learn/javascript/first_steps/test_your_skills_colon__arrays/index.md +++ b/files/fr/learn/javascript/first_steps/test_your_skills_colon__arrays/index.md @@ -10,84 +10,67 @@ tags: translation_of: Learn/JavaScript/First_steps/Test_your_skills:_Arrays original_slug: Learn/JavaScript/First_steps/Testes_vos_competence:_Tableaux --- -<div>{{learnsidebar}}</div> +{{learnsidebar}} -<p>L'objectif de ce test est d'évaluer votre compréhension <a href="/fr/docs/Learn/JavaScript/First_steps/Arrays">de l'article sur les tableaux en JavaScript (<i>arrays</i>)</a>.</p> +L'objectif de ce test est d'évaluer votre compréhension [de l'article sur les tableaux en JavaScript (_arrays_)](/fr/docs/Learn/JavaScript/First_steps/Arrays). -<div class="note"> -<p><strong>Note :</strong> Vous pouvez essayer vos solutions dans les éditeurs interactifs qui suivent. Toutefois, il peut aussi être utile de télécharger le code et d'utiliser un outil en ligne comme <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a> afin de travailler sur ces tâches.</p> -<p>Si vous vous retrouvez bloqué·e, vous pouvez demander de l'aide (voir <a href="#assessment_or_further_help">la section à ce sujet en fin de page</a>).</p> -</div> +> **Note :** Vous pouvez essayer vos solutions dans les éditeurs interactifs qui suivent. Toutefois, il peut aussi être utile de télécharger le code et d'utiliser un outil en ligne comme [CodePen](https://codepen.io/), [jsFiddle](https://jsfiddle.net/), ou [Glitch](https://glitch.com/) afin de travailler sur ces tâches. +> +> Si vous vous retrouvez bloqué·e, vous pouvez demander de l'aide (voir [la section à ce sujet en fin de page](#assessment_or_further_help)). -<div class="note"> -<p><strong>Note :</strong> Dans les exemples qui suivent, s'il y a une erreur dans votre code, celle-ci s'affichera dans le panneau des résultats, sur la page, afin de vous aider à trouver la solution (ou bien dans la console JavaScript du navigateur si vous utilisez la version téléchargeable).</p> -</div> +> **Note :** Dans les exemples qui suivent, s'il y a une erreur dans votre code, celle-ci s'affichera dans le panneau des résultats, sur la page, afin de vous aider à trouver la solution (ou bien dans la console JavaScript du navigateur si vous utilisez la version téléchargeable). -<h2 id="arrays_1">Tableaux - Exercice 1</h2> +## Tableaux - Exercice 1 -<p>Commençons par quelques manipulations de base. Dans cet exercice, vous devrez créer un tableau avec trois éléments. Ce tableau devra être stocké dans une variable intitulée <code>myArray</code>. Les éléments du tableau peuvent être n'importe quoi (si vous avez besoin d'inspiration : pourquoi ne pas utiliser vos plats ou vos groupes de musique préférés ?).</p> +Commençons par quelques manipulations de base. Dans cet exercice, vous devrez créer un tableau avec trois éléments. Ce tableau devra être stocké dans une variable intitulée `myArray`. Les éléments du tableau peuvent être n'importe quoi (si vous avez besoin d'inspiration : pourquoi ne pas utiliser vos plats ou vos groupes de musique préférés ?). -<p>Ensuite, modifiez les deux premiers éléments du tableau en utilisant la notation avec les guillemets/quotes et des opérations d'affectation. Puis ajoutez un nouvel élément au début du tableau.</p> +Ensuite, modifiez les deux premiers éléments du tableau en utilisant la notation avec les guillemets/quotes et des opérations d'affectation. Puis ajoutez un nouvel élément au début du tableau. -<p>Vous pouvez mettre à jour le code suivant pour parvenir à la solution :</p> +Vous pouvez mettre à jour le code suivant pour parvenir à la solution : -<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/arrays/arrays1.html", '100%', 400)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/arrays/arrays1.html", '100%', 400)}} -<div class="note"> -<p><strong>Note :</strong> <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/arrays/arrays1-download.html">Téléchargez le code initial pour cet exercice</a> afin de travailler dans votre éditeur sur votre ordinateur ou sur un éditeur en ligne.</p> -</div> +> **Note :** [Téléchargez le code initial pour cet exercice](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/arrays/arrays1-download.html) afin de travailler dans votre éditeur sur votre ordinateur ou sur un éditeur en ligne. -<h2 id="arrays_2">Tableaux - Exercice 2</h2> +## Tableaux - Exercice 2 -<p>Voyons maintenant un autre exercice. Ici, vous avez une chaîne de caractères sur laquelle travailler. Vous devrez :</p> +Voyons maintenant un autre exercice. Ici, vous avez une chaîne de caractères sur laquelle travailler. Vous devrez : -<ol> - <li>Convertir la chaîne de caractères en un tableau tout en retirant les caractères <code>+</code> lors de la conversion. Stockez ensuite le résultat dans une variable intitulée <code>myArray</code>.</li> - <li>Stocker la longueur du tableau dans une variable intitulée <code>arrayLength</code>.</li> - <li>Stocker le dernier élément du tableau dans une variable intitulée <code>lastItem</code>.</li> -</ol> +1. Convertir la chaîne de caractères en un tableau tout en retirant les caractères `+` lors de la conversion. Stockez ensuite le résultat dans une variable intitulée `myArray`. +2. Stocker la longueur du tableau dans une variable intitulée `arrayLength`. +3. Stocker le dernier élément du tableau dans une variable intitulée `lastItem`. -<p>Essayez de mettre à jour le code qui suit pour parvenir à la solution :</p> +Essayez de mettre à jour le code qui suit pour parvenir à la solution : -<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/arrays/arrays2.html", '100%', 400)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/arrays/arrays2.html", '100%', 400)}} -<div class="note"> -<p><strong>Note :</strong> <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/arrays/arrays2-download.html">Téléchargez le code initial pour cet exercice</a> afin de travailler dans votre éditeur sur votre ordinateur ou sur un éditeur en ligne.</p> -</div> +> **Note :** [Téléchargez le code initial pour cet exercice](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/arrays/arrays2-download.html) afin de travailler dans votre éditeur sur votre ordinateur ou sur un éditeur en ligne. -<h2 id="Arrays_3">Tableaux - Exercice 3</h2> +## Tableaux - Exercice 3 -<p>Dans ce dernier exercice, vous disposez d'un tableau de départ et vous devrez effectuer les opérations inverses de l'exercice précédent. Voici ce qu'il faudra réaliser :</p> +Dans ce dernier exercice, vous disposez d'un tableau de départ et vous devrez effectuer les opérations inverses de l'exercice précédent. Voici ce qu'il faudra réaliser : -<ol> - <li>Retirer le dernier élément du tableau.</li> - <li>Ajouter deux nouveaux noms à la fin du tableau.</li> - <li>Parcourir chaque élément du tableau et ajouter son indice, entre parenthèses, après le nom (par exemple <code>Ryu (0)</code>). Note : ceci n'est pas indiqué dans l'article sur les tableaux, il vous faudra rechercher comment faire.</li> - <li>Enfin, fusionner les éléments du tableau dans une chaîne de caractères intitulée <code>myString</code> en utilisant "<code> - </code>" comme séparateur.</li> -</ol> +1. Retirer le dernier élément du tableau. +2. Ajouter deux nouveaux noms à la fin du tableau. +3. Parcourir chaque élément du tableau et ajouter son indice, entre parenthèses, après le nom (par exemple `Ryu (0)`). Note : ceci n'est pas indiqué dans l'article sur les tableaux, il vous faudra rechercher comment faire. +4. Enfin, fusionner les éléments du tableau dans une chaîne de caractères intitulée `myString` en utilisant "` - `" comme séparateur. -<p>Essayez de mettre à jour le code qui suit pour parvenir à la solution :</p> +Essayez de mettre à jour le code qui suit pour parvenir à la solution : -<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/arrays/arrays3.html", '100%', 400)}}</p> +{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/arrays/arrays3.html", '100%', 400)}} -<div class="note"> -<p><strong>Note :</strong> <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/arrays/arrays3-download.html">Téléchargez le code initial pour cet exercice</a> afin de travailler dans votre éditeur sur votre ordinateur ou sur un éditeur en ligne.</p> -</div> +> **Note :** [Téléchargez le code initial pour cet exercice](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/arrays/arrays3-download.html) afin de travailler dans votre éditeur sur votre ordinateur ou sur un éditeur en ligne. -<h2 id="assessment_or_further_help">Recevoir une évaluation ou de l'aide</h2> +## Recevoir une évaluation ou de l'aide -<p>Vous pouvez vous exercer sur ces exemples grâce aux éditeurs interactifs de la page.</p> +Vous pouvez vous exercer sur ces exemples grâce aux éditeurs interactifs de la page. -<p>Si vous souhaitez faire évaluer votre travail ou si vous êtes bloqué·e et que vous voulez demander de l'aide :</p> +Si vous souhaitez faire évaluer votre travail ou si vous êtes bloqué·e et que vous voulez demander de l'aide : -<ol> - <li>Enregistrez votre travail dans un éditeur en ligne tel que <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a> pour le partager. Vous pouvez écrire le code vous-même ou utiliser les fichiers téléchargeables indiqués comme point de départ.</li> - <li>Rédigez un message pour la demande d'aide ou d'évaluation sur <a href="https://discourse.mozilla.org/c/mdn/learn">la catégorie <i>Learning</i> du forum Discourse de MDN</a>. Votre billet devrait inclure : - <ul> - <li>Un titre descriptif comme « Évaluation demandée pour le test Tableaux JavaScript ».</li> - <li>Des détails sur ce que vous avez déjà tenté et sur quels aspects vous avez besoin d'aide si vous bloquez.</li> - <li>Un lien vers l'exemple que vous voulez évaluer ou sur lequel vous avez besoin d'aide. Ce lien doit pointer vers un éditeur en ligne (voir l'étape 1). Il s'agit ici d'une bonne pratique pour commencer : il est souvent difficile d'aider quelqu'un si on ne peut pas voir le code.</li> - <li>Un lien vers la page MDN pour la tâche ou l'évaluation afin que nous puissions trouver la question sur laquelle vous avez besoin d'aide.</li> - </ul> - </li> -</ol> +1. Enregistrez votre travail dans un éditeur en ligne tel que [CodePen](https://codepen.io/), [jsFiddle](https://jsfiddle.net/), ou [Glitch](https://glitch.com/) pour le partager. Vous pouvez écrire le code vous-même ou utiliser les fichiers téléchargeables indiqués comme point de départ. +2. Rédigez un message pour la demande d'aide ou d'évaluation sur [la catégorie _Learning_ du forum Discourse de MDN](https://discourse.mozilla.org/c/mdn/learn). Votre billet devrait inclure : + + - Un titre descriptif comme « Évaluation demandée pour le test Tableaux JavaScript ». + - Des détails sur ce que vous avez déjà tenté et sur quels aspects vous avez besoin d'aide si vous bloquez. + - Un lien vers l'exemple que vous voulez évaluer ou sur lequel vous avez besoin d'aide. Ce lien doit pointer vers un éditeur en ligne (voir l'étape 1). Il s'agit ici d'une bonne pratique pour commencer : il est souvent difficile d'aider quelqu'un si on ne peut pas voir le code. + - Un lien vers la page MDN pour la tâche ou l'évaluation afin que nous puissions trouver la question sur laquelle vous avez besoin d'aide. diff --git a/files/fr/learn/javascript/first_steps/useful_string_methods/index.md b/files/fr/learn/javascript/first_steps/useful_string_methods/index.md index f2e52aa169..0ff7cd44d7 100644 --- a/files/fr/learn/javascript/first_steps/useful_string_methods/index.md +++ b/files/fr/learn/javascript/first_steps/useful_string_methods/index.md @@ -17,43 +17,51 @@ tags: translation_of: Learn/JavaScript/First_steps/Useful_string_methods original_slug: Learn/JavaScript/First_steps/methode_chaine_utile --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> - -<p>À présent que nous avons vu les bases de la manipulation des chaînes de caractères, allons un cran plus loin et commençons à imaginer les opérations utiles que nous pourrions faire sur les chaînes de caractères avec les méthodes intégrées : trouver la longueur d'une chaîne, assembler ou couper des chaînes, substituer un caractère à un autre dans une chaîne, et plus encore.</p> +À présent que nous avons vu les bases de la manipulation des chaînes de caractères, allons un cran plus loin et commençons à imaginer les opérations utiles que nous pourrions faire sur les chaînes de caractères avec les méthodes intégrées : trouver la longueur d'une chaîne, assembler ou couper des chaînes, substituer un caractère à un autre dans une chaîne, et plus encore. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Vocabulaire courant de l'informatique, bases de HTML et CSS, compréhension de ce que fait JavaScript.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre que les chaînes de caractères sont des objets, et apprendre à utiliser certaines méthodes basiques disponibles sur ces objets pour manipuler les chaînes.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Vocabulaire courant de l'informatique, bases de HTML et CSS, + compréhension de ce que fait JavaScript. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Comprendre que les chaînes de caractères sont des objets, et apprendre à + utiliser certaines méthodes basiques disponibles sur ces objets pour + manipuler les chaînes. + </td> + </tr> + </tbody> </table> -<h2 id="Les_chaînes_de_caractères_sont_des_objets">Les chaînes de caractères sont des objets</h2> +## Les chaînes de caractères sont des objets -<p>Nous l'avons déjà dit, et nous le redirons — <em>tout</em> est objet en JavaScript. Lorsque vous créez une chaîne, par exemple en utilisant :</p> +Nous l'avons déjà dit, et nous le redirons — _tout_ est objet en JavaScript. Lorsque vous créez une chaîne, par exemple en utilisant : -<pre class="brush: js">let string = 'Ceci est une chaîne';</pre> +```js +let string = 'Ceci est une chaîne'; +``` -<p>votre variable devient une instance de l'objet <code>String</code>, et par conséquent possède un grand nombre de propriétés et de méthodes associées. Allez sur la page de l'objet {{jsxref("String")}} et regardez la liste sur le côté de la page !</p> +votre variable devient une instance de l'objet `String`, et par conséquent possède un grand nombre de propriétés et de méthodes associées. Allez sur la page de l'objet {{jsxref("String")}} et regardez la liste sur le côté de la page ! -<p><strong>Avant que votre cervelle ne commence à bouillir, pas de panique !</strong> Vous n'avez vraiment pas besoin de connaître la plupart des méthodes de cette liste au début de cet apprentissage. Mais il est probable que vous utiliserez certaines assez souvent. Nous allons les voir maintenant.</p> +**Avant que votre cervelle ne commence à bouillir, pas de panique !** Vous n'avez vraiment pas besoin de connaître la plupart des méthodes de cette liste au début de cet apprentissage. Mais il est probable que vous utiliserez certaines assez souvent. Nous allons les voir maintenant. -<p>Entrez quelques exemples dans une console vierge. En voici une ci-dessous (vous pouvez aussi <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">ouvrir cette console</a> dans un onglet ou une fenêtre séparés, ou utiliser la <a href="/fr/docs/Learn/Common_questions/What_are_browser_developer_tools">console de développement du navigateur</a> si vous préférez).</p> +Entrez quelques exemples dans une console vierge. En voici une ci-dessous (vous pouvez aussi [ouvrir cette console](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html) dans un onglet ou une fenêtre séparés, ou utiliser la [console de développement du navigateur](/fr/docs/Learn/Common_questions/What_are_browser_developer_tools) si vous préférez). -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>JavaScript console</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> * { box-sizing: border-box; } @@ -101,14 +109,14 @@ original_slug: Learn/JavaScript/First_steps/methode_chaine_utile clear: both; } - </style> - </head> - <body> + </style> + </head> + <body> - </body> + </body> - <script> + <script> var geval = eval; function createInput() { var inputDiv = document.createElement('div'); @@ -116,7 +124,7 @@ original_slug: Learn/JavaScript/First_steps/methode_chaine_utile var inputForm = document.createElement('input'); inputDiv.setAttribute('class', 'input'); - inputPara.textContent = '>'; + inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); @@ -147,106 +155,131 @@ original_slug: Learn/JavaScript/First_steps/methode_chaine_utile createInput(); - </script> -</html></pre> + </script> +</html> +``` -<p>{{ EmbedLiveSample('Les_chaînes_de_caractères_sont_des_objets', '100%', 300) }}</p> +{{ EmbedLiveSample('Les_chaînes_de_caractères_sont_des_objets', '100%', 300) }} -<h3 id="Trouver_la_longueur_dune_chaîne">Trouver la longueur d'une chaîne</h3> +### Trouver la longueur d'une chaîne -<p>C'est facile — il suffit d'utiliser la propriété {{jsxref("String.prototype.length", "length")}}. Entrez ceci :</p> +C'est facile — il suffit d'utiliser la propriété {{jsxref("String.prototype.length", "length")}}. Entrez ceci : -<pre class="brush: js">let browserType = 'mozilla'; -browserType.length;</pre> +```js +let browserType = 'mozilla'; +browserType.length; +``` -<p>Cette commande doit renvoyer le nombre 7, parce que « mozilla » comporte 7 caractères. C'est utile pour de nombreuses raisons ; par exemple, vous pourriez avoir besoin de trouver les longueurs d'une série de noms pour les afficher par taille ou faire savoir à un utilisateur qu'il a entré un nom trop long dans un champ de formulaire à partir du moment où il dépasse une certaine taille.</p> +Cette commande doit renvoyer le nombre 7, parce que « mozilla » comporte 7 caractères. C'est utile pour de nombreuses raisons ; par exemple, vous pourriez avoir besoin de trouver les longueurs d'une série de noms pour les afficher par taille ou faire savoir à un utilisateur qu'il a entré un nom trop long dans un champ de formulaire à partir du moment où il dépasse une certaine taille. -<h3 id="Retrouver_un_caractère_donné_dans_une_chaîne">Retrouver un caractère donné dans une chaîne</h3> +### Retrouver un caractère donné dans une chaîne -<p>Dans le même ordre d'idées, il est possible de faire renvoyer tout caractère d'une chaîne avec <strong>la notation crochets</strong> — c'est-à-dire en ajoutant des crochets (<code>[]</code>) à la fin du nom de la variable. Entre les crochets, mettez le rang du caractère à retrouver ; par exemple, pour retrouver le premier caractère, vous devez écrire ceci :</p> +Dans le même ordre d'idées, il est possible de faire renvoyer tout caractère d'une chaîne avec **la notation crochets** — c'est-à-dire en ajoutant des crochets (`[]`) à la fin du nom de la variable. Entre les crochets, mettez le rang du caractère à retrouver ; par exemple, pour retrouver le premier caractère, vous devez écrire ceci : -<pre class="brush: js">browserType[0];</pre> +```js +browserType[0]; +``` -<p>Les ordinateurs décomptent à partir de 0, pas de 1 ! Pour retrouver le dernier caractère de <em>n'importe quelle</em> chaîne, on peut utiliser la commande qui suit ; elle combine cette technique avec la propriété <code>length</code> que nous avons vue plus haut :</p> +Les ordinateurs décomptent à partir de 0, pas de 1 ! Pour retrouver le dernier caractère de _n'importe quelle_ chaîne, on peut utiliser la commande qui suit ; elle combine cette technique avec la propriété `length` que nous avons vue plus haut : -<pre class="brush: js">browserType[browserType.length-1];</pre> +```js +browserType[browserType.length-1]; +``` -<p>La longueur de « mozilla » est de 7 caractères, mais comme le décompte se fait à partir de 0, la position du caractère est 6, d'où la nécessité d'écrire <code>length-1</code>. Vous pourrez utiliser cette propriété pour, par exemple, trouver la première lettre d'une série de chaînes et les trier alphabétiquement.</p> +La longueur de « mozilla » est de 7 caractères, mais comme le décompte se fait à partir de 0, la position du caractère est 6, d'où la nécessité d'écrire `length-1`. Vous pourrez utiliser cette propriété pour, par exemple, trouver la première lettre d'une série de chaînes et les trier alphabétiquement. -<h3 id="Trouver_une_sous-chaîne_à_lintérieur_dune_chaîne_et_lextraire">Trouver une sous-chaîne à l'intérieur d'une chaîne et l'extraire</h3> +### Trouver une sous-chaîne à l'intérieur d'une chaîne et l'extraire -<ol> - <li>Parfois, vous aurez besoin de trouver si une chaîne est présente à l'intérieur d'une autre chaîne plus grande (on dit en général <em>si une sous-chaîne est présente à l'intérieur d'une chaîne</em>). La méthode {{jsxref("String.prototype.indexOf()", "indexOf()")}} permet de le faire ; elle prend un unique ({{glossary("parameter")}}) — la sous-chaîne recherchée. Essayez : +1. Parfois, vous aurez besoin de trouver si une chaîne est présente à l'intérieur d'une autre chaîne plus grande (on dit en général _si une sous-chaîne est présente à l'intérieur d'une chaîne_). La méthode {{jsxref("String.prototype.indexOf()", "indexOf()")}} permet de le faire ; elle prend un unique ({{glossary("parameter")}}) — la sous-chaîne recherchée. Essayez : - <pre class="brush: js">browserType.indexOf('zilla');</pre> - La commande donne 2 comme résultat, car la sous-chaîne « zilla » commence à la position 2 (0, 1, 2 — donc au troisième caractère) dans « mozilla ». Un tel code s'utilise pour filtrer des chaînes. Par exemple, vous pourriez avoir une liste d'adresses web et ne vouloir afficher que celles qui contiennent « mozilla ».</li> - <li>On peut faire cela autrement, peut-être plus efficacement encore. Écrivez : - <pre class="brush: js">browserType.indexOf('vanilla');</pre> - Cela doit vous donner <code>-1</code> comme résultat — renvoyé quand la sous-chaîne, en l'occurence « vanilla », n'est pas trouvée dans la chaîne principale.<br> - <br> - Vous pouvez utiliser cette propriété pour trouver tous les cas de chaînes <strong>ne</strong> <strong>contenant</strong> <strong>pas</strong> la sous-chaîne « mozilla », ou bien <strong>la contenant</strong>, si vous utilisez l'opérateur négation logique, tel que montré ci-dessous. Vous pourriez faire quelque chose comme : + ```js + browserType.indexOf('zilla'); + ``` - <pre class="brush: js">if(browserType.indexOf('mozilla') !== -1) { - // faire des tas de choses avec la chaîne -}</pre> - </li> - <li>Lorsque vous savez où la sous-chaîne commence à l'intérieur de la chaîne, et savez à quel caractère elle prend fin, vous pouvez utiliser {{jsxref("String.prototype.slice()", "slice()")}} pour l'extraire. Voyez ce code : - <pre class="brush: js">browserType.slice(0,3);</pre> - Il renvoie « moz » — le premier paramètre est la position du caractère où doit commencer l'extraction, et le second paramètre est la position du caractère se trouvant après le dernier à extraire. Ainsi, l'extraction va de la première position à la dernière, celle-ci non comprise. On peut dire, dans notre cas, que le second paramètre est égal à la longueur de la chaîne retournée.</li> - <li>Également, si vous souhaitez extraire tous les caractères après un caractère donné jusqu'à la fin de la chaîne, vous n'avez pas à mettre le second paramètre ! Il suffit d'indiquer la position du caractère à partir duquel vous voulez extraire les caractères restants dans la chaîne. Essayez la commande : - <pre class="brush: js">browserType.slice(2);</pre> - Elle renvoie « zilla » — le caractère à la position 2 est « z » et comme nous n'avons pas mis de second paramètre, la sous-chaîne retournée comporte tous les caractères restants de la chaîne.</li> -</ol> + La commande donne 2 comme résultat, car la sous-chaîne « zilla » commence à la position 2 (0, 1, 2 — donc au troisième caractère) dans « mozilla ». Un tel code s'utilise pour filtrer des chaînes. Par exemple, vous pourriez avoir une liste d'adresses web et ne vouloir afficher que celles qui contiennent « mozilla ». -<div class="note"> -<p><strong>Note :</strong> Le second paramètre de <code>slice()</code> est optionnel : s'il n'est pas defini, l'extraction va jusqu'à la fin de la chaîne originale. Il existe aussi d'autres options, allez à la page de {{jsxref("String.prototype.slice()", "slice()")}} pour voir ces autres options.</p> -</div> +2. On peut faire cela autrement, peut-être plus efficacement encore. Écrivez : + + ```js + browserType.indexOf('vanilla'); + ``` + + Cela doit vous donner `-1` comme résultat — renvoyé quand la sous-chaîne, en l'occurence « vanilla », n'est pas trouvée dans la chaîne principale. + + Vous pouvez utiliser cette propriété pour trouver tous les cas de chaînes **ne** **contenant** **pas** la sous-chaîne « mozilla », ou bien **la contenant**, si vous utilisez l'opérateur négation logique, tel que montré ci-dessous. Vous pourriez faire quelque chose comme : + + ```js + if(browserType.indexOf('mozilla') !== -1) { + // faire des tas de choses avec la chaîne + } + ``` + +3. Lorsque vous savez où la sous-chaîne commence à l'intérieur de la chaîne, et savez à quel caractère elle prend fin, vous pouvez utiliser {{jsxref("String.prototype.slice()", "slice()")}} pour l'extraire. Voyez ce code : + + ```js + browserType.slice(0,3); + ``` + + Il renvoie « moz » — le premier paramètre est la position du caractère où doit commencer l'extraction, et le second paramètre est la position du caractère se trouvant après le dernier à extraire. Ainsi, l'extraction va de la première position à la dernière, celle-ci non comprise. On peut dire, dans notre cas, que le second paramètre est égal à la longueur de la chaîne retournée. + +4. Également, si vous souhaitez extraire tous les caractères après un caractère donné jusqu'à la fin de la chaîne, vous n'avez pas à mettre le second paramètre ! Il suffit d'indiquer la position du caractère à partir duquel vous voulez extraire les caractères restants dans la chaîne. Essayez la commande : -<h3 id="Changer_la_casse">Changer la casse</h3> + ```js + browserType.slice(2); + ``` -<p>Les méthodes {{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}} et {{jsxref("String.prototype.toUpperCase()", "toUpperCase()")}} s'appliquent à une chaîne et en convertissent tous les caractères, respectivement en minuscules ou en majuscules. C'est utile si, par exemple, vous souhaitez normaliser toutes les données entrées par des utilisateurs avant de les stocker dans une base de données.</p> + Elle renvoie « zilla » — le caractère à la position 2 est « z » et comme nous n'avons pas mis de second paramètre, la sous-chaîne retournée comporte tous les caractères restants de la chaîne. -<p>Essayons d'entrer les lignes suivantes et voyons ce qui se passe :</p> +> **Note :** Le second paramètre de `slice()` est optionnel : s'il n'est pas defini, l'extraction va jusqu'à la fin de la chaîne originale. Il existe aussi d'autres options, allez à la page de {{jsxref("String.prototype.slice()", "slice()")}} pour voir ces autres options. -<pre class="brush: js">let radData = 'My NaMe Is MuD'; +### Changer la casse + +Les méthodes {{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}} et {{jsxref("String.prototype.toUpperCase()", "toUpperCase()")}} s'appliquent à une chaîne et en convertissent tous les caractères, respectivement en minuscules ou en majuscules. C'est utile si, par exemple, vous souhaitez normaliser toutes les données entrées par des utilisateurs avant de les stocker dans une base de données. + +Essayons d'entrer les lignes suivantes et voyons ce qui se passe : + +```js +let radData = 'My NaMe Is MuD'; radData.toLowerCase(); -radData.toUpperCase();</pre> +radData.toUpperCase(); +``` -<h3 id="Actualiser_des_parties_de_chaîne">Actualiser des parties de chaîne</h3> +### Actualiser des parties de chaîne -<p>Vous pouvez remplacer une sous-chaîne à l'intérieur d'une chaîne avec une autre sous-chaîne à l'aide de la méthode {{jsxref("String.prototype.replace()", "replace()")}}. Cela fonctionne très simplement au niveau basique, bien qu'il soit possible de faire des choses plus avancées, mais nous ne y attarderons pas maintenant.</p> +Vous pouvez remplacer une sous-chaîne à l'intérieur d'une chaîne avec une autre sous-chaîne à l'aide de la méthode {{jsxref("String.prototype.replace()", "replace()")}}. Cela fonctionne très simplement au niveau basique, bien qu'il soit possible de faire des choses plus avancées, mais nous ne y attarderons pas maintenant. -<p>La méthode prend deux paramètres — la chaîne que vous voulez remplacer et la chaîne avec laquelle vous voulez la remplacer. Essayez avec cet exemple :</p> +La méthode prend deux paramètres — la chaîne que vous voulez remplacer et la chaîne avec laquelle vous voulez la remplacer. Essayez avec cet exemple : -<pre class="brush: js">browserType.replace('moz','van');</pre> +```js +browserType.replace('moz','van'); +``` -<p>À noter : pour que, dans un programme réel, la variable <code>browserType</code> reflète effectivement la valeur actualisée, il faut assigner à la valeur de la variable le résultat de l'opération ; cette dernière ne met pas à jour automatiquement la valeur de la sous-chaîne. Pour ce faire, il faut écrire :<code> browserType = browserType.replace('moz','van');</code></p> +À noter : pour que, dans un programme réel, la variable `browserType` reflète effectivement la valeur actualisée, il faut assigner à la valeur de la variable le résultat de l'opération ; cette dernière ne met pas à jour automatiquement la valeur de la sous-chaîne. Pour ce faire, il faut écrire :` browserType = browserType.replace('moz','van');` -<h2 id="Apprendre_en_pratiquant">Apprendre en pratiquant</h2> +## Apprendre en pratiquant -<p>Dans cette section, vous allez pouvoir vous entraîner à écrire du code de manipulation de chaîne. Dans chacun des exercices ci-dessous, nous avons un tableau de chaînes, une boucle qui traîte chaque valeur dans le tableau et l'affiche dans une liste à puces. Vous n'avez pas besoin de comprendre comment fonctionnent les tableaux ou les boucles dès maintenant — cela vous sera expliqué dans de prochains articles. Tout ce dont vous avez besoin dans chaque cas est d'écrire le code qui va renvoyer les chaînes dans le format souhaité.</p> +Dans cette section, vous allez pouvoir vous entraîner à écrire du code de manipulation de chaîne. Dans chacun des exercices ci-dessous, nous avons un tableau de chaînes, une boucle qui traîte chaque valeur dans le tableau et l'affiche dans une liste à puces. Vous n'avez pas besoin de comprendre comment fonctionnent les tableaux ou les boucles dès maintenant — cela vous sera expliqué dans de prochains articles. Tout ce dont vous avez besoin dans chaque cas est d'écrire le code qui va renvoyer les chaînes dans le format souhaité. -<p>Chaque exemple est accompagné d'un bouton « Réinitialiser », que vous pouvez utiliser pour réinitialiser le code si vous faites une erreur et que vous ne parvenez pas à la corriger, et un bouton « Montrer la solution » sur lequel vous pouvez cliquer pour afficher une réponse possible si jamais vous êtes vraiment bloqué.</p> +Chaque exemple est accompagné d'un bouton « Réinitialiser », que vous pouvez utiliser pour réinitialiser le code si vous faites une erreur et que vous ne parvenez pas à la corriger, et un bouton « Montrer la solution » sur lequel vous pouvez cliquer pour afficher une réponse possible si jamais vous êtes vraiment bloqué. -<h3 id="Filtrer_des_messages_de_vœux">Filtrer des messages de vœux</h3> +### Filtrer des messages de vœux -<p>Dans ce premier exercice, nous commencerons simplement — nous avons un tableau de carte de voeux, mais nous voulons les trier pour ne lister que les messages concernant Noël. Nous attendons de vous que vous utilisiez un test conditionnel à l'intérieur d'une structure <code>if( ... )</code>, pour tester chaque chaîne et ne l'afficher dans la liste que si elle contient un message concernant Noël.</p> +Dans ce premier exercice, nous commencerons simplement — nous avons un tableau de carte de voeux, mais nous voulons les trier pour ne lister que les messages concernant Noël. Nous attendons de vous que vous utilisiez un test conditionnel à l'intérieur d'une structure `if( ... )`, pour tester chaque chaîne et ne l'afficher dans la liste que si elle contient un message concernant Noël. -<ol> - <li>Réfléchissez d'abord à comment vérifier que le message concerne Noël. Quelle chaîne est présente dans tous ces messages, et quelle méthode pourriez-vous utiliser pour en tester la présence ?</li> - <li>Il vous faudra alors écrire un test conditionnel sous la forme <em>opérande1 opérateur opérande2</em>. La chose à gauche est-elle égale à la chose à droite ? Ou dans notre cas, l'appel de méthode de gauche renvoie-t-il le résultat de droite ?</li> - <li>Conseil : dans notre cas, il est probablement plus utile de tester si le résultat de l'appel de notre méthode <em>n'est pas égal</em> à un certain résultat.</li> -</ol> +1. Réfléchissez d'abord à comment vérifier que le message concerne Noël. Quelle chaîne est présente dans tous ces messages, et quelle méthode pourriez-vous utiliser pour en tester la présence ? +2. Il vous faudra alors écrire un test conditionnel sous la forme _opérande1 opérateur opérande2_. La chose à gauche est-elle égale à la chose à droite ? Ou dans notre cas, l'appel de méthode de gauche renvoie-t-il le résultat de droite ? +3. Conseil : dans notre cas, il est probablement plus utile de tester si le résultat de l'appel de notre méthode _n'est pas égal_ à un certain résultat. -<pre class="brush: html hidden"><div class="output" style="min-height: 125px;"> +```html hidden +<div class="output" style="min-height: 125px;"> -<ul> +<ul> -</ul> +</ul> -</div> +</div> -<textarea id="code" class="playable-code" style="height: 290px;"> +<textarea id="code" class="playable-code" style="height: 290px;"> var list = document.querySelector('.output ul'); list.innerHTML = ''; var greetings = ['Happy Birthday!', @@ -255,7 +288,7 @@ var greetings = ['Happy Birthday!', 'You\'re all I want for Christmas', 'Get well soon']; -for (var i = 0; i < greetings.length; i++) { +for (var i = 0; i < greetings.length; i++) { var input = greetings[i]; // Your conditional test needs to go inside the parentheses // in the line below, replacing what's currently there @@ -266,15 +299,16 @@ for (var i = 0; i < greetings.length; i++) { list.appendChild(listItem); } } -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: js hidden">var textarea = document.getElementById('code'); +```js hidden +var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; @@ -293,42 +327,39 @@ solution.addEventListener('click', function() { updateCode(); }); -var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar greetings = [\'Happy Birthday!\',\n \'Merry Christmas my love\',\n \'A happy Christmas to all the family\',\n \'You\\\'re all I want for Christmas\',\n \'Get well soon\'];\n\nfor(var i = 0; i < greetings.length; i++) {\n var input = greetings[i];\n if(greetings[i].indexOf(\'Christmas\') !== -1) {\n var result = input;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n }\n}'; +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar greetings = [\'Happy Birthday!\',\n \'Merry Christmas my love\',\n \'A happy Christmas to all the family\',\n \'You\\\'re all I want for Christmas\',\n \'Get well soon\'];\n\nfor(var i = 0; i < greetings.length; i++) {\n var input = greetings[i];\n if(greetings[i].indexOf(\'Christmas\') !== -1) {\n var result = input;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n }\n}'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Filtrer_des_messages_de_vœux', '100%', 490) }}</p> +{{ EmbedLiveSample('Filtrer_des_messages_de_vœux', '100%', 490) }} -<h3 id="Remettre_les_majuscules">Remettre les majuscules</h3> +### Remettre les majuscules -<p>Dans cet exercice, nous avons des noms des villes du Royaume-Uni, mais les majuscules ne sont pas au bon endroit. Nous souhaitons modifier les noms pour qu'ils soient en minuscules à l'exception de la première lettre qui doit être une majuscule. Une bonne manière de faire ceci :</p> +Dans cet exercice, nous avons des noms des villes du Royaume-Uni, mais les majuscules ne sont pas au bon endroit. Nous souhaitons modifier les noms pour qu'ils soient en minuscules à l'exception de la première lettre qui doit être une majuscule. Une bonne manière de faire ceci : -<ol> - <li>Convertissez la totalité de la chaîne contenue dans la variable <code>input</code> en minuscules et stockez-la dans une nouvelle variable.</li> - <li>Récupérez la première lettre de la chaîne dans cette nouvelle variable et stockez-la dans une autre variable.</li> - <li>En utilisant la dernière variable comme une sous-chaîne, remplacez la première lettre de la chaîne en minuscules par la première lettre de la chaîne en minuscules transformé en majuscules. Stockez le résultat de cette procédure de remplacement dans une autre nouvelle variable.</li> - <li>Changez la valeur de la variable <code>result</code> afin qu'elle soit égale au résultat final plutôt qu'à <code>input</code>.</li> -</ol> +1. Convertissez la totalité de la chaîne contenue dans la variable `input` en minuscules et stockez-la dans une nouvelle variable. +2. Récupérez la première lettre de la chaîne dans cette nouvelle variable et stockez-la dans une autre variable. +3. En utilisant la dernière variable comme une sous-chaîne, remplacez la première lettre de la chaîne en minuscules par la première lettre de la chaîne en minuscules transformé en majuscules. Stockez le résultat de cette procédure de remplacement dans une autre nouvelle variable. +4. Changez la valeur de la variable `result` afin qu'elle soit égale au résultat final plutôt qu'à `input`. -<div class="note"> -<p><strong>Note :</strong> Un conseil — les paramètres des méthodes de chaîne n'ont pas besoin d'être des chaînes, elle peuvent aussi être des variables, ou même des variables avec une méthode invoquée sur elles.</p> -</div> +> **Note :** Un conseil — les paramètres des méthodes de chaîne n'ont pas besoin d'être des chaînes, elle peuvent aussi être des variables, ou même des variables avec une méthode invoquée sur elles. -<pre class="brush: html hidden"><div class="output" style="min-height: 125px;"> +```html hidden +<div class="output" style="min-height: 125px;"> -<ul> +<ul> -</ul> +</ul> -</div> +</div> -<textarea id="code" class="playable-code" style="height: 250px;"> +<textarea id="code" class="playable-code" style="height: 250px;"> var list = document.querySelector('.output ul'); list.innerHTML = ''; var cities = ['lonDon', 'ManCHESTer', 'BiRmiNGHAM', 'liVERpoOL']; -for(var i = 0; i < cities.length; i++) { +for(var i = 0; i < cities.length; i++) { var input = cities[i]; // write your code just below here @@ -337,15 +368,16 @@ for(var i = 0; i < cities.length; i++) { listItem.textContent = result; list.appendChild(listItem); } -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: js hidden">var textarea = document.getElementById('code'); +```js hidden +var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; @@ -364,43 +396,42 @@ solution.addEventListener('click', function() { updateCode(); }); -var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar cities = [\'lonDon\', \'ManCHESTer\', \'BiRmiNGHAM\', \'liVERpoOL\'];\n\nfor(var i = 0; i < cities.length; i++) {\n var input = cities[i];\n var lower = input.toLowerCase();\n var firstLetter = lower.slice(0,1);\n var capitalized = lower.replace(firstLetter,firstLetter.toUpperCase());\n var result = capitalized;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n\n}'; +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar cities = [\'lonDon\', \'ManCHESTer\', \'BiRmiNGHAM\', \'liVERpoOL\'];\n\nfor(var i = 0; i < cities.length; i++) {\n var input = cities[i];\n var lower = input.toLowerCase();\n var firstLetter = lower.slice(0,1);\n var capitalized = lower.replace(firstLetter,firstLetter.toUpperCase());\n var result = capitalized;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n\n}'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Remettre_les_majuscules', '100%', 450) }}</p> +{{ EmbedLiveSample('Remettre_les_majuscules', '100%', 450) }} -<h3 id="Créer_de_nouvelles_chaînes_à_partir_de_morceaux">Créer de nouvelles chaînes à partir de morceaux</h3> +### Créer de nouvelles chaînes à partir de morceaux -<p>Dans ce dernier exercice, le tableau contient un lot de chaînes contenant des informations à propos d'arrêts de train dans le nord de l'Angleterre. Les chaînes sont des éléments de données contenant le code en trois lettres de l'arrêt, suivi par des données lisibles par machine, suivi par un point-virgule, et enfin le nom de la station lisible par un humain. Par exemple :</p> +Dans ce dernier exercice, le tableau contient un lot de chaînes contenant des informations à propos d'arrêts de train dans le nord de l'Angleterre. Les chaînes sont des éléments de données contenant le code en trois lettres de l'arrêt, suivi par des données lisibles par machine, suivi par un point-virgule, et enfin le nom de la station lisible par un humain. Par exemple : -<pre>MAN675847583748sjt567654;Manchester Piccadilly</pre> + MAN675847583748sjt567654;Manchester Piccadilly -<p>Nous voulons extraire le code de la station et son nom, et les associer dans une chaîne avec la structure suivante :</p> +Nous voulons extraire le code de la station et son nom, et les associer dans une chaîne avec la structure suivante : -<pre>MAN: Manchester Piccadilly</pre> + MAN: Manchester Piccadilly -<p>Nous vous recommandons de procéder de la manière suivante :</p> +Nous vous recommandons de procéder de la manière suivante : -<ol> - <li>Extraire le code de trois lettres de la station et le stocker dans une nouvelle variable.</li> - <li>Trouver la position du caractère point-virgule.</li> - <li>Extraire le nom de la station lisible par un humain en utilisant la position du caractère point virgule comme référence, et le stocker dans une nouvelle variable.</li> - <li>Concaténer les deux nouvelles variables et une chaîne pour fabriquer la chaîne finale.</li> - <li>Changer la valeur de la variable <code>result</code> pour qu'elle soit égale à la chaîne finale, plutôt qu'à <code>input</code>.</li> -</ol> +1. Extraire le code de trois lettres de la station et le stocker dans une nouvelle variable. +2. Trouver la position du caractère point-virgule. +3. Extraire le nom de la station lisible par un humain en utilisant la position du caractère point virgule comme référence, et le stocker dans une nouvelle variable. +4. Concaténer les deux nouvelles variables et une chaîne pour fabriquer la chaîne finale. +5. Changer la valeur de la variable `result` pour qu'elle soit égale à la chaîne finale, plutôt qu'à `input`. -<pre class="brush: html hidden"><div class="output" style="min-height: 125px;"> +```html hidden +<div class="output" style="min-height: 125px;"> -<ul> +<ul> -</ul> +</ul> -</div> +</div> -<textarea id="code" class="playable-code" style="height: 285px;"> +<textarea id="code" class="playable-code" style="height: 285px;"> var list = document.querySelector('.output ul'); list.innerHTML = ''; var stations = ['MAN675847583748sjt567654;Manchester Piccadilly', @@ -409,7 +440,7 @@ var stations = ['MAN675847583748sjt567654;Manchester Piccadilly', 'SYB4f65hf75f736463;Stalybridge', 'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield']; -for (var i = 0; i < stations.length; i++) { +for (var i = 0; i < stations.length; i++) { var input = stations[i]; // write your code just below here @@ -418,15 +449,16 @@ for (var i = 0; i < stations.length; i++) { listItem.textContent = result; list.appendChild(listItem); } -</textarea> +</textarea> -<div class="playable-buttons"> - <input id="reset" type="button" value="Reset"> - <input id="solution" type="button" value="Show solution"> -</div> -</pre> +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +``` -<pre class="brush: js hidden">var textarea = document.getElementById('code'); +```js hidden +var textarea = document.getElementById('code'); var reset = document.getElementById('reset'); var solution = document.getElementById('solution'); var code = textarea.value; @@ -445,17 +477,17 @@ solution.addEventListener('click', function() { updateCode(); }); -var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar stations = [\'MAN675847583748sjt567654;Manchester Piccadilly\',\n \'GNF576746573fhdg4737dh4;Greenfield\',\n \'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street\',\n \'SYB4f65hf75f736463;Stalybridge\',\n \'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield\'];\n\nfor(var i = 0; i < stations.length; i++) {\n var input = stations[i];\n var code = input.slice(0,3);\n var semiC = input.indexOf(\';\');\n var name = input.slice(semiC + 1);\n var result = code + \': \' + name;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n}'; +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar stations = [\'MAN675847583748sjt567654;Manchester Piccadilly\',\n \'GNF576746573fhdg4737dh4;Greenfield\',\n \'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street\',\n \'SYB4f65hf75f736463;Stalybridge\',\n \'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield\'];\n\nfor(var i = 0; i < stations.length; i++) {\n var input = stations[i];\n var code = input.slice(0,3);\n var semiC = input.indexOf(\';\');\n var name = input.slice(semiC + 1);\n var result = code + \': \' + name;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n}'; textarea.addEventListener('input', updateCode); window.addEventListener('load', updateCode); -</pre> +``` -<p>{{ EmbedLiveSample('Créer_de_nouvelles_chaînes_à_partir_de_morceaux', '100%', 485) }}</p> +{{ EmbedLiveSample('Créer_de_nouvelles_chaînes_à_partir_de_morceaux', '100%', 485) }} -<h2 id="Conclusion">Conclusion</h2> +## Conclusion -<p>Il n'est pas possible d'éluder le fait qu'il est très important de savoir manipuler des mots et des phrases lorsqu'on programme — tout particulièrement en JavaScript, dans la mesure où les sites web servent à la communication entre les personnes. Cet article vous a indiqué, pour l'instant, les bases à connaître pour manipuler les chaînes. Ce sera utile lorsque vous aborderez des sujets plus complexes à l'avenir. Pour suivre, nous allons nous intéresser au dernier grand type de données sur lequel nous devons nous concentrer à court terme — les tableaux.</p> +Il n'est pas possible d'éluder le fait qu'il est très important de savoir manipuler des mots et des phrases lorsqu'on programme — tout particulièrement en JavaScript, dans la mesure où les sites web servent à la communication entre les personnes. Cet article vous a indiqué, pour l'instant, les bases à connaître pour manipuler les chaînes. Ce sera utile lorsque vous aborderez des sujets plus complexes à l'avenir. Pour suivre, nous allons nous intéresser au dernier grand type de données sur lequel nous devons nous concentrer à court terme — les tableaux. -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> +{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}} diff --git a/files/fr/learn/javascript/first_steps/variables/index.md b/files/fr/learn/javascript/first_steps/variables/index.md index dacd075396..eee7f25dc7 100644 --- a/files/fr/learn/javascript/first_steps/variables/index.md +++ b/files/fr/learn/javascript/first_steps/variables/index.md @@ -3,51 +3,59 @@ title: Stocker les informations nécessaires — les variables slug: Learn/JavaScript/First_steps/Variables translation_of: Learn/JavaScript/First_steps/Variables --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}</div> - -<p>Après lecture des deux articles précédents, vous savez maintenant ce qu'est JavaScript, ce qu'il peut vous apporter, comment l'utiliser aux côtés d'autres technologies web et l'aspect de ses principales fonctionnalités vues de haut. Dans cet article, nous revenons aux fondements réels en examinant comment travailler avec le bloc de construction le plus basique du JavaScript — les variables.</p> +Après lecture des deux articles précédents, vous savez maintenant ce qu'est JavaScript, ce qu'il peut vous apporter, comment l'utiliser aux côtés d'autres technologies web et l'aspect de ses principales fonctionnalités vues de haut. Dans cet article, nous revenons aux fondements réels en examinant comment travailler avec le bloc de construction le plus basique du JavaScript — les variables. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Vocabulaire courant de l'informatique, bases de HTML et CSS, compréhension de ce que fait JavaScript.</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Se familiariser avec l'usage élémentaire des variables en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Vocabulaire courant de l'informatique, bases de HTML et CSS, + compréhension de ce que fait JavaScript. + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Se familiariser avec l'usage élémentaire des variables en JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Outils_nécessaires">Outils nécessaires</h2> +## Outils nécessaires -<p>Tout au long de cet article, on vous demandera de saisir des lignes de code pour tester votre compréhension. Si vous vous servez du navigateur avec un ordinateur de bureau, l'endroit le plus approprié pour saisir les exemples de code est la console JavaScript du navigateur (voyez <a href="/fr/docs/Learn/Common_questions/What_are_browser_developer_tools">Les outils de développement du navigateur</a> pour plus d'informations sur la manière d'accéder à ces outils).</p> +Tout au long de cet article, on vous demandera de saisir des lignes de code pour tester votre compréhension. Si vous vous servez du navigateur avec un ordinateur de bureau, l'endroit le plus approprié pour saisir les exemples de code est la console JavaScript du navigateur (voyez [Les outils de développement du navigateur](/fr/docs/Learn/Common_questions/What_are_browser_developer_tools) pour plus d'informations sur la manière d'accéder à ces outils). -<p>Toutefois, nous avons aussi incorporé une console JavaScript dans cette page pour vous permettre d'y écrire le code au cas où vous n'utiliseriez pas un navigateur avec une console JavaScript facilement accessible, ou si vous estimez qu'une console incorporée est plus confortable.</p> +Toutefois, nous avons aussi incorporé une console JavaScript dans cette page pour vous permettre d'y écrire le code au cas où vous n'utiliseriez pas un navigateur avec une console JavaScript facilement accessible, ou si vous estimez qu'une console incorporée est plus confortable. -<h2 id="Quest_ce_quune_variable">Qu'est ce qu'une variable ?</h2> +## Qu'est ce qu'une variable ? -<p>Une variable est un conteneur pour une valeur, tel un nombre à utiliser pour une addition, ou une chaîne devant faire partie d'une phrase. Mais un aspect spécial des variables est que les valeurs contenues peuvent changer. Voyons un exemple simple :</p> +Une variable est un conteneur pour une valeur, tel un nombre à utiliser pour une addition, ou une chaîne devant faire partie d'une phrase. Mais un aspect spécial des variables est que les valeurs contenues peuvent changer. Voyons un exemple simple : -<pre class="brush: html"><button>Pressez moi</button></pre> +```html +<button>Pressez moi</button> +``` -<pre class="brush: js">const button = document.querySelector('button'); +```js +const button = document.querySelector('button'); button.onclick = function() { let name = prompt('Quel est votre nom ?'); alert('Salut ' + name + ', sympa de vous voir !'); -}</pre> +} +``` -<p>{{ EmbedLiveSample('Quest_ce_quune_variable', '100%', 50) }}</p> +{{ EmbedLiveSample('Quest_ce_quune_variable', '100%', 50) }} -<p>Dans cet exemple, presser le bouton déclenche l'exécution de quelques lignes de code. La première ligne affiche à l'écran une boîte priant l'utilisateur de saisir son nom et stocke la valeur entrée dans une variable. La deuxième affiche un message de bienvenue avec la valeur de la variable.</p> +Dans cet exemple, presser le bouton déclenche l'exécution de quelques lignes de code. La première ligne affiche à l'écran une boîte priant l'utilisateur de saisir son nom et stocke la valeur entrée dans une variable. La deuxième affiche un message de bienvenue avec la valeur de la variable. -<p>Pour comprendre le pratique de la chose, imaginons comment nous aurions du coder cet exemple sans utiliser de variable. Serait-ce comme cela ?</p> +Pour comprendre le pratique de la chose, imaginons comment nous aurions du coder cet exemple sans utiliser de variable. Serait-ce comme cela ? -<pre class="example-bad">let name = prompt('Quel est votre nom ?'); +```plain example-bad +let name = prompt('Quel est votre nom ?'); if (name === 'Adam') { alert('Salut Adam, sympa de vous voir !'); @@ -61,35 +69,37 @@ if (name === 'Adam') { alert('Salut Chris, sympa de vous voir !'); } -// ... etc.</pre> +// ... etc. +``` -<p>Peut-être ne comprenez‑vous pas (encore !) la syntaxe utilisée, mais vous l'imaginerez sans peine — si nous n'avions pas de variables à disposition, nous devrions implémenter un bloc de code géant qui vérifierait quel était le nom saisi, puis afficherait un message approprié à ce nom. Cela est évidemment inefficace (le code est déjà plus volumineux avec seulement quatre possibilités) et il ne fonctionnerait certainement pas — il n'est pas possible de stocker tous les choix possibles.</p> +Peut-être ne comprenez‑vous pas (encore !) la syntaxe utilisée, mais vous l'imaginerez sans peine — si nous n'avions pas de variables à disposition, nous devrions implémenter un bloc de code géant qui vérifierait quel était le nom saisi, puis afficherait un message approprié à ce nom. Cela est évidemment inefficace (le code est déjà plus volumineux avec seulement quatre possibilités) et il ne fonctionnerait certainement pas — il n'est pas possible de stocker tous les choix possibles. -<p>Les variables sont essentielles et à mesure que vous en apprendrez plus sur JavaScript, elles deviendront une seconde nature pour vous.</p> +Les variables sont essentielles et à mesure que vous en apprendrez plus sur JavaScript, elles deviendront une seconde nature pour vous. -<p>Une autre particularité des variables : elle peuvent contenir pratiquement de tout — pas uniquement des chaînes ou des nombres. Elles peuvent aussi contenir des données complexes et même des fonctions, ce qui permet de réaliser des choses étonnantes. Vous en apprendrez plus à ce propos au long de ce parcours.</p> +Une autre particularité des variables : elle peuvent contenir pratiquement de tout — pas uniquement des chaînes ou des nombres. Elles peuvent aussi contenir des données complexes et même des fonctions, ce qui permet de réaliser des choses étonnantes. Vous en apprendrez plus à ce propos au long de ce parcours. -<div class="note"> -<p><strong>Note :</strong> Nous disons que les variables contiennent des valeurs. C'est un distingo important. Les variables ne sont pas les valeurs elles‑mêmes : ce sont des conteneurs pour ces valeurs. Vous pouvez vous les représenter comme une boîte en carton dans laquelle il est possible de ranger des choses.</p> -</div> +> **Note :** Nous disons que les variables contiennent des valeurs. C'est un distingo important. Les variables ne sont pas les valeurs elles‑mêmes : ce sont des conteneurs pour ces valeurs. Vous pouvez vous les représenter comme une boîte en carton dans laquelle il est possible de ranger des choses. -<p><img alt="" src="boxes.png"></p> + -<h2 id="Déclarer_une_variable">Déclarer une variable</h2> +## Déclarer une variable -<p>Avant de se servir d'une variable, il faut d'abord la créer — plus précisément, nous disons <em>déclarer la variable</em>. Pour ce faire, nous saisissons le mot‑clé <code>var</code> ou <code>let</code> suivi du nom que vous voulez donner à la variable :</p> +Avant de se servir d'une variable, il faut d'abord la créer — plus précisément, nous disons _déclarer la variable_. Pour ce faire, nous saisissons le mot‑clé `var` ou `let` suivi du nom que vous voulez donner à la variable : -<pre class="brush: js">let myName; -let myAge;</pre> +```js +let myName; +let myAge; +``` -<p>Dans ces lignes, nous venons de créer deux variables nommées respectivement <code>myName</code> et <code>myAge</code>. Saisissez les maintenant dans la console de votre navigateur, ou dans la console au bas de la page (Vous <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">ouvrez cette console</a> soit dans un onglet séparé, soit dans une fenêtre selon votre préférence). Après cela, essayez de créer une variable (ou deux) en choisissant vous même le nom.</p> +Dans ces lignes, nous venons de créer deux variables nommées respectivement `myName` et `myAge`. Saisissez les maintenant dans la console de votre navigateur, ou dans la console au bas de la page (Vous [ouvrez cette console](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html) soit dans un onglet séparé, soit dans une fenêtre selon votre préférence). Après cela, essayez de créer une variable (ou deux) en choisissant vous même le nom. -<pre class="brush: html hidden"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>JavaScript console</title> - <style> +```html hidden +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> * { box-sizing: border-box; } @@ -137,14 +147,14 @@ let myAge;</pre> clear: both; } - </style> - </head> - <body> + </style> + </head> + <body> - </body> + </body> - <script> + <script> var geval = eval; function createInput() { var inputDiv = document.createElement('div'); @@ -152,12 +162,12 @@ let myAge;</pre> var inputForm = document.createElement('input'); inputDiv.setAttribute('class','input'); - inputPara.textContent = '>'; + inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); - if(document.querySelectorAll('div').length > 1) { + if(document.querySelectorAll('div').length > 1) { inputForm.focus(); } @@ -187,57 +197,65 @@ let myAge;</pre> createInput(); - </script> -</html></pre> + </script> +</html> +``` -<p>{{ EmbedLiveSample('Déclarer_une_variable', '100%', 300) }}</p> +{{ EmbedLiveSample('Déclarer_une_variable', '100%', 300) }} -<div class="note"> -<p><strong>Note :</strong> En JavaScript, le code de toute instruction doit se terminer par un point‑virgule (<code>;</code>) — il peut fonctionner correctement sans ce point‑virgule pour des lignes isolées, mais ce ne sera probablement pas le cas si vous écrivez plusieurs lignes de code ensemble. Prenez l'habitude de mettre ce point‑virgule.</p> -</div> +> **Note :** En JavaScript, le code de toute instruction doit se terminer par un point‑virgule (`;`) — il peut fonctionner correctement sans ce point‑virgule pour des lignes isolées, mais ce ne sera probablement pas le cas si vous écrivez plusieurs lignes de code ensemble. Prenez l'habitude de mettre ce point‑virgule. -<p>Vous pouvez maintenant tester si ces valeurs existent dans l'environnement d'exécution en saisissant simplement le nom de ces variables, par exemple</p> +Vous pouvez maintenant tester si ces valeurs existent dans l'environnement d'exécution en saisissant simplement le nom de ces variables, par exemple -<pre class="brush: js">myName; -myAge;</pre> +```js +myName; +myAge; +``` -<p>Actuellement elles ne contiennent aucune valeur ; ce sont des conteneurs vides. Quand vous entrez les noms des variables, vous obtiendrez la valeur <code>undefined</code> en retour. Si elles n'existent pas, vous aurez un message d'erreur — essayez en saisissant</p> +Actuellement elles ne contiennent aucune valeur ; ce sont des conteneurs vides. Quand vous entrez les noms des variables, vous obtiendrez la valeur `undefined` en retour. Si elles n'existent pas, vous aurez un message d'erreur — essayez en saisissant -<pre class="brush: js">scoobyDoo;</pre> +```js +scoobyDoo; +``` -<div class="note"> -<p><strong>Note :</strong> Ne confondez pas une variable qui existe mais sans valeur définie avec une variable qui n'existe pas du tout — ce sont deux choses tout à fait différentes. Dans l'analogie des boîtes, <em>ne pas exister</em> correspond à l'absence de boîte ; <em>valeur indéfinie</em> correspond à une boîte vide.</p> -</div> +> **Note :** Ne confondez pas une variable qui existe mais sans valeur définie avec une variable qui n'existe pas du tout — ce sont deux choses tout à fait différentes. Dans l'analogie des boîtes, _ne pas exister_ correspond à l'absence de boîte ; *valeur indéfinie* correspond à une boîte vide. -<h2 id="Initialisation_dune_variable">Initialisation d'une variable</h2> +## Initialisation d'une variable -<p>Une fois la variable déclarée, vous pouvez l'initialiser avec une valeur. On réalise cela en saisissant le nom de la variable, suivi d'un signe égale (<code>=</code>), lui-même suivi de la valeur souhaitée pour la variable. Par exemple :</p> +Une fois la variable déclarée, vous pouvez l'initialiser avec une valeur. On réalise cela en saisissant le nom de la variable, suivi d'un signe égale (`=`), lui-même suivi de la valeur souhaitée pour la variable. Par exemple : -<pre class="brush: js">myName = 'Chris'; -myAge = 37;</pre> +```js +myName = 'Chris'; +myAge = 37; +``` -<p>Revenez à la console maintenant et saisissez‑y ces deux lignes. Constatez que la console renvoie en confirmation la valeur assignée à la variable dans chaque cas. Vous pouvez, à nouveau, faire renvoyer par la console les valeurs de variable en saisissant simplement son nom dans la console — essayez encore :</p> +Revenez à la console maintenant et saisissez‑y ces deux lignes. Constatez que la console renvoie en confirmation la valeur assignée à la variable dans chaque cas. Vous pouvez, à nouveau, faire renvoyer par la console les valeurs de variable en saisissant simplement son nom dans la console — essayez encore : -<pre class="brush: js">myName; -myAge;</pre> +```js +myName; +myAge; +``` -<p>Il est possible de déclarer et initialiser une variable en même temps, comme ceci :</p> +Il est possible de déclarer et initialiser une variable en même temps, comme ceci : -<pre class="brush: js">let myDog = 'Rover';</pre> +```js +let myDog = 'Rover'; +``` -<p>C'est probablement ce que vous ferez la plupart du temps, c'est plus rapide que d'effectuer ces deux actions sur deux lignes distinctes.</p> +C'est probablement ce que vous ferez la plupart du temps, c'est plus rapide que d'effectuer ces deux actions sur deux lignes distinctes. -<h2 id="La_différence_entre_var_et_let">La différence entre <code>var</code> et <code>let</code></h2> +## La différence entre `var` et `let` -<p>A ce moment de votre apprentissage, vous vous demandez sans doute : mais quel besoin de deux mot-clé pour définir une variable ? Pourquoi <code>var</code> et <code>let</code> ?</p> +A ce moment de votre apprentissage, vous vous demandez sans doute : mais quel besoin de deux mot-clé pour définir une variable ? Pourquoi `var` et `let` ? -<p>Les raisons sont d'ordre historique. A l'origine, quand Javascript fut créé, il n'y avait que <code>var</code>. Cela fonctionnait plutôt bien dans la plupart des cas, avec parfois quelques surprises -- l'implémentation étonnante du <code>var</code> peut amener à une mauvaise interprétation, voire à des soucis. Ainsi, <code>let</code> a été ajouté dans les versions plus récentes de Javascript, un nouveau mot-clé pour créer des variables, avec un fonctionnement différent de celui du <code>var</code>, réglant ainsi les difficultés évoquées ci-dessus.</p> +Les raisons sont d'ordre historique. A l'origine, quand Javascript fut créé, il n'y avait que `var`. Cela fonctionnait plutôt bien dans la plupart des cas, avec parfois quelques surprises -- l'implémentation étonnante du `var` peut amener à une mauvaise interprétation, voire à des soucis. Ainsi, `let` a été ajouté dans les versions plus récentes de Javascript, un nouveau mot-clé pour créer des variables, avec un fonctionnement différent de celui du `var`, réglant ainsi les difficultés évoquées ci-dessus. -<p>Nous évoquons ci-dessous quelques unes de ces différences, sans pouvoir faire ici le tour complet de la question. Vous comprendrez mieux la différence entre ces deux constructions au fur et à mesure de votre progression en JavaScript (si vous ne pouvez pas attendre, consultez la page de référence du <code>let</code>). </p> +Nous évoquons ci-dessous quelques unes de ces différences, sans pouvoir faire ici le tour complet de la question. Vous comprendrez mieux la différence entre ces deux constructions au fur et à mesure de votre progression en JavaScript (si vous ne pouvez pas attendre, consultez la page de référence du `let`). -<p>Pour commencer, si vous écrivez un programme JavaScript multi-lignes qui déclare et initialise une variable, vous pouvez déclarez une variable avec le mot-clé <code>var</code> après l'avoir initialisée. Cela fonctionnera. Par exemple :</p> +Pour commencer, si vous écrivez un programme JavaScript multi-lignes qui déclare et initialise une variable, vous pouvez déclarez une variable avec le mot-clé `var` après l'avoir initialisée. Cela fonctionnera. Par exemple : -<pre class="brush: js">myName = 'Chris'; +```js +myName = 'Chris'; function logName(){ console.log(myName); @@ -246,76 +264,79 @@ function logName(){ logName(); var myName; -</pre> +``` -<div class="note"> -<p><strong>Note :</strong> l'exemple ci-dessus ne fonctionnera pas si on tape des lignes une à une dans la console, mais seulement quand on exécute un script JavaScript multi-lignes dans un document web.</p> -</div> +> **Note :** l'exemple ci-dessus ne fonctionnera pas si on tape des lignes une à une dans la console, mais seulement quand on exécute un script JavaScript multi-lignes dans un document web. -<p>Ce processus se nomme <strong>«</strong> <strong>hoisting »</strong> (en français, "hissage") — lisez <a href="/fr/docs/Web/JavaScript/Reference/Statements/var#var_hoisting">var hoisting</a> pour plus de précisions sur ce sujet.</p> +Ce processus se nomme **«** **hoisting »** (en français, "hissage") — lisez [var hoisting](/fr/docs/Web/JavaScript/Reference/Statements/var#var_hoisting) pour plus de précisions sur ce sujet. -<p>Le hissage ne fonctionne plus avec <code>let</code>. Si on remplaçait var par let dans l'exemple ci-dessus, l'exécution du script planterait sur une erreur. C'est une bonne chose — déclarer une variable après l'avoir initialisé produit un code obscur, difficile à lire.</p> +Le hissage ne fonctionne plus avec `let`. Si on remplaçait var par let dans l'exemple ci-dessus, l'exécution du script planterait sur une erreur. C'est une bonne chose — déclarer une variable après l'avoir initialisé produit un code obscur, difficile à lire. -<p>Deuxièmement, quand vous utilisez <code>var</code>, vous pouvez déclarer la même variable autant de fois que vous le désirez, avec <code>let</code> c'est impossible. Le code suivant s'exécute sans erreur :</p> +Deuxièmement, quand vous utilisez `var`, vous pouvez déclarer la même variable autant de fois que vous le désirez, avec `let` c'est impossible. Le code suivant s'exécute sans erreur : -<pre class="brush: js">var myName = 'Chris'; +```js +var myName = 'Chris'; var myName = 'Bob'; -</pre> +``` -<p> Celui là produit une erreur sur la seconde ligne :</p> +Celui là produit une erreur sur la seconde ligne : -<pre class="brush: js">let myName = 'Chris'; +```js +let myName = 'Chris'; let myName = 'Bob'; -</pre> +``` -<p>Le code correct serait :</p> +Le code correct serait : -<pre class="brush: js">let myName = 'Chris' ; +```js +let myName = 'Chris' ; -myName = 'Bob' ;</pre> +myName = 'Bob' ; +``` -<p>Encore une fois, c'est une décision sensée des concepteurs du langage. Il n'y a aucune bonne raison de redéclarer une variable — cela rend les choses obscures.</p> +Encore une fois, c'est une décision sensée des concepteurs du langage. Il n'y a aucune bonne raison de redéclarer une variable — cela rend les choses obscures. -<p>Pour ces raisons, et d'autres, nous recommandons d'utiliser <code>let</code> plutôt que <code>var</code>. Il n'y a pas de bonne raison d'utiliser <code>var</code>, sauf à rechercher la compatibilité avec de vieilles versions d'Internet Explorer (pas de support du <code>let</code> avant la version 11 ; le support de <code>let</code> par le navigateur Edge ne pose pas de problème).</p> +Pour ces raisons, et d'autres, nous recommandons d'utiliser `let` plutôt que `var`. Il n'y a pas de bonne raison d'utiliser `var`, sauf à rechercher la compatibilité avec de vieilles versions d'Internet Explorer (pas de support du `let` avant la version 11 ; le support de `let` par le navigateur Edge ne pose pas de problème). -<h2 id="Mise_à_jour_dune_variable">Mise à jour d'une variable</h2> +## Mise à jour d'une variable -<p>Une fois la variable initialisée avec une valeur, vous pouvez simplement modifier (ou mettre à jour) cette valeur en lui assignant une nouvelle valeur. Entrez ces deux lignes dans la console :</p> +Une fois la variable initialisée avec une valeur, vous pouvez simplement modifier (ou mettre à jour) cette valeur en lui assignant une nouvelle valeur. Entrez ces deux lignes dans la console : -<pre class="brush: js">myName = 'Bob'; -myAge = 40;</pre> +```js +myName = 'Bob'; +myAge = 40; +``` -<h3 id="Aparté_concernant_les_règles_de_nommage_des_variables">Aparté concernant les règles de nommage des variables</h3> +### Aparté concernant les règles de nommage des variables -<p>Vous pouvez nommer une variable comme vous l'entendez, mais il y a des restrictions. Généralement, il convient de se limiter à l'emploi des caractères latins (0-9, a-z, A-Z) et du underscore ( _ ).</p> +Vous pouvez nommer une variable comme vous l'entendez, mais il y a des restrictions. Généralement, il convient de se limiter à l'emploi des caractères latins (0-9, a-z, A-Z) et du underscore ( \_ ). -<ul> - <li>N'utilisez pas d'autres caractères ; ils pourraient entraîner des erreurs ou être difficiles à comprendre pour un auditoire international.</li> - <li>N'utilisez pas le underscore comme premier caractère d'un nom de variable — cette façon d'opérer est utilisée dans certaines constructions JavaScript pour signer certaines spécificités ; il pourrait y avoir confusion.</li> - <li>Ne mettez pas un chiffre en début de nom de variable. Ce n'est pas permis et provoque une erreur.</li> - <li>Une convention sûre, nommée <a href="https://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms">"lower camel case"</a> (dos de chameau), consiste à accoler plusieurs mots en mettant le premier en minuscules les suivants commençant par une majuscule. Dans cet article, nous avons adopté cette convention pour les noms de variables.</li> - <li>Prenez des noms de variable intuitifs, décrivant les données que la variable contient. Évitez les noms se limitant à un caractère ou à l'inverse des noms trop longs, trop verbeux.</li> - <li>Les variables sont sensibles à la casse — donc <code>myage</code> et <code>myAge</code> correspondent à deux variables différentes.</li> - <li>Enfin les <em>mots réservés</em> du langage JavaScript ne peuvent pas être choisis comme nom pour une variable — les mots réservés sont les mots qui font effectivement partie de la syntaxe du JavaScript. Donc, vous ne pouvez pas utiliser des mots comme <code>var</code>, <code>function</code>, <code>let</code> ou <code>for</code> comme noms de variable. Les navigateurs les reconnaîtront en tant qu'éléments de code, et cela déclenchera des erreurs.</li> -</ul> +- N'utilisez pas d'autres caractères ; ils pourraient entraîner des erreurs ou être difficiles à comprendre pour un auditoire international. +- N'utilisez pas le underscore comme premier caractère d'un nom de variable — cette façon d'opérer est utilisée dans certaines constructions JavaScript pour signer certaines spécificités ; il pourrait y avoir confusion. +- Ne mettez pas un chiffre en début de nom de variable. Ce n'est pas permis et provoque une erreur. +- Une convention sûre, nommée ["lower camel case"](https://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms) (dos de chameau), consiste à accoler plusieurs mots en mettant le premier en minuscules les suivants commençant par une majuscule. Dans cet article, nous avons adopté cette convention pour les noms de variables. +- Prenez des noms de variable intuitifs, décrivant les données que la variable contient. Évitez les noms se limitant à un caractère ou à l'inverse des noms trop longs, trop verbeux. +- Les variables sont sensibles à la casse — donc `myage` et `myAge` correspondent à deux variables différentes. +- Enfin les _mots réservés_ du langage JavaScript ne peuvent pas être choisis comme nom pour une variable — les mots réservés sont les mots qui font effectivement partie de la syntaxe du JavaScript. Donc, vous ne pouvez pas utiliser des mots comme `var`, `function`, `let` ou `for` comme noms de variable. Les navigateurs les reconnaîtront en tant qu'éléments de code, et cela déclenchera des erreurs. -<div class="note"> -<p><strong>Note :</strong> Une liste exhaustive des mots réservés est proposée dans la page <a href="/fr/docs/Web/JavaScript/Reference/Lexical_grammar#keywords">Lexical grammar — keywords</a>.</p> -</div> +> **Note :** Une liste exhaustive des mots réservés est proposée dans la page [Lexical grammar — keywords](/fr/docs/Web/JavaScript/Reference/Lexical_grammar#keywords). -<p>Exemples de noms corrects :</p> +Exemples de noms corrects : -<pre class="example-good">age +```plain example-good +age myAge init initialColor finalOutputValue audio1 -audio2</pre> +audio2 +``` -<p>Exemples de noms incorrects (soit illégal, soit non conforme aux recommandations) :</p> +Exemples de noms incorrects (soit illégal, soit non conforme aux recommandations) : -<pre class="example-bad">1 +```plain example-bad +1 a _12 myage @@ -323,96 +344,118 @@ MYAGE var document skjfndskjfnbdskjfb -thisisareallylongstupidvariablenameman </pre> +thisisareallylongstupidvariablenameman +``` -<p>Parmi ces noms, les suivants déclenchent une <code>SyntaxError</code> :</p> +Parmi ces noms, les suivants déclenchent une `SyntaxError` : -<pre class="brush: js example-bad">1 //la variable commence par un chiffre +```js example-bad +1 //la variable commence par un chiffre var //mot réservé document //mot réservé -</pre> +``` -<p>Essayez maintenant de créer quelques variables supplémentaires en tenant compte de ce qui précède.</p> +Essayez maintenant de créer quelques variables supplémentaires en tenant compte de ce qui précède. -<h2 id="Types_de_variables">Types de variables</h2> +## Types de variables -<p>Plusieurs types de données peuvent être stockés dans des variables. Dans cette section, nous allons les décrire brièvement, puis dans les prochains articles, nous vous en dirons plus.</p> +Plusieurs types de données peuvent être stockés dans des variables. Dans cette section, nous allons les décrire brièvement, puis dans les prochains articles, nous vous en dirons plus. -<p>Jusqu'à présent, nous avons vu les deux types suivants, mais il y en a d'autres.</p> +Jusqu'à présent, nous avons vu les deux types suivants, mais il y en a d'autres. -<h3 id="Nombres">Nombres</h3> +### Nombres -<p>Vous pouvez stocker des nombres dans des variables, soit des nombres entiers comme 30 ou des nombres décimaux comme 2.456 (appelés aussi nombres à virgule flottante). Il n'est pas nécessaire de déclarer le type de la variable dans JavaScript, contrairement à d'autres langages de programmation. Lorsque vous donnez une valeur numérique à une variable, ne la mettez pas entre guillemets.</p> +Vous pouvez stocker des nombres dans des variables, soit des nombres entiers comme 30 ou des nombres décimaux comme 2.456 (appelés aussi nombres à virgule flottante). Il n'est pas nécessaire de déclarer le type de la variable dans JavaScript, contrairement à d'autres langages de programmation. Lorsque vous donnez une valeur numérique à une variable, ne la mettez pas entre guillemets. -<pre class="brush: js">var myAge = 17;</pre> +```js +var myAge = 17; +``` -<h3 id="Chaînes">Chaînes</h3> +### Chaînes -<p>Les chaînes sont des mots ou des suites de mots. Quand vous stockez dans une variable une valeur chaîne, vous devez la mettre entre guillemets simples ou doubles, sinon JavaScript va tenter de l'interpréter en tant qu'un autre nom de variable.</p> +Les chaînes sont des mots ou des suites de mots. Quand vous stockez dans une variable une valeur chaîne, vous devez la mettre entre guillemets simples ou doubles, sinon JavaScript va tenter de l'interpréter en tant qu'un autre nom de variable. -<pre class="brush: js">var dolphinGoodbye = 'So long and thanks for all the fish';</pre> +```js +var dolphinGoodbye = 'So long and thanks for all the fish'; +``` -<h3 id="Booléens">Booléens</h3> +### Booléens -<p>Les booléens sont des valeurs true/false (vrai/faux) — elles ne peuvent prendre que deux valeurs: <code>true</code> ou <code>false</code>. Elles sont généralement utilisées pour tester une condition, à la suite de laquelle le code est exécuté de manière appropriée. Ainsi, par exemple, un cas simple pourrait être :</p> +Les booléens sont des valeurs true/false (vrai/faux) — elles ne peuvent prendre que deux valeurs: `true` ou `false`. Elles sont généralement utilisées pour tester une condition, à la suite de laquelle le code est exécuté de manière appropriée. Ainsi, par exemple, un cas simple pourrait être : -<pre class="brush: js">var iAmAlive = true;</pre> +```js +var iAmAlive = true; +``` -<p>Toutefois, en réalité, un booléen sera plutôt utilisé ainsi :</p> +Toutefois, en réalité, un booléen sera plutôt utilisé ainsi : -<pre class="brush: js">var test = 6 < 3;</pre> +```js +var test = 6 < 3; +``` -<p>Cette expression utilise l'opérateur « inférieur à » (<code><</code>) pour tester si 6 est plus petit que 3. Comme vous pouvez vous y attendre, cette expression renverra <code>false</code>, car 6 n'est pas plus petit que 3 ! Vous en apprendrez bien plus à propos de ces opérateurs plus loin dans ce cours.</p> +Cette expression utilise l'opérateur « inférieur à » (`<`) pour tester si 6 est plus petit que 3. Comme vous pouvez vous y attendre, cette expression renverra `false`, car 6 n'est pas plus petit que 3 ! Vous en apprendrez bien plus à propos de ces opérateurs plus loin dans ce cours. -<h3 id="Tableaux">Tableaux</h3> +### Tableaux -<p>Une tableau est un objet unique contenant plusieurs valeurs entre crochets séparées par des virgules. Saisissez les lignes suivantes dans la console :</p> +Une tableau est un objet unique contenant plusieurs valeurs entre crochets séparées par des virgules. Saisissez les lignes suivantes dans la console : -<pre class="brush: js">var myNameArray = ['Chris', 'Bob', 'Jim']; -var myNumberArray = [10,15,40];</pre> +```js +var myNameArray = ['Chris', 'Bob', 'Jim']; +var myNumberArray = [10,15,40]; +``` -<p>Un fois ces tableaux définis, vous pouvez avoir accès à chaque valeur en fonction de leur emplacement dans le tableau. Voyez ces lignes :</p> +Un fois ces tableaux définis, vous pouvez avoir accès à chaque valeur en fonction de leur emplacement dans le tableau. Voyez ces lignes : -<pre class="brush: js">myNameArray[0]; // renverra 'Chris' -myNumberArray[2]; // renverra 40</pre> +```js +myNameArray[0]; // renverra 'Chris' +myNumberArray[2]; // renverra 40 +``` -<p>La valeur entre crochets précise l'index correspondant à la position de la valeur que vous souhaitez voir renvoyée. Vous remarquerez que les tableaux en JavaScript sont indexés à partir de zéro : le premier élément a l'index 0.</p> +La valeur entre crochets précise l'index correspondant à la position de la valeur que vous souhaitez voir renvoyée. Vous remarquerez que les tableaux en JavaScript sont indexés à partir de zéro : le premier élément a l'index 0. -<p>Vous en apprendrez beaucoup plus au sujet des tableaux dans un article suivant.</p> +Vous en apprendrez beaucoup plus au sujet des tableaux dans un article suivant. -<h3 id="Objets">Objets</h3> +### Objets -<p>En programmation, un objet est une structure de code qui modélise un objet du réel. Vous pouvez avoir un objet simple représentant une place de parking avec sa largeur et sa profondeur ou bien un objet représentant une personne avec comme données son nom, sa taille, son poids, son vernaculaire, comment le contacter, et plus encore.</p> +En programmation, un objet est une structure de code qui modélise un objet du réel. Vous pouvez avoir un objet simple représentant une place de parking avec sa largeur et sa profondeur ou bien un objet représentant une personne avec comme données son nom, sa taille, son poids, son vernaculaire, comment le contacter, et plus encore. -<p>Entrez la ligne suivant dans la console de votre explorateur :</p> +Entrez la ligne suivant dans la console de votre explorateur : -<pre class="brush: js">var dog = { name : 'Spot', breed : 'Dalmatian' };</pre> +```js +var dog = { name : 'Spot', breed : 'Dalmatian' }; +``` -<p>Pour récupérer une information stockée dans un objet, vous pouvez utiliser la syntaxe suivante :</p> +Pour récupérer une information stockée dans un objet, vous pouvez utiliser la syntaxe suivante : -<pre class="brush: js">dog.name</pre> +```js +dog.name +``` -<p>Nous en resterons là avec les objets pour le moment — vous en saurez plus à leur propos dans un module ultérieur.</p> +Nous en resterons là avec les objets pour le moment — vous en saurez plus à leur propos dans un module ultérieur. -<h2 id="Typage_faible">Typage faible</h2> +## Typage faible -<p>JavaScript est un « langage faiblement typé », ce qui veut dire que, contrairement à d'autres langages, vous n'êtes pas obligé de préciser quel est le type de donnée que doit contenir une variable (par ex. nombres, chaînes, tableaux, etc).</p> +JavaScript est un « langage faiblement typé », ce qui veut dire que, contrairement à d'autres langages, vous n'êtes pas obligé de préciser quel est le type de donnée que doit contenir une variable (par ex. nombres, chaînes, tableaux, etc). -<p>Par exemple, si vous déclarez une variable et si vous y placez une valeur entre guillemets, le navigateur la traitera comme étant une chaîne :</p> +Par exemple, si vous déclarez une variable et si vous y placez une valeur entre guillemets, le navigateur la traitera comme étant une chaîne : -<pre class="brush: js">var myString = 'Hello';</pre> +```js +var myString = 'Hello'; +``` -<p>Ce sera toujours une chaîne, même si ce sont des nombres, donc soyez prudents :</p> +Ce sera toujours une chaîne, même si ce sont des nombres, donc soyez prudents : -<pre class="brush: js">var myNumber = '500'; // oops, c'est toujours une chaîne +```js +var myNumber = '500'; // oops, c'est toujours une chaîne typeof(myNumber); myNumber = 500; // mieux — maintenant c'est un nombre -typeof(myNumber);</pre> +typeof(myNumber); +``` -<p>Entrez ces quatre lignes dans la console les unes à la suite des autres, et voyez les résultats. Notez l'emploi de la fonction spéciale <code>typeof()</code> — elle renvoie le type de donnée placé dans la variable. À son premier appel, elle renverra <code>string</code>, car à ce stade la variable <code>myNumber</code> contient la chaîne <code>'500'</code>. Observez bien et voyez ce que la fonction renvoie au second appel.</p> +Entrez ces quatre lignes dans la console les unes à la suite des autres, et voyez les résultats. Notez l'emploi de la fonction spéciale `typeof()` — elle renvoie le type de donnée placé dans la variable. À son premier appel, elle renverra `string`, car à ce stade la variable `myNumber` contient la chaîne `'500'`. Observez bien et voyez ce que la fonction renvoie au second appel. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Maintenant, nous en savons un peu plus à propos des variables JavaScript, en particulier comment les créer. Dans le prochain article, nous verrons en détail les nombres et comment effectuer les opérations mathématiques élémentaires.</p> +Maintenant, nous en savons un peu plus à propos des variables JavaScript, en particulier comment les créer. Dans le prochain article, nous verrons en détail les nombres et comment effectuer les opérations mathématiques élémentaires. -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}</p> +{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}} diff --git a/files/fr/learn/javascript/first_steps/what_is_javascript/index.md b/files/fr/learn/javascript/first_steps/what_is_javascript/index.md index 5e37499c73..072084dc21 100644 --- a/files/fr/learn/javascript/first_steps/what_is_javascript/index.md +++ b/files/fr/learn/javascript/first_steps/what_is_javascript/index.md @@ -3,48 +3,53 @@ title: Qu'est-ce que le JavaScript ? slug: Learn/JavaScript/First_steps/What_is_JavaScript translation_of: Learn/JavaScript/First_steps/What_is_JavaScript --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}} -<div>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</div> - -<p>Bienvenue dans le cours JavaScript pour débutants sur le MDN. Dans ce premier article nous donnons une description générale de JavaScript en présentant le « pourquoi » et le « comment » du JavaScript. L'objectif est que vous compreniez bien son but.</p> +Bienvenue dans le cours JavaScript pour débutants sur le MDN. Dans ce premier article nous donnons une description générale de JavaScript en présentant le « pourquoi » et le « comment » du JavaScript. L'objectif est que vous compreniez bien son but. <table> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td> - <p>Une culture informatique basique et une compréhension élémentaire de HTML et CSS.</p> - </td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Se familiariser avec JavaScript, ce qu'il peut faire et comment il s'intègre dans un site web.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + <p> + Une culture informatique basique et une compréhension élémentaire de + HTML et CSS. + </p> + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Se familiariser avec JavaScript, ce qu'il peut faire et comment il + s'intègre dans un site web. + </td> + </tr> + </tbody> </table> -<h2 id="Une_définition_générale">Une définition générale</h2> +## Une définition générale -<p>JavaScript est un langage de programmation qui permet d'implémenter des mécanismes complexes sur une page web. À chaque fois qu'une page web fait plus que simplement afficher du contenu statique — afficher du contenu mis à jour à des temps déterminés, des cartes interactives, des animations 2D/3D, des menus vidéo défilants, ou autre, JavaScript a de bonnes chances d'être impliqué. C'est la troisième couche des technologies standards du web, les deux premières (<a href="/fr/docs/Learn/HTML">HTML</a> et <a href="/fr/docs/Learn/CSS">CSS</a>) étant couvertes bien plus en détail dans d'autres tutoriels sur MDN.</p> +JavaScript est un langage de programmation qui permet d'implémenter des mécanismes complexes sur une page web. À chaque fois qu'une page web fait plus que simplement afficher du contenu statique — afficher du contenu mis à jour à des temps déterminés, des cartes interactives, des animations 2D/3D, des menus vidéo défilants, ou autre, JavaScript a de bonnes chances d'être impliqué. C'est la troisième couche des technologies standards du web, les deux premières ([HTML](/fr/docs/Learn/HTML) et [CSS](/fr/docs/Learn/CSS)) étant couvertes bien plus en détail dans d'autres tutoriels sur MDN. -<p><img alt="" src="cake.png"></p> + -<ul> - <li>{{glossary("HTML")}} est un langage de balises utilisé pour structurer et donner du sens au contenu web. Par exemple : définir des paragraphes, titres et tables de données ou encore intégrer des images ou des vidéos dans une page.</li> - <li>{{glossary("CSS")}} est un langage de règles de style utilisé pour mettre en forme le contenu HTML. Par exemple : en modifiant la couleur d'arrière-plan ou les polices, ou en disposant le contenu en plusieurs colonnes.</li> - <li>{{glossary("JavaScript")}} est un langage de programmation qui permet de créer du contenu mis à jour de façon dynamique, de contrôler le contenu multimédia, d'animer des images, et tout ce à quoi on peut penser. Bon, peut-être pas tout, mais vous pouvez faire bien des choses avec quelques lignes de JavaScript.</li> -</ul> +- {{glossary("HTML")}} est un langage de balises utilisé pour structurer et donner du sens au contenu web. Par exemple : définir des paragraphes, titres et tables de données ou encore intégrer des images ou des vidéos dans une page. +- {{glossary("CSS")}} est un langage de règles de style utilisé pour mettre en forme le contenu HTML. Par exemple : en modifiant la couleur d'arrière-plan ou les polices, ou en disposant le contenu en plusieurs colonnes. +- {{glossary("JavaScript")}} est un langage de programmation qui permet de créer du contenu mis à jour de façon dynamique, de contrôler le contenu multimédia, d'animer des images, et tout ce à quoi on peut penser. Bon, peut-être pas tout, mais vous pouvez faire bien des choses avec quelques lignes de JavaScript. -<p>Les trois couches se superposent naturellement. Prenons pour exemple une simple étiquette texte. Les balises HTML lui donnent une structure et un but :</p> +Les trois couches se superposent naturellement. Prenons pour exemple une simple étiquette texte. Les balises HTML lui donnent une structure et un but : -<pre class="brush: html"><p>Player 1: Chris</p></pre> +```html +<p>Player 1: Chris</p> +``` -<p><img alt="" src="just-html.png"></p> + -<p>Nous pouvons ensuite ajouter du CSS pour rendre cela plus joli :</p> +Nous pouvons ensuite ajouter du CSS pour rendre cela plus joli : -<pre class="brush: css">p { +```css +p { font-family: 'helvetica neue', helvetica, sans-serif; letter-spacing: 1px; text-transform: uppercase; @@ -57,13 +62,15 @@ translation_of: Learn/JavaScript/First_steps/What_is_JavaScript padding: 3px 10px; display: inline-block; cursor:pointer; -}</pre> +} +``` -<p><img alt="" src="html-and-css.png"></p> + -<p>Et enfin utiliser JavaScript pour ajouter un comportement dynamique :</p> +Et enfin utiliser JavaScript pour ajouter un comportement dynamique : -<pre class="brush: js">let para = document.querySelector('p'); +```js +let para = document.querySelector('p'); para.addEventListener('click', updateName); @@ -71,297 +78,296 @@ function updateName() { let name = prompt('Enter a new name'); para.textContent = 'Player 1: ' + name; } -</pre> +``` -<p>{{ EmbedLiveSample('Une_définition_générale', '100%', 80) }}</p> +{{ EmbedLiveSample('Une_définition_générale', '100%', 80) }} -<p>Essayez de cliquer sur l'étiquette texte pour voir ce qui se passe. Notez que vous pouvez également retrouver cet exemple sur GitHub — voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/javascript-label.html">code source</a>, ou l'<a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/javascript-label.html">exécuter</a>.</p> +Essayez de cliquer sur l'étiquette texte pour voir ce qui se passe. Notez que vous pouvez également retrouver cet exemple sur GitHub — voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/javascript-label.html), ou l'[exécuter](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/javascript-label.html). -<p>JavaScript peut faire bien plus. Voyons cela plus en détail.</p> +JavaScript peut faire bien plus. Voyons cela plus en détail. -<h2 id="Que_peut-il_vraiment_faire">Que peut-il <em>vraiment</em> faire ?</h2> +## Que peut-il _vraiment_ faire ? -<p>Le cœur de JavaScript est constitué de fonctionnalités communes de programmation permettant de :</p> +Le cœur de JavaScript est constitué de fonctionnalités communes de programmation permettant de : -<ul> - <li>stocker des valeurs utiles dans des variables. Dans l'exemple plus haut, nous demandons un nouveau nom à l'utilisateur puis le stockons dans une variable appelée <code>name</code>.</li> - <li>faire des opérations sur des morceaux de texte (appelés en programmation « chaînes de caractères » ou « strings » en anglais). Dans l'exemple plus haut, nous prenons la chaîne de caractères "Player 1: " et lui adjoignons la variable <code>name</code> pour créer l'étiquette ''Player 1: Chris".</li> - <li>exécuter du code en réponse à certains événements se produisant sur une page web. Dans l'exemple, nous avons utilisé un événement (« event ») {{Event("click")}} pour détecter quand l'utilisateur clique sur le bouton ; on exécute alors le code qui met à jour l'étiquette.</li> - <li>Et bien plus encore !</li> -</ul> +- stocker des valeurs utiles dans des variables. Dans l'exemple plus haut, nous demandons un nouveau nom à l'utilisateur puis le stockons dans une variable appelée `name`. +- faire des opérations sur des morceaux de texte (appelés en programmation « chaînes de caractères » ou « strings » en anglais). Dans l'exemple plus haut, nous prenons la chaîne de caractères "Player 1: " et lui adjoignons la variable `name` pour créer l'étiquette ''Player 1: Chris". +- exécuter du code en réponse à certains événements se produisant sur une page web. Dans l'exemple, nous avons utilisé un événement (« event ») {{Event("click")}} pour détecter quand l'utilisateur clique sur le bouton ; on exécute alors le code qui met à jour l'étiquette. +- Et bien plus encore ! -<p>Là où ça devient excitant, c'est que de nombreuses fonctionnalités sont basées sur ce cœur de JavaScript. Les « interfaces de programmation applicatives » (API pour « Application Programming Interfaces ») donnent accès à des fonctionnalités presqu'illimitées dans votre code JavaScript.</p> +Là où ça devient excitant, c'est que de nombreuses fonctionnalités sont basées sur ce cœur de JavaScript. Les « interfaces de programmation applicatives » (API pour « Application Programming Interfaces ») donnent accès à des fonctionnalités presqu'illimitées dans votre code JavaScript. -<p>Les API sont des blocs de code déjà prêts qui permettent à un développeur d'implémenter des programmes qui seraient difficiles voire impossibles à implémenter sans elles. C'est comme du code "en kit" pour la programmation, très pratiques à assembler et à combiner. Les API sont au code ce que les meubles en kits sont aux fournitures de maison — il est beaucoup plus facile de prendre des panneaux prêts à l'emploi et de les visser ensemble pour faire une étagère que de travailler vous-même sur le design, d'aller chercher le bon bois, de couper tous les panneaux à la bonne taille et la bonne forme, de trouver les vis de la bonne taille, puis les assembler pour faire une étagère.</p> +Les API sont des blocs de code déjà prêts qui permettent à un développeur d'implémenter des programmes qui seraient difficiles voire impossibles à implémenter sans elles. C'est comme du code "en kit" pour la programmation, très pratiques à assembler et à combiner. Les API sont au code ce que les meubles en kits sont aux fournitures de maison — il est beaucoup plus facile de prendre des panneaux prêts à l'emploi et de les visser ensemble pour faire une étagère que de travailler vous-même sur le design, d'aller chercher le bon bois, de couper tous les panneaux à la bonne taille et la bonne forme, de trouver les vis de la bonne taille, puis les assembler pour faire une étagère. -<p>Elles se divisent généralement en deux catégories :</p> +Elles se divisent généralement en deux catégories : -<p><img alt="" src="browser.png"></p> + -<p><strong>Les API de navigateur</strong> font partie intégrante de votre navigateur web, et peuvent accéder à des données de l'environnement informatique (l'ordinateur), ou faire d'autres choses complexes. Par exemple :</p> +**Les API de navigateur** font partie intégrante de votre navigateur web, et peuvent accéder à des données de l'environnement informatique (l'ordinateur), ou faire d'autres choses complexes. Par exemple : -<ul> - <li>l'<a href="/fr/docs/Web/API/Document_Object_Model">API DOM (Document Object Model)</a> permet de manipuler du HTML et du CSS (créer, supprimer et modifier du HTML, appliquer de nouveaux styles à la page de façon dynamique, etc.). Chaque fois que vous voyez une fenêtre popup sur une page ou du nouveau contenu apparaître (comme dans notre démonstration plus haut), il s'agit d'une action du DOM.</li> - <li>l'<a href="/fr/docs/Web/API/Geolocation">API de géolocalisation</a> récupère des informations géographiques. C'est ainsi que <a href="https://www.google.com/maps">Google Maps</a> peut trouver votre position et la situer sur une carte.</li> - <li>les API <a href="/fr/docs/Web/API/Canvas_API">Canvas</a> et <a href="/fr/docs/Web/API/WebGL_API">WebGL</a> permettent de créer des animations 2D et 3D. On fait des choses incroyables avec ces technologies, voyez <a href="https://www.chromeexperiments.com/webgl">Chrome Experiments</a> et <a href="https://webglsamples.org/">webglsamples</a>.</li> - <li><a href="/fr/docs/Web/Apps/Fundamentals/Audio_and_video_delivery">les API Audio et Video</a>, comme {{domxref("HTMLMediaElement")}} et <a href="/fr/docs/Web/API/WebRTC_API">WebRTC</a> permettent des actions intéressantes sur le multimédia, telles que jouer de l'audio ou de la vidéo directement dans une page web, ou récupérer le flux vidéo de votre webcam et l'afficher sur l'ordinateur de quelqu'un d'autre (essayez la <a href="http://chrisdavidmills.github.io/snapshot/">Snapshot demo </a>pour vous faire une idée).</li> -</ul> +- l'[API DOM (Document Object Model)](/fr/docs/Web/API/Document_Object_Model) permet de manipuler du HTML et du CSS (créer, supprimer et modifier du HTML, appliquer de nouveaux styles à la page de façon dynamique, etc.). Chaque fois que vous voyez une fenêtre popup sur une page ou du nouveau contenu apparaître (comme dans notre démonstration plus haut), il s'agit d'une action du DOM. +- l'[API de géolocalisation](/fr/docs/Web/API/Geolocation) récupère des informations géographiques. C'est ainsi que [Google Maps](https://www.google.com/maps) peut trouver votre position et la situer sur une carte. +- les API [Canvas](/fr/docs/Web/API/Canvas_API) et [WebGL](/fr/docs/Web/API/WebGL_API) permettent de créer des animations 2D et 3D. On fait des choses incroyables avec ces technologies, voyez [Chrome Experiments](https://www.chromeexperiments.com/webgl) et [webglsamples](https://webglsamples.org/). +- [les API Audio et Video](/fr/docs/Web/Apps/Fundamentals/Audio_and_video_delivery), comme {{domxref("HTMLMediaElement")}} et [WebRTC](/fr/docs/Web/API/WebRTC_API) permettent des actions intéressantes sur le multimédia, telles que jouer de l'audio ou de la vidéo directement dans une page web, ou récupérer le flux vidéo de votre webcam et l'afficher sur l'ordinateur de quelqu'un d'autre (essayez la [Snapshot demo ](http://chrisdavidmills.github.io/snapshot/)pour vous faire une idée). -<div class="note"> -<p><strong>Note :</strong> Beaucoup des exemples ci-dessus ne fonctionneront pas dans un ancien navigateur. Il vaut mieux utiliser un navigateur moderne comme Firefox, Chrome, Edge ou Opera pour exécuter votre code et faire vos tests. Si vous êtes amené à écrire du code de production (c'est-à-dire destiné à de véritables utilisateurs), il vous faudra prendre en compte la compatibilité pour différents navigateurs.</p> -</div> +> **Note :** Beaucoup des exemples ci-dessus ne fonctionneront pas dans un ancien navigateur. Il vaut mieux utiliser un navigateur moderne comme Firefox, Chrome, Edge ou Opera pour exécuter votre code et faire vos tests. Si vous êtes amené à écrire du code de production (c'est-à-dire destiné à de véritables utilisateurs), il vous faudra prendre en compte la compatibilité pour différents navigateurs. -<p>Les<strong> APIs tierces</strong> ne font par défaut pas partie de votre navigateur, et vous devrez en général récupérer le code et les informations les concernant quelque part sur le web. Par exemple :</p> +Les **APIs tierces** ne font par défaut pas partie de votre navigateur, et vous devrez en général récupérer le code et les informations les concernant quelque part sur le web. Par exemple : -<ul> - <li>l'<a href="https://dev.twitter.com/overview/documentation">API Twitter</a> vous permet par exemple d'afficher vos derniers tweets sur votre site.</li> - <li>l'<a href="https://developers.google.com/maps/">API Google Maps</a> permet d'intégrer à votre site des cartes personnalisées et d'autres fonctionnalités de ce type.</li> -</ul> +- l'[API Twitter](https://dev.twitter.com/overview/documentation) vous permet par exemple d'afficher vos derniers tweets sur votre site. +- l'[API Google Maps](https://developers.google.com/maps/) permet d'intégrer à votre site des cartes personnalisées et d'autres fonctionnalités de ce type. -<div class="note"> -<p><strong>Note :</strong> ces APIs sont d'un niveau avancé et nous ne couvrirons aucune d'entre elles dans ce cours, mais les liens ci-dessus fournissent une large documentation si vous voulez en savoir davantage.</p> -</div> +> **Note :** ces APIs sont d'un niveau avancé et nous ne couvrirons aucune d'entre elles dans ce cours, mais les liens ci-dessus fournissent une large documentation si vous voulez en savoir davantage. -<p>Et il y a bien plus encore ! Pas de précipitation cependant. Vous ne serez pas en mesure de créer le nouveau Facebook, Google Maps ou Instagram après une journée de travail sur JavaScript, il y a d'abord beaucoup de bases à assimiler. Et c'est pourquoi vous êtes ici. Allons-y !</p> +Et il y a bien plus encore ! Pas de précipitation cependant. Vous ne serez pas en mesure de créer le nouveau Facebook, Google Maps ou Instagram après une journée de travail sur JavaScript, il y a d'abord beaucoup de bases à assimiler. Et c'est pourquoi vous êtes ici. Allons-y ! -<h2 id="Que_fait_JavaScript_sur_votre_page">Que fait JavaScript sur votre page ?</h2> +## Que fait JavaScript sur votre page ? -<p>Ici nous allons commencer à réellement nous intéresser au code, et, ce faisant, à explorer ce qui se passe quand vous exécutez du JavaScript dans votre page.</p> +Ici nous allons commencer à réellement nous intéresser au code, et, ce faisant, à explorer ce qui se passe quand vous exécutez du JavaScript dans votre page. -<p>Commençons par un bref récapitulatif de ce qui se passe lorsqu'une page web se charge dans le navigateur (voir <a href="/fr/docs/Apprendre/CSS/Introduction_%C3%A0_CSS/Le_fonctionnement_de_CSS#Comment_fonctionnent_vraiment_les_CSS">Comment fonctionnent vraiment les CSS</a>). Quand la page se charge, les codes HTML, CSS et JavaScript s'exécutent dans un environnement (l'onglet du navigateur). C'est un peu comme une usine qui prend des matières premières (le code) et sort un produit (la page web).</p> +Commençons par un bref récapitulatif de ce qui se passe lorsqu'une page web se charge dans le navigateur (voir [Comment fonctionnent vraiment les CSS](/fr/docs/Apprendre/CSS/Introduction_%C3%A0_CSS/Le_fonctionnement_de_CSS#Comment_fonctionnent_vraiment_les_CSS)). Quand la page se charge, les codes HTML, CSS et JavaScript s'exécutent dans un environnement (l'onglet du navigateur). C'est un peu comme une usine qui prend des matières premières (le code) et sort un produit (la page web). -<p><img alt="" src="execution.png"></p> + -<p>Le JavaScript est exécuté par le moteur JavaScript du navigateur, après que le HTML et le CSS ont été assemblés et combinés en une page web. Cet enchaînement est nécessaire pour être sûr que la structure et le style de la page sont déjà en place quand le JavaScript commence son exécution.</p> +Le JavaScript est exécuté par le moteur JavaScript du navigateur, après que le HTML et le CSS ont été assemblés et combinés en une page web. Cet enchaînement est nécessaire pour être sûr que la structure et le style de la page sont déjà en place quand le JavaScript commence son exécution. -<p>C'est une bonne chose, étant donné qu'un usage fréquent de JavaScript est de modifier dynamiquement le HTML et le CSS pour mettre à jour l'interface utilisateur, via l'API DOM comme évoqué plus tôt. Charger le JavaScript et essayer de l'exécuter avant que le HTML et le CSS ne soient en place mènerait à des erreurs.</p> +C'est une bonne chose, étant donné qu'un usage fréquent de JavaScript est de modifier dynamiquement le HTML et le CSS pour mettre à jour l'interface utilisateur, via l'API DOM comme évoqué plus tôt. Charger le JavaScript et essayer de l'exécuter avant que le HTML et le CSS ne soient en place mènerait à des erreurs. -<h3 id="Sécurité_du_navigateur">Sécurité du navigateur</h3> +### Sécurité du navigateur -<p>Chaque onglet du navigateur constitue un périmètre séparé dans lequel s'exécute le code (en termes techniques ces périmètres sont des « environnements d'exécution ») ce qui signifie que, dans la plupart des cas, le code de chaque onglet est exécuté complètement séparément, et le code d'un onglet ne peut affecter directement le code d'un autre onglet ou d'un autre site. C'est une bonne mesure de sécurité. Si ce n'était pas le cas, des pirates pourraient par exemple écrire du code pour voler des informations sur d'autres sites web.</p> +Chaque onglet du navigateur constitue un périmètre séparé dans lequel s'exécute le code (en termes techniques ces périmètres sont des « environnements d'exécution ») ce qui signifie que, dans la plupart des cas, le code de chaque onglet est exécuté complètement séparément, et le code d'un onglet ne peut affecter directement le code d'un autre onglet ou d'un autre site. C'est une bonne mesure de sécurité. Si ce n'était pas le cas, des pirates pourraient par exemple écrire du code pour voler des informations sur d'autres sites web. -<div class="note"> -<p><strong>Note :</strong> il existe des moyens d'envoyer du code et des données entre différents sites/onglets de façon sécurisée, mais ce sont des techniques avancées que ne nous couvrirons pas dans ce cours.</p> -</div> +> **Note :** il existe des moyens d'envoyer du code et des données entre différents sites/onglets de façon sécurisée, mais ce sont des techniques avancées que ne nous couvrirons pas dans ce cours. -<h3 id="Ordre_d'exécution_du_JavaScript">Ordre d'exécution du JavaScript</h3> +### Ordre d'exécution du JavaScript -<p>Quand le navigateur rencontre un bloc de JavaScript, il l'exécute généralement dans l'ordre, de haut en bas. Vous devrez donc faire attention à l'ordre dans lequel vous écrivez les choses. Reprenons le bloc de JavaScript vu dans notre premier exemple :</p> +Quand le navigateur rencontre un bloc de JavaScript, il l'exécute généralement dans l'ordre, de haut en bas. Vous devrez donc faire attention à l'ordre dans lequel vous écrivez les choses. Reprenons le bloc de JavaScript vu dans notre premier exemple : -<pre class="brush: js">let para = document.querySelector('p'); +```js +let para = document.querySelector('p'); para.addEventListener('click', updateName); function updateName() { let name = prompt('Enter a new name'); para.textContent = 'Player 1: ' + name; -}</pre> +} +``` + +Nous sélectionnons ici un paragraphe de texte (ligne 1), puis lui attachons un « gestionnaire d'évènement » (<i lang="en">event listener</i>) ligne 3, pour qu'ensuite, lors d'un clic sur le paragraphe, le bloc de code `updateName()` (lignes 5-8) s'exécute. Le bloc de code `updateName()` (ces blocs de code réutilisables sont appelés « fonctions ») demande à l'utilisateur un nouveau nom, et l'insère dans le paragraphe pour mettre à jour l'affichage. + +Si vous échangiez les deux premières lignes de code, rien ne fonctionnerait plus, vous obtiendriez une erreur dans la console développeur du navigateur : `TypeError: para is undefined`. Cela signifie que l'objet `para` n'existe pas encore, donc nous ne pouvons pas y ajouter de gestionnaire d'évènement. + +> **Note :** c'est une erreur très fréquente. Il faut veiller à ce que les objets référencés dans votre code existent avant d'essayer de les utiliser. + +### Code interprété contre code compilé + +En informatique, on parle de code **interprété** ou **compilé**. JavaScript est un langage interprété : le code est exécuté de haut en bas et le résultat du code exécuté est envoyé immédiatement. Vous n'avez pas à transformer le code en une autre forme avant que le navigateur ne l'exécute. + +Les langages compilés quant à eux sont transformés (compilés) en une autre forme avant d'être exécutés par l'ordinateur. Par exemple le C et le C++ sont compilés en langage assembleur qui est ensuite exécuté par l'ordinateur. -<p>Nous sélectionnons ici un paragraphe de texte (ligne 1), puis lui attachons un « gestionnaire d'évènement » (<i lang="en">event listener</i>) ligne 3, pour qu'ensuite, lors d'un clic sur le paragraphe, le bloc de code <code>updateName()</code> (lignes 5-8) s'exécute. Le bloc de code <code>updateName()</code> (ces blocs de code réutilisables sont appelés « fonctions ») demande à l'utilisateur un nouveau nom, et l'insère dans le paragraphe pour mettre à jour l'affichage.</p> +Chaque approche a ses avantages, ce que nous ne développerons pas pour l'instant. -<p>Si vous échangiez les deux premières lignes de code, rien ne fonctionnerait plus, vous obtiendriez une erreur dans la console développeur du navigateur : <code>TypeError: para is undefined</code>. Cela signifie que l'objet <code>para</code> n'existe pas encore, donc nous ne pouvons pas y ajouter de gestionnaire d'évènement.</p> +### Code côté client contre côté serveur -<div class="note"> -<p><strong>Note :</strong> c'est une erreur très fréquente. Il faut veiller à ce que les objets référencés dans votre code existent avant d'essayer de les utiliser.</p> -</div> +Vous pouvez aussi rencontrer les termes de code **côté serveur** et **côté client**, notamment dans le contexte du développement web. Le code **côté client** est du code exécuté sur l'ordinateur de l'utilisateur : quand une page web est vue, le code côté client de la page est téléchargé, puis exécuté et affiché par le navigateur. Dans ce module JavaScript, nous parlons explicitement de **JavaScript côté client**. -<h3 id="Code_interprété_contre_code_compilé">Code interprété contre code compilé</h3> +Le code **côté serveur** quant à lui est exécuté sur le serveur, puis ses résultats sont téléchargés et affichés par le navigateur. Citons comme langages web côté serveur populaires le PHP, Python, Ruby, et ASP.NET. Et JavaScript ! JavaScript peut aussi s'utiliser comme un langage **côté serveur**, par exemple dans le populaire environnement Node.js — vous pouvez en apprendre plus sur le JavaScript côté serveur dans notre article[ Programmation de Sites Web côté serveur](/fr/docs/Learn/Server-side). -<p>En informatique, on parle de code <strong>interprété</strong> ou <strong>compilé</strong>. JavaScript est un langage interprété : le code est exécuté de haut en bas et le résultat du code exécuté est envoyé immédiatement. Vous n'avez pas à transformer le code en une autre forme avant que le navigateur ne l'exécute.</p> +### Code dynamique contre code statique -<p>Les langages compilés quant à eux sont transformés (compilés) en une autre forme avant d'être exécutés par l'ordinateur. Par exemple le C et le C++ sont compilés en langage assembleur qui est ensuite exécuté par l'ordinateur.</p> +Le mot **dynamique** est utilisé tant pour qualifier le JavaScript côté client que les langages côté serveur. Il se réfère à la capacité de mettre à jour l'affichage d'une page/application web pour montrer des choses différentes en des circonstances différentes, en générant un nouveau contenu quand nécessaire. Le code côté serveur génère dynamiquement du nouveau contenu sur le serveur, par exemple en lisant une base de données, tandis que le JavaScript côté client peut générer dynamiquement un contenu nouveau dans le navigateur, par exemple en créant une nouvelle table HTML, en y insérant les données demandées au serveur, puis en affichant la table dans une page web. Selon le contexte, le terme _dynamique_ prend un sens un peu différent, mais les deux sont très liés, et les deux approches (côté serveur et client) vont souvent de pair. -<p>Chaque approche a ses avantages, ce que nous ne développerons pas pour l'instant.</p> +Une page web sans contenu mis à jour dynamiquement est appelé **statique** : elle montre simplement toujours le même contenu. -<h3 id="Code_côté_client_contre_côté_serveur">Code côté client contre côté serveur</h3> +## Comment ajouter du JavaScript à votre page ? -<p>Vous pouvez aussi rencontrer les termes de code <strong>côté serveur</strong> et <strong>côté client</strong>, notamment dans le contexte du développement web. Le code <strong>côté client</strong> est du code exécuté sur l'ordinateur de l'utilisateur : quand une page web est vue, le code côté client de la page est téléchargé, puis exécuté et affiché par le navigateur. Dans ce module JavaScript, nous parlons explicitement de <strong>JavaScript côté client</strong>.</p> +Le JavaScript est appliqué à votre page HTML un peu comme le CSS. Les éléments {{htmlelement("link")}} permettent d'appliquer des feuilles de style externes au HTML alors que les feuilles de style internes utilisent les éléments {{htmlelement("style")}}. Pour ajouter du JavaScript à un document HTML, il n'y a qu'une seule façon : avec l'élément {{htmlelement("script")}}. Voyons cela sur un exemple. -<p>Le code <strong>côté serveur</strong> quant à lui est exécuté sur le serveur, puis ses résultats sont téléchargés et affichés par le navigateur. Citons comme langages web côté serveur populaires le PHP, Python, Ruby, et ASP.NET. Et JavaScript ! JavaScript peut aussi s'utiliser comme un langage <strong>côté serveur</strong>, par exemple dans le populaire environnement Node.js — vous pouvez en apprendre plus sur le JavaScript côté serveur dans notre article<a href="/fr/docs/Learn/Server-side"> Programmation de Sites Web côté serveur</a>.</p> +### JavaScript interne -<h3 id="Code_dynamique_contre_code_statique">Code dynamique contre code statique</h3> +1. Faites d'abord une copie locale de notre fichier d'exemple [apply-javascript.html](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript.html). Enregistrez-le dans un répertoire approprié. +2. Ouvrez le fichier dans votre navigateur web et dans un éditeur de texte. Vous verrez que le HTML crée une page web simple contenant un bouton cliquable. +3. Ensuite, allez dans votre éditeur de texte et ajoutez ce qui suit juste avant la balise fermante `</head>` : -<p>Le mot <strong>dynamique</strong> est utilisé tant pour qualifier le JavaScript côté client que les langages côté serveur. Il se réfère à la capacité de mettre à jour l'affichage d'une page/application web pour montrer des choses différentes en des circonstances différentes, en générant un nouveau contenu quand nécessaire. Le code côté serveur génère dynamiquement du nouveau contenu sur le serveur, par exemple en lisant une base de données, tandis que le JavaScript côté client peut générer dynamiquement un contenu nouveau dans le navigateur, par exemple en créant une nouvelle table HTML, en y insérant les données demandées au serveur, puis en affichant la table dans une page web. Selon le contexte, le terme <em>dynamique</em> prend un sens un peu différent, mais les deux sont très liés, et les deux approches (côté serveur et client) vont souvent de pair.</p> + ```html + <script> -<p>Une page web sans contenu mis à jour dynamiquement est appelé <strong>statique</strong> : elle montre simplement toujours le même contenu.</p> + // JavaScript goes here -<h2 id="Comment_ajouter_du_JavaScript_à_votre_page">Comment ajouter du JavaScript à votre page ?</h2> + </script> + ``` -<p>Le JavaScript est appliqué à votre page HTML un peu comme le CSS. Les éléments {{htmlelement("link")}} permettent d'appliquer des feuilles de style externes au HTML alors que les feuilles de style internes utilisent les éléments {{htmlelement("style")}}. Pour ajouter du JavaScript à un document HTML, il n'y a qu'une seule façon : avec l'élément {{htmlelement("script")}}. Voyons cela sur un exemple.</p> +4. Ajoutons maintenant du JavaScript dans notre élément {{htmlelement("script")}} pour rendre la page plus dynamique. Ajoutez le code suivant juste en dessous de la ligne "// JavaScript goes here" : -<h3 id="JavaScript_interne">JavaScript interne</h3> + ```js + document.addEventListener("DOMContentLoaded", function() { + function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'Vous avez cliqué sur le bouton!'; + document.body.appendChild(para); + } -<ol> - <li>Faites d'abord une copie locale de notre fichier d'exemple <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript.html">apply-javascript.html</a>. Enregistrez-le dans un répertoire approprié.</li> - <li>Ouvrez le fichier dans votre navigateur web et dans un éditeur de texte. Vous verrez que le HTML crée une page web simple contenant un bouton cliquable.</li> - <li>Ensuite, allez dans votre éditeur de texte et ajoutez ce qui suit juste avant la balise fermante <code></head></code> : - <pre class="brush: html"><script> + const buttons = document.querySelectorAll('button'); - // JavaScript goes here + for(let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); + } + }); + ``` -</script></pre> - </li> - <li>Ajoutons maintenant du JavaScript dans notre élément {{htmlelement("script")}} pour rendre la page plus dynamique. Ajoutez le code suivant juste en dessous de la ligne "// JavaScript goes here" : - <pre class="brush: js"> document.addEventListener("DOMContentLoaded", function() { - function createParagraph() { - let para = document.createElement('p'); - para.textContent = 'Vous avez cliqué sur le bouton!'; - document.body.appendChild(para); - } +5. Enregistrez le fichier et actualisez le navigateur. Vous pouvez maintenant voir que, lorsque vous cliquez sur le bouton, un nouveau paragraphe est généré et placé en dessous. - const buttons = document.querySelectorAll('button'); +> **Note :** si l'exemple ne semble pas marcher, reprenez pas à pas chaque étape. Avez-vous bien enregistré le code de départ comme un fichier `.html` ? Avez-vous bien ajouté l'élément {{htmlelement("script")}} juste après la balise `</head>` ? Avez-vous collé le bon code JavaScript au bon endroit ? **JavaScript est sensible à la casse, et assez tatillon, il faut donc respecter scrupuleusement la syntaxe indiquée, sans quoi il peut ne pas fonctionner.** - for(let i = 0; i < buttons.length ; i++) { - buttons[i].addEventListener('click', createParagraph); - } -});</pre> - </li> - <li>Enregistrez le fichier et actualisez le navigateur. Vous pouvez maintenant voir que, lorsque vous cliquez sur le bouton, un nouveau paragraphe est généré et placé en dessous.</li> -</ol> +> **Note :** vous pouvez voir cette version sur GitHub avec [apply-javascript-internal.html](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html) ([et aussi en live](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html)). -<div class="note"> -<p><strong>Note :</strong> si l'exemple ne semble pas marcher, reprenez pas à pas chaque étape. Avez-vous bien enregistré le code de départ comme un fichier <code>.html</code> ? Avez-vous bien ajouté l'élément {{htmlelement("script")}} juste après la balise <code></head></code> ? Avez-vous collé le bon code JavaScript au bon endroit ? <strong>JavaScript est sensible à la casse, et assez tatillon, il faut donc respecter scrupuleusement la syntaxe indiquée, sans quoi il peut ne pas fonctionner.</strong></p> -</div> +### JavaScript externe -<div class="note"> -<p><strong>Note :</strong> vous pouvez voir cette version sur GitHub avec <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html">apply-javascript-internal.html</a> (<a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html">et aussi en live</a>).</p> -</div> +Ça marche très bien, mais si nous voulons mettre notre JavaScript dans un fichier externe ? Voyons cela. -<h3 id="JavaScript_externe">JavaScript externe</h3> +1. Créez d'abord un nouveau fichier dans le même répertoire que votre fichier HTML. Nommez-le `script.js` (vérifiez qu'il a bien l'extension de fichier .js, c'est ainsi qu'il est identifié comme fichier JavaScript). +2. Ensuite, copiez-collez tout le script contenu dans l'élément {{htmlelement("script")}} vers le fichier .js, et enregistrez le fichier. +3. À présent remplacez l'élément {{htmlelement("script")}} par : -<p>Ça marche très bien, mais si nous voulons mettre notre JavaScript dans un fichier externe ? Voyons cela.</p> + ```html + <script src="script.js" defer></script> + ``` -<ol> - <li>Créez d'abord un nouveau fichier dans le même répertoire que votre fichier HTML. Nommez-le <code>script.js</code> (vérifiez qu'il a bien l'extension de fichier .js, c'est ainsi qu'il est identifié comme fichier JavaScript).</li> - <li>Ensuite, copiez-collez tout le script contenu dans l'élément {{htmlelement("script")}} vers le fichier .js, et enregistrez le fichier.</li> - <li>À présent remplacez l'élément {{htmlelement("script")}} par : - <pre class="brush: html"><script src="script.js" defer></script></pre> - </li> - <li>Enregistrez et rechargez la page dans votre navigateur, et vous devriez voir la même chose qu'avant. C'est la même chose, mais nous avons maintenant le JavaScript dans un fichier externe. C'est une bonne chose en général pour organiser le code et le rendre réutilisable pour plusieurs fichiers HTML. Cela rend aussi le code HTML plus lisible en évitant d'y inclure de gros blocs de JavaScript.</li> -</ol> +4. Enregistrez et rechargez la page dans votre navigateur, et vous devriez voir la même chose qu'avant. C'est la même chose, mais nous avons maintenant le JavaScript dans un fichier externe. C'est une bonne chose en général pour organiser le code et le rendre réutilisable pour plusieurs fichiers HTML. Cela rend aussi le code HTML plus lisible en évitant d'y inclure de gros blocs de JavaScript. -<p><strong>Note :</strong> vous pouvez voir cette version sur GitHub avec <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html">apply-javascript-external.html</a> et <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/script.js">script.js</a> (<a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html">ainsi qu'en live</a>).</p> +**Note :** vous pouvez voir cette version sur GitHub avec [apply-javascript-external.html](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html) et [script.js](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/script.js) ([ainsi qu'en live](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html)). -<h3 id="Handlers_JavaScript_en_ligne">Handlers JavaScript en ligne</h3> +### Handlers JavaScript en ligne -<p>Notez que parfois vous tomberez sur des morceaux de JavaScript directement dans le HTML. Ce qui peut ressembler à ça :</p> +Notez que parfois vous tomberez sur des morceaux de JavaScript directement dans le HTML. Ce qui peut ressembler à ça : -<pre class="brush: js example-bad">function createParagraph() { +```js example-bad +function createParagraph() { let para = document.createElement('p'); para.textContent = 'Vous avez cliqué !'; document.body.appendChild(para); -}</pre> +} +``` -<pre class="brush: html example-bad"><button onclick="createParagraph()">Cliquez-moi!</button></pre> +```html example-bad +<button onclick="createParagraph()">Cliquez-moi!</button> +``` -<p>Vous pouvez essayer cette version dans la démonstration ci-dessous.</p> +Vous pouvez essayer cette version dans la démonstration ci-dessous. -<p>{{ EmbedLiveSample('Handlers_JavaScript_en_ligne', '100%', 150) }}</p> +{{ EmbedLiveSample('Handlers_JavaScript_en_ligne', '100%', 150) }} -<p>Cet exemple a exactement le même comportement que ceux des deux sections précédentes, sauf que l'élément {{htmlelement("button")}} a un handler <code>onclick</code> en ligne pour déclencher l'exécution de la fonction à la pression du bouton.</p> +Cet exemple a exactement le même comportement que ceux des deux sections précédentes, sauf que l'élément {{htmlelement("button")}} a un handler `onclick` en ligne pour déclencher l'exécution de la fonction à la pression du bouton. -<p><strong>Évitez cependant de faire cela.</strong> C'est une mauvaise habitude de polluer le HTML avec du JavaScript, en plus d'être inefficace. Dans cette méthode, on doit inclure l'attribut <code>onclick="createParagraph()"</code> sur chaque bouton où le JavaScript doit s'appliquer.</p> +**Évitez cependant de faire cela.** C'est une mauvaise habitude de polluer le HTML avec du JavaScript, en plus d'être inefficace. Dans cette méthode, on doit inclure l'attribut `onclick="createParagraph()"` sur chaque bouton où le JavaScript doit s'appliquer. -<h3 id="En_JavaScript_pur">En JavaScript pur</h3> +### En JavaScript pur -<p>Une construction en JavaScript pur permet de sélectionner tous les boutons avec une instruction. Dans l'exemple précédent c'est cette partie qui s'en charge :</p> +Une construction en JavaScript pur permet de sélectionner tous les boutons avec une instruction. Dans l'exemple précédent c'est cette partie qui s'en charge : -<pre class="brush: js">let buttons = document.querySelectorAll('button'); +```js +let buttons = document.querySelectorAll('button'); -for(let i = 0; i < buttons.length ; i++) { +for(let i = 0; i < buttons.length ; i++) { buttons[i].addEventListener('click', createParagraph); -}</pre> +} +``` -<p>Cela peut sembler un peu plus long que l'attribut <code>onclick</code>, mais cela fonctionnera pour tous les boutons peu importe leur nombre sur la page, et peu importe si des boutons sont ajoutés ou retirés, le code JavaScript n'aura pas besoin d'être modifié.</p> +Cela peut sembler un peu plus long que l'attribut `onclick`, mais cela fonctionnera pour tous les boutons peu importe leur nombre sur la page, et peu importe si des boutons sont ajoutés ou retirés, le code JavaScript n'aura pas besoin d'être modifié. -<div class="note"> -<p><strong>Note :</strong> essayez de modifier votre version de <code>apply-javascript.html</code> et d'y ajouter quelques boutons dans le fichier. En actualisant la page, tous les boutons devraient créer un paragraphe quand ils sont cliqués. Pas mal, non ?</p> -</div> +> **Note :** essayez de modifier votre version de `apply-javascript.html` et d'y ajouter quelques boutons dans le fichier. En actualisant la page, tous les boutons devraient créer un paragraphe quand ils sont cliqués. Pas mal, non ? -<h3 id="Stratégies_de_chargement_de_script">Stratégies de chargement de script</h3> +### Stratégies de chargement de script -<p>Le chargement des scripts au bon moment pose un certain nombre de problèmes. Rien n'est aussi simple qu'il y paraît ! Un problème courant est que le code HTML d'une page se charge en suivant l'ordre d'apparition dans le code source. Si vous utilisez JavaScript pour manipuler des éléments sur la page (plus précisément, le <a href="/fr/docs/Web/API/Document_Object_Model">DOM</a>), votre code ne fonctionnera pas si le JavaScript est chargé et analysé avant le code HTML sur lequel vous voulez opérer.</p> +Le chargement des scripts au bon moment pose un certain nombre de problèmes. Rien n'est aussi simple qu'il y paraît ! Un problème courant est que le code HTML d'une page se charge en suivant l'ordre d'apparition dans le code source. Si vous utilisez JavaScript pour manipuler des éléments sur la page (plus précisément, le [DOM](/fr/docs/Web/API/Document_Object_Model)), votre code ne fonctionnera pas si le JavaScript est chargé et analysé avant le code HTML sur lequel vous voulez opérer. -<p>Dans les exemples de code interne et externe ci-dessus, le JavaScript est chargé et exécuté dans l'en-tête du document, avant que le corps soit analysé. Cela peut causer une erreur, donc nous avons utilisé des structures pour le contourner.</p> +Dans les exemples de code interne et externe ci-dessus, le JavaScript est chargé et exécuté dans l'en-tête du document, avant que le corps soit analysé. Cela peut causer une erreur, donc nous avons utilisé des structures pour le contourner. -<p>Dans l'exemple interne, vous pouvez voir cette structure autour du code :</p> +Dans l'exemple interne, vous pouvez voir cette structure autour du code : -<pre class="brush: js"> +```js document.addEventListener("DOMContentLoaded", function() { ... -});</pre> +}); +``` + +Il s'agit d'un gestionnaire d'évènement associé à l'événement `DOMContentLoaded` du navigateur, cet événement est déclenché quand le `body` HTML est complètement chargé et analysé. Le code JavaScript à l'intérieur du bloc est exécuté après le déclenchement de `DOMContentLoaded`. Par conséquent, l'erreur est évitée (vous en apprendrez plus sur les [événements](/fr/docs/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements) plus tard dans le cours). -<p>Il s'agit d'un gestionnaire d'évènement associé à l'événement <code>DOMContentLoaded</code> du navigateur, cet événement est déclenché quand le <code>body</code> HTML est complètement chargé et analysé. Le code JavaScript à l'intérieur du bloc est exécuté après le déclenchement de <code>DOMContentLoaded</code>. Par conséquent, l'erreur est évitée (vous en apprendrez plus sur les <a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Ev%C3%A8nements">événements</a> plus tard dans le cours).</p> +Dans l'exemple externe, nous utilisons une fonctionnalité JavaScript plus moderne pour résoudre le problème, l'attribut `async`, qui indique au navigateur de continuer à télécharger le contenu HTML une fois que l'élément de balise {{htmlelement("script")}} a été atteint. -<p>Dans l'exemple externe, nous utilisons une fonctionnalité JavaScript plus moderne pour résoudre le problème, l'attribut <code>async</code>, qui indique au navigateur de continuer à télécharger le contenu HTML une fois que l'élément de balise {{htmlelement("script")}} a été atteint.</p> +```js +<script src="script.js" defer></script> +``` -<pre class="brush: js"><script src="script.js" defer></script></pre> +Dans ce cas, le script et le code HTML se chargeront simultanément et le code fonctionnera. -<p>Dans ce cas, le script et le code HTML se chargeront simultanément et le code fonctionnera.</p> +> **Note :** Dans le cas externe, nous n'avions pas besoin d'utiliser l'événement `DOMContentLoaded`, car l'attribut `async` a résolu le problème pour nous. Nous n'avons pas utilisé la solution `async` pour l'exemple JavaScript interne, car elle ne fonctionne que pour les scripts externes. -<div class="note"> -<p><strong>Note :</strong> Dans le cas externe, nous n'avions pas besoin d'utiliser l'événement <code>DOMContentLoaded</code>, car l'attribut <code>async</code> a résolu le problème pour nous. Nous n'avons pas utilisé la solution <code>async</code> pour l'exemple JavaScript interne, car elle ne fonctionne que pour les scripts externes.</p> -</div> +Auparavant, une solution à ce problème consistait à placer votre élément de script juste au bas du corps (par exemple, juste avant la balise), afin qu'il soit chargé après que tout le code HTML a été analysé. Le problème de cette solution (et de la solution `DOMContentLoaded` vue ci-dessus) est que le chargement et l'analyse du script sont complètements bloqués jusqu'à ce que le DOM HTML soit chargé. Sur des sites plus importants avec beaucoup de JavaScript, cela peut entraîner un problème de performances majeur, ce qui ralentit votre site. C'est pourquoi `async` a été ajouté aux navigateurs ! -<p>Auparavant, une solution à ce problème consistait à placer votre élément de script juste au bas du corps (par exemple, juste avant la balise), afin qu'il soit chargé après que tout le code HTML a été analysé. Le problème de cette solution (et de la solution <code>DOMContentLoaded</code> vue ci-dessus) est que le chargement et l'analyse du script sont complètements bloqués jusqu'à ce que le DOM HTML soit chargé. Sur des sites plus importants avec beaucoup de JavaScript, cela peut entraîner un problème de performances majeur, ce qui ralentit votre site. C'est pourquoi <code>async</code> a été ajouté aux navigateurs !</p> +#### async et defer -<h4 id="async_et_defer">async et defer</h4> +En fait, il existe deux façons de contourner le problème du script de blocage : `async` et `defer`. Regardons la différence entre les deux. -<p>En fait, il existe deux façons de contourner le problème du script de blocage : <code>async</code> et <code>defer</code>. Regardons la différence entre les deux.</p> +Les scripts asynchrones téléchargeront le script sans bloquer le rendu de la page et l'exécuteront dès que le téléchargement du script sera terminé. Vous n'obtenez aucune garantie que les scripts s'exécutent dans un ordre spécifique, mais seulement qu'ils n'empêcheront pas le reste de la page de s'afficher. Il est préférable d'utiliser `async` lorsque les scripts de la page s'exécutent indépendamment les uns des autres et ne dépendent d'aucun autre script de la page. -<p>Les scripts asynchrones téléchargeront le script sans bloquer le rendu de la page et l'exécuteront dès que le téléchargement du script sera terminé. Vous n'obtenez aucune garantie que les scripts s'exécutent dans un ordre spécifique, mais seulement qu'ils n'empêcheront pas le reste de la page de s'afficher. Il est préférable d'utiliser <code>async</code> lorsque les scripts de la page s'exécutent indépendamment les uns des autres et ne dépendent d'aucun autre script de la page.</p> + -<img src="async-defer.jpg" alt="async vs defer" > +Image de [la spécification HTML](https://html.spec.whatwg.org/images/asyncdefer.svg), copiée et rognée selon les termes de la licence [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). -<p>Image de <a href="https://html.spec.whatwg.org/images/asyncdefer.svg" target="_blank" >la spécification HTML</a>, copiée et rognée selon les termes de la licence <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC BY 4.0</a>. -</p> +Par exemple, si vous avez les éléments de script suivants : -<p>Par exemple, si vous avez les éléments de script suivants :</p> +```html +<script async src="js/vendor/jquery.js"></script> -<pre class="brush: html"><script async src="js/vendor/jquery.js"></script> +<script async src="js/script2.js"></script> -<script async src="js/script2.js"></script> +<script async src="js/script3.js"></script> +``` -<script async src="js/script3.js"></script></pre> +Vous ne pouvez pas compter sur l'ordre dans lequel les scripts seront chargés. `Jquery.js` peut être chargé avant ou après `script2.js` et `script3.js`. Si tel est le cas, toute fonction de ces scripts dépendant de `jquery` générera une erreur, car `jquery` ne sera pas défini au moment de l'exécution du script. -<p>Vous ne pouvez pas compter sur l'ordre dans lequel les scripts seront chargés. <code>Jquery.js</code> peut être chargé avant ou après <code>script2.js</code> et <code>script3.js</code>. Si tel est le cas, toute fonction de ces scripts dépendant de <code>jquery</code> générera une erreur, car <code>jquery</code> ne sera pas défini au moment de l'exécution du script.</p> +`defer` exécute les scripts dans l'ordre dans lequel ils apparaissent dans la page et les exécute dès que le script et le contenu sont téléchargés : -<p><code>defer</code> exécute les scripts dans l'ordre dans lequel ils apparaissent dans la page et les exécute dès que le script et le contenu sont téléchargés :</p> +```html +<script defer src="js/vendor/jquery.js"></script> -<pre class="brush: html"><script defer src="js/vendor/jquery.js"></script> +<script defer src="js/script2.js"></script> -<script defer src="js/script2.js"></script> +<script defer src="js/script3.js"></script> +``` -<script defer src="js/script3.js"></script></pre> +Tous les scripts dotés de l'attribut de `defer` seront chargés dans l'ordre dans lequel ils apparaissent sur la page. Ainsi, dans le deuxième exemple, nous pouvons être sûrs que `jquery.js` se chargera avant `script2.js` et `script3.js` et que `script2.js` se chargera avant `script3.js`. -<p>Tous les scripts dotés de l'attribut de <code>defer</code> seront chargés dans l'ordre dans lequel ils apparaissent sur la page. Ainsi, dans le deuxième exemple, nous pouvons être sûrs que <code>jquery.js</code> se chargera avant <code>script2.js</code> et <code>script3.js</code> et que <code>script2.js</code> se chargera avant <code>script3.js</code>.</p> +Pour résumer : -<p>Pour résumer :</p> +- Si vos scripts n'ont pas besoin d'attendre l'analyse et peuvent s'exécuter indépendamment sans dépendances, utilisez `async`. +- Si vos scripts doivent attendre l'analyse et dépendent d'autres scripts, chargez-les à l'aide de `defer` et placez leurs éléments {{htmlelement("script")}} correspondants dans l'ordre dans lequel vous souhaitez que le navigateur les exécute. -<ul> - <li>Si vos scripts n'ont pas besoin d'attendre l'analyse et peuvent s'exécuter indépendamment sans dépendances, utilisez <code>async</code>.</li> - <li>Si vos scripts doivent attendre l'analyse et dépendent d'autres scripts, chargez-les à l'aide de <code>defer</code> et placez leurs éléments {{htmlelement("script")}} correspondants dans l'ordre dans lequel vous souhaitez que le navigateur les exécute.</li> -</ul> +## Commentaires -<h2 id="Commentaires">Commentaires</h2> +Comme pour le HTML et le CSS, il est possible d'écrire des commentaires dans le code JavaScript qui seront ignorés par le navigateur. Ils ne sont là que pour apporter des précisions aux autres développeurs sur le fonctionnement du code (et vous-même, si vous reprenez votre code après six mois sans pouvoir vous rappeler ce que vous avez fait). Les commentaires sont très utiles, et vous devriez les utiliser fréquemment, surtout pour des applications de grande taille. Il y en a deux types : -<p>Comme pour le HTML et le CSS, il est possible d'écrire des commentaires dans le code JavaScript qui seront ignorés par le navigateur. Ils ne sont là que pour apporter des précisions aux autres développeurs sur le fonctionnement du code (et vous-même, si vous reprenez votre code après six mois sans pouvoir vous rappeler ce que vous avez fait). Les commentaires sont très utiles, et vous devriez les utiliser fréquemment, surtout pour des applications de grande taille. Il y en a deux types :</p> +- Un commentaire sur une ligne s'écrit après un double slash, par exemple : -<ul> - <li>Un commentaire sur une ligne s'écrit après un double slash, par exemple : - <pre class="brush: js">// Ceci est un commentaire</pre> - </li> - <li>Un commentaire sur plusieurs lignes s'écrit entre deux balises /* et */, par exemple : - <pre class="brush: js">/* - Ceci est un commentaire - sur deux lignes -*/</pre> - </li> -</ul> + ```js + // Ceci est un commentaire + ``` -<p>Ainsi, vous pourriez par exemple annoter notre dernière démonstration de JavaScript de cette manière :</p> +- Un commentaire sur plusieurs lignes s'écrit entre deux balises /\* et \*/, par exemple : -<pre class="brush: js">// Fonction: créer un nouveau paragraphe et l'ajouter en bas du HTML + ```js + /* + Ceci est un commentaire + sur deux lignes + */ + ``` + +Ainsi, vous pourriez par exemple annoter notre dernière démonstration de JavaScript de cette manière : + +```js +// Fonction: créer un nouveau paragraphe et l'ajouter en bas du HTML function createParagraph() { let para = document.createElement('p'); @@ -378,29 +384,30 @@ function createParagraph() { let buttons = document.querySelectorAll('button'); -for(let i = 0; i < buttons.length ; i++) { +for(let i = 0; i < buttons.length ; i++) { buttons[i].addEventListener('click', createParagraph); -}</pre> +} +``` + +## Résumé -<h2 id="Résumé">Résumé</h2> +Et voilà votre premier pas dans le monde du JavaScript. Nous avons commencé par la théorie seule, pour vous habituer aux raisons d'utiliser JavaScript, et à ses possibilités. Vous avez pu voir quelques exemples de code et appris comment JavaScript s'intègre avec le reste du code sur votre site web, entre autres choses. -<p>Et voilà votre premier pas dans le monde du JavaScript. Nous avons commencé par la théorie seule, pour vous habituer aux raisons d'utiliser JavaScript, et à ses possibilités. Vous avez pu voir quelques exemples de code et appris comment JavaScript s'intègre avec le reste du code sur votre site web, entre autres choses.</p> +Le JavaScript peut sembler un peu impressionnant pour l'instant, mais pas d'inquiétude, ce cours progressera pas à pas. Dans le prochain article [Notre premier code JavaScript,](/fr/docs/Learn/JavaScript/First_steps/A_first_splash) nous entrons au cœur du sujet et vous réaliserez vos propres exemples de JavaScript. -<p>Le JavaScript peut sembler un peu impressionnant pour l'instant, mais pas d'inquiétude, ce cours progressera pas à pas. Dans le prochain article <a href="/fr/docs/Learn/JavaScript/First_steps/A_first_splash">Notre premier code JavaScript,</a> nous entrons au cœur du sujet et vous réaliserez vos propres exemples de JavaScript.</p> +{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}} -<p>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</p> +## Dans ce module +- [Qu'est-ce que JavaScript ?](/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript) +- [Un premier code JavaScript](/fr/docs/Learn/JavaScript/First_steps/A_first_splash) +- [Quel est le souci ? Analyser un problème avec JavaScript](/fr/docs/Learn/JavaScript/First_steps/What_went_wrong) +- [Stocker les informations nécessaires : les variables](/fr/docs/Learn/JavaScript/First_steps/Variables) +- [Opérations mathématiques de base en JavaScript : les nombres et les opérateurs](/fr/docs/Learn/JavaScript/First_steps/Math) +- [Gérer le texte : les chaînes de caractères en JavaScript](/fr/docs/Learn/JavaScript/First_steps/Strings) +- [Les méthodes utiles pour les chaînes de caractères](/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods) +- [Les tableaux <i lang="en">(arrays)</i>](/fr/docs/Learn/JavaScript/First_steps/Arrays) -<h2 id="In_this_module">Dans ce module</h2> + <i lang="en">(arrays)</i> -<ul> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/What_is_JavaScript">Qu'est-ce que JavaScript ?</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/A_first_splash">Un premier code JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/What_went_wrong">Quel est le souci ? Analyser un problème avec JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Variables">Stocker les informations nécessaires : les variables</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Math">Opérations mathématiques de base en JavaScript : les nombres et les opérateurs</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Strings">Gérer le texte : les chaînes de caractères en JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Useful_string_methods">Les méthodes utiles pour les chaînes de caractères</a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Arrays">Les tableaux <i lang="en">(arrays)</i></a></li> - <li><a href="/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator">Évaluation : Générateur d'histoires aléatoires</a></li> -</ul> +- [Évaluation : Générateur d'histoires aléatoires](/fr/docs/Learn/JavaScript/First_steps/Silly_story_generator) diff --git a/files/fr/learn/javascript/first_steps/what_went_wrong/index.md b/files/fr/learn/javascript/first_steps/what_went_wrong/index.md index f8ec006003..ead4a81f29 100644 --- a/files/fr/learn/javascript/first_steps/what_went_wrong/index.md +++ b/files/fr/learn/javascript/first_steps/what_went_wrong/index.md @@ -14,243 +14,258 @@ tags: - outils de développement translation_of: Learn/JavaScript/First_steps/What_went_wrong --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}} -<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</div> - -<p>Après avoir créé le jeu "Devinez le nombre" de l'article précédent, vous avez peut-être constaté qu'il ne fonctionnait pas. Pas de panique — cet article vise à ce que vous ne vous arrachiez pas les cheveux sur ces problèmes en donnant quelques conseils simples sur la façon de trouver et corriger les erreurs dans les programmes JavaScript.</p> +Après avoir créé le jeu "Devinez le nombre" de l'article précédent, vous avez peut-être constaté qu'il ne fonctionnait pas. Pas de panique — cet article vise à ce que vous ne vous arrachiez pas les cheveux sur ces problèmes en donnant quelques conseils simples sur la façon de trouver et corriger les erreurs dans les programmes JavaScript. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td> - <p>Vocabulaire courant de l'informatique, bases de HTML et CSS, compréhension de ce que fait JavaScript.</p> - </td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Acquérir la capacité et la confiance pour commencer à résoudre des problèmes simples dans votre propre code.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + <p> + Vocabulaire courant de l'informatique, bases de HTML et CSS, + compréhension de ce que fait JavaScript. + </p> + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Acquérir la capacité et la confiance pour commencer à résoudre des + problèmes simples dans votre propre code. + </td> + </tr> + </tbody> </table> -<h2 id="Types_d_erreurs">Types d' erreurs</h2> - -<p>En règle générale, les erreurs dans un code sont à ranger dans deux catégories :</p> - -<ul> - <li><strong>Erreurs de syntaxe : </strong>Ce sont les fautes d'orthographe. Elles empêchent réellement le programme de fonctionner ou l'arrêtent en cours de chemin — elles sont accompagnées de messages d'erreur. Ces erreurs sont généralement simple à corriger, pour autant que vous connaissiez les bons outils et sachiez ce que signifient les messages !</li> - <li> - <p><strong>Erreurs logiques : </strong>La syntaxe est correcte, mais le code n'est pas ce que vous attendiez : le programme tourne sans planter mais donne des résultats inattendus. Ces erreurs sont souvent plus difficiles à corriger que les erreurs de syntaxe, car il n'y a pas, en général, de message d'erreur pour vous diriger vers la source de l'erreur.</p> - </li> -</ul> - -<p>Bon, mais ce n'est pas si simple que cela — il y a d'autres facteurs de différenciation lorsque vous approfondissez. Mais la classification ci-dessus suffiira pour commencer. Nous examinerons ces deux catégories d'erreur un peu plus loin.</p> - -<h2 id="Un_exemple_erroné">Un exemple erroné</h2> - -<p>Pour commencer, revenons à notre jeu de devinettes numériques — sauf que cette fois-ci, nous explorerons une version qui comporte des erreurs délibérées. Allez sur Github et fabriquez vous-même une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html">number-game-errors.html</a> (<a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html">voyez-la ici</a> en direct).</p> - -<ol> - <li>Pour commencer, ouvrez la copie locale avec votre éditeur de texte favoris.</li> - <li>Essayez de lancer le jeu — vous remarquerez que quand vous pressez le bouton <kbd>Submit guess</kbd>, cela ne fonctionne pas!</li> -</ol> - -<div class="note"> -<p><strong>Note :</strong> Votre propre version de l'exemple de jeu ne fonctionne pas, vous pourriez vouloir la corriger ! Il nous semble plus efficace que vous travailliez sur notre version boguée, afin que vous puissiez apprendre les techniques que nous enseignons ici. Ensuite, vous pouvez revenir en arrière et essayer de réparer votre exemple.</p> -</div> - -<p>À ce stade, consultons la <a href="/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs">console du développeur</a> pour voir si nous pouvons voir des erreurs de syntaxe, puis essayez de les corriger. Vous apprendrez comment ci-dessous.</p> - -<h2 id="Réparer_les_erreurs_de_syntaxe">Réparer les erreurs de syntaxe</h2> +## Types d' erreurs + +En règle générale, les erreurs dans un code sont à ranger dans deux catégories : + +- **Erreurs de syntaxe :** Ce sont les fautes d'orthographe. Elles empêchent réellement le programme de fonctionner ou l'arrêtent en cours de chemin — elles sont accompagnées de messages d'erreur. Ces erreurs sont généralement simple à corriger, pour autant que vous connaissiez les bons outils et sachiez ce que signifient les messages ! +- **Erreurs logiques :** La syntaxe est correcte, mais le code n'est pas ce que vous attendiez : le programme tourne sans planter mais donne des résultats inattendus. Ces erreurs sont souvent plus difficiles à corriger que les erreurs de syntaxe, car il n'y a pas, en général, de message d'erreur pour vous diriger vers la source de l'erreur. + +Bon, mais ce n'est pas si simple que cela — il y a d'autres facteurs de différenciation lorsque vous approfondissez. Mais la classification ci-dessus suffiira pour commencer. Nous examinerons ces deux catégories d'erreur un peu plus loin. + +## Un exemple erroné + +Pour commencer, revenons à notre jeu de devinettes numériques — sauf que cette fois-ci, nous explorerons une version qui comporte des erreurs délibérées. Allez sur Github et fabriquez vous-même une copie locale de [number-game-errors.html](https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html) ([voyez-la ici](https://mdn.github.io/learning-area/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html) en direct). + +1. Pour commencer, ouvrez la copie locale avec votre éditeur de texte favoris. +2. Essayez de lancer le jeu — vous remarquerez que quand vous pressez le bouton + + <kbd>Submit guess</kbd> + + , cela ne fonctionne pas! + +> **Note :** Votre propre version de l'exemple de jeu ne fonctionne pas, vous pourriez vouloir la corriger ! Il nous semble plus efficace que vous travailliez sur notre version boguée, afin que vous puissiez apprendre les techniques que nous enseignons ici. Ensuite, vous pouvez revenir en arrière et essayer de réparer votre exemple. + +À ce stade, consultons la [console du développeur](/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs) pour voir si nous pouvons voir des erreurs de syntaxe, puis essayez de les corriger. Vous apprendrez comment ci-dessous. + +## Réparer les erreurs de syntaxe + +Antérieurement dans le cours, nous vous avons demandé de taper quelques commandes JavaScript simples dans la [console JavaScript](/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs) [des outils de développement](/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs) (si vous ne pouvez pas vous rappeler comment l'ouvrir dans votre navigateur, suivez le lien précédent pour savoir comment). Ce qui est encore plus utile, c'est que la console vous donne des messages d'erreur chaque fois qu'une erreur de syntaxe existe dans le JavaScript qui est introduit dans le moteur JavaScript du navigateur. Maintenant partons en chasse ! + +1. Allez à l'onglet dans lequel est affiché `number-game-errors.html`, et ouvrez la console JavaScript. Vous devriez voir un message d'erreur dans les lignes qui suivent :  +2. C'est une erreur très facile à trouver, et le navigateur vous fournit quelques indices pour vous en sortir (la copie d'écran ci‑dessus provient de Firefox, mais les autres navigateurs donnent des indications semblables). De gauche à droite, nous avons : + + - Une croix rouge indiquant que c'est une erreur. + - Un message d'erreur précisant ce qui ne va pas : "TypeError: guessSubmit.addeventListener is not a function" ("Type d'erreur : guessSubmit.addeventListener n'est pas une fonction") + - Un lien "Learn More" ("En savoir plus") pointant sur une page MDN explicitant ce que l'erreur signifie avec pléthore de détails. + - Le nom du fichier JavaScript, lié à l'onglet Debugger de l'outil de développement. Si vous suivez le lien, vous verrez exactement la ligne dans laquelle l'erreur est mise en évidence. + - Le numéro de la ligne où se situe l'erreur, et le rang du caractère dans cette ligne où l'erreur a été repérée pour la première fois. Dans notre cas, il s'agit de la ligne 86, caractère 3. + +3. En examinant la ligne 86 dans l'éditeur de code, nous voyons : + + ```js + guessSubmit.addeventListener('click', checkGuess); + ``` + +4. Le message d'erreur dit "guessSubmit.addeventListener n'est pas une fonction", donc nous avons probablement mal orthographié quelque chose. Si vous n'êtes pas sûr de la bonne orthographe d'un élément syntaxique, il est fréquemment opportun de regarder dans MDN. Actuellement, la meilleure façon d'opérer consiste à faire une recherche pour "mdn _nom-de-fonctionnalité_" avec votre moteur de recherche préféré. Voici un raccourci pour gagner un peu de temps dans le cas présent : [`addEventListener()`](/fr/docs/Web/API/EventTarget/addEventListener). +5. Donc, en regardant cette page, il apparaît que nous avions mal orthographié le nom de la fonction ! Souvenez-vous que JavaScript est sensible à la casse, et que la moindre différence dans l'orthographe ou la casse déclenchera une erreur. Remplacer `addeventListener` par `addEventListener` corrigera cela. Faisons‑le maintenant. + +> **Note :** Voyez la page relative à [TypeError: "x" is not a function](/fr/docs/Web/JavaScript/Reference/Errors/Not_a_function) pour plus de précisions à propos de cette erreur. + +### Erreurs de syntaxe : deuxième tour + +1. Enregistrez la page et actualisez‑la, vous constaterez que l'erreur a disparu. +2. Maintenant si vous entrez une supposition et pressez le bouton de soumission, vous constaterez ... une autre erreur !  +3. Cette fois‑ci, l'erreur rapportée est "TypeError: lowOrHi is null", à la ligne 78. + + > **Note :** [`Null`](/fr/docs/Glossary/Null) est une valeur spéciale signifiant "rien" ou "aucune valeur". Or `lowOrHi` a été déclaré et initialisé, mais sans valeur signifiante — il n'a ni type ni valeur. + + > **Note :** Cette erreur n'apparaît pas au moment du chargement de la page car elle survient à l'intérieur d'une fonction (dans `checkGuess() { ... }`). Comme vous l'apprendrez de manière plus précise plus loin dans l'article à propos des fonctions, le code dans les fonctions s'exécute dans une instance séparée du code en dehors des fonctions. Dans notre cas, le code n'avait pas été exécuté et l'erreur ne pouvait pas survenir avant que la fonction `checkGuess()` soit lancée à la ligne 86. + +4. Regardez à la ligne 78, vous verrez ce code : + + ```js + lowOrHi.textContent = 'Last guess was too high!'; + ``` + +5. La commande dans cette ligne essaie de définir la propriété `textContent` de la variable `lowOrHi` à l'aide d'une chaîne textuelle ; mais cela ne fonctionne pas car `lowOrHi` ne contient pas ce qui est attendu. Voyons voir — recherchons d'autres occurrences de `lowOrHi` dans le code. La plus proche que vous trouverez dans le JavaScript se situe à la ligne 48 : + + ```js + let lowOrHi = document.querySelector('lowOrHi'); + ``` + +6. Là, nous essayons de faire en sorte que la variable contienne une référence à un élément dans le HTML du document. Vérifions si sa valeur est `null` après que cette ligne ait été exécutée. Ajoutez le code suivant à la ligne 49 : + + ```js + console.log(lowOrHi); + ``` + + > **Note :** [`console.log()`](/fr/docs/Web/API/Console/log) est vraiment utile pour déboguer une fonction en affichant sa valeur sur la console. Donc, elle affichera sur cette dernière la valeur de `lowOrHi` que nous avons essayé de définir à la ligne 48. -<p>Antérieurement dans le cours, nous vous avons demandé de taper quelques commandes JavaScript simples dans la <a href="/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs">console JavaScript</a> <a href="/fr/docs/Apprendre/Découvrir_outils_développement_navigateurs">des outils de développement</a> (si vous ne pouvez pas vous rappeler comment l'ouvrir dans votre navigateur, suivez le lien précédent pour savoir comment). Ce qui est encore plus utile, c'est que la console vous donne des messages d'erreur chaque fois qu'une erreur de syntaxe existe dans le JavaScript qui est introduit dans le moteur JavaScript du navigateur. Maintenant partons en chasse !</p> +7. Enregistrez et actualisez la page, et vous verrez le résultat de `console.log()` sur la console.  C'est sûr, la valeur de `lowOrHi` est `null` à ce niveau ; il y a bien un problème à la ligne 48. +8. Quel est ce problème ? Réfléchissons. À la ligne 48, nous avons utilisé la méthode [`document.querySelector()`](/fr/docs/Web/API/Document/querySelector) pour obtenir une référence sur un élément avec un sélecteur CSS. En regardant plus en amont dans notre fichier, nous pouvons trouver le paragraphe en question : -<ol> - <li>Allez à l'onglet dans lequel est affiché <code>number-game-errors.html</code>, et ouvrez la console JavaScript. Vous devriez voir un message d'erreur dans les lignes qui suivent : <img alt="" src="not-a-function.png"></li> - <li>C'est une erreur très facile à trouver, et le navigateur vous fournit quelques indices pour vous en sortir (la copie d'écran ci‑dessus provient de Firefox, mais les autres navigateurs donnent des indications semblables). De gauche à droite, nous avons : - <ul> - <li>Une croix rouge indiquant que c'est une erreur.</li> - <li>Un message d'erreur précisant ce qui ne va pas : "TypeError: guessSubmit.addeventListener is not a function" ("Type d'erreur : guessSubmit.addeventListener n'est pas une fonction")</li> - <li>Un lien "Learn More" ("En savoir plus") pointant sur une page MDN explicitant ce que l'erreur signifie avec pléthore de détails.</li> - <li>Le nom du fichier JavaScript, lié à l'onglet Debugger de l'outil de développement. Si vous suivez le lien, vous verrez exactement la ligne dans laquelle l'erreur est mise en évidence.</li> - <li>Le numéro de la ligne où se situe l'erreur, et le rang du caractère dans cette ligne où l'erreur a été repérée pour la première fois. Dans notre cas, il s'agit de la ligne 86, caractère 3.</li> - </ul> - </li> - <li>En examinant la ligne 86 dans l'éditeur de code, nous voyons : - <pre class="brush: js">guessSubmit.addeventListener('click', checkGuess);</pre> - </li> - <li>Le message d'erreur dit "guessSubmit.addeventListener n'est pas une fonction", donc nous avons probablement mal orthographié quelque chose. Si vous n'êtes pas sûr de la bonne orthographe d'un élément syntaxique, il est fréquemment opportun de regarder dans MDN. Actuellement, la meilleure façon d'opérer consiste à faire une recherche pour "mdn <em>nom-de-fonctionnalité</em>" avec votre moteur de recherche préféré. Voici un raccourci pour gagner un peu de temps dans le cas présent : <code><a href="/fr/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>.</li> - <li>Donc, en regardant cette page, il apparaît que nous avions mal orthographié le nom de la fonction ! Souvenez-vous que JavaScript est sensible à la casse, et que la moindre différence dans l'orthographe ou la casse déclenchera une erreur. Remplacer <code>addeventListener</code> par <code>addEventListener</code> corrigera cela. Faisons‑le maintenant.</li> -</ol> + ```js + <p class="lowOrHi"></p> + ``` -<div class="note"> -<p><strong>Note :</strong> Voyez la page relative à <a href="/fr/docs/Web/JavaScript/Reference/Errors/Not_a_function">TypeError: "x" is not a function</a> pour plus de précisions à propos de cette erreur.</p> -</div> +9. Donc, il nous faut un sélecteur de classe ici, précédé d'un point (.), alors que le sélecteur passé à la méthode `querySelector()` en ligne 48 n'en a pas. Ce pourrait être le problème ! Changeons `lowOrHi` en `.lowOrHi` à la ligne 48. +10. Enregistrons et actualisons à nouveau, et la directive `console.log()` renvoie bien l'élément `<p>` attendu. Pfff ! Une autre erreur corrigée ! On peut enlever la ligne `console.log()` maintenant, ou bien la garder pour s'y reporter plus tard — comme vous l'entendez. -<h3 id="Erreurs_de_syntaxe_deuxième_tour">Erreurs de syntaxe : deuxième tour</h3> +> **Note :** Voyez la page relative à [TypeError: "x" is (not) "y"](/fr/docs/Web/JavaScript/Reference/Errors/Unexpected_type) pour plus de précisions à propos de cette erreur. -<ol> - <li>Enregistrez la page et actualisez‑la, vous constaterez que l'erreur a disparu.</li> - <li>Maintenant si vous entrez une supposition et pressez le bouton de soumission, vous constaterez ... une autre erreur ! <img alt="" src="variable-is-null.png"></li> - <li>Cette fois‑ci, l'erreur rapportée est "TypeError: lowOrHi is null", à la ligne 78. - <div class="note"> - <p><strong>Note :</strong> <code><a href="/fr/docs/Glossary/Null">Null</a></code> est une valeur spéciale signifiant "rien" ou "aucune valeur". Or <code>lowOrHi</code> a été déclaré et initialisé, mais sans valeur signifiante — il n'a ni type ni valeur.</p></div> +### Erreurs de syntaxe : troisième tour - <div class="note"> - <p><strong>Note :</strong> Cette erreur n'apparaît pas au moment du chargement de la page car elle survient à l'intérieur d'une fonction (dans <code>checkGuess() { ... }</code>). Comme vous l'apprendrez de manière plus précise plus loin dans l'article à propos des fonctions, le code dans les fonctions s'exécute dans une instance séparée du code en dehors des fonctions. Dans notre cas, le code n'avait pas été exécuté et l'erreur ne pouvait pas survenir avant que la fonction <code>checkGuess()</code> soit lancée à la ligne 86.</p></div> - </li> - <li>Regardez à la ligne 78, vous verrez ce code : - <pre class="brush: js">lowOrHi.textContent = 'Last guess was too high!';</pre> - </li> - <li>La commande dans cette ligne essaie de définir la propriété <code>textContent</code> de la variable <code>lowOrHi</code> à l'aide d'une chaîne textuelle ; mais cela ne fonctionne pas car <code>lowOrHi</code> ne contient pas ce qui est attendu. Voyons voir — recherchons d'autres occurrences de <code>lowOrHi</code> dans le code. La plus proche que vous trouverez dans le JavaScript se situe à la ligne 48 : - <pre class="brush: js">let lowOrHi = document.querySelector('lowOrHi');</pre> - </li> - <li>Là, nous essayons de faire en sorte que la variable contienne une référence à un élément dans le HTML du document. Vérifions si sa valeur est <code>null</code> après que cette ligne ait été exécutée. Ajoutez le code suivant à la ligne 49 : - <pre class="brush: js">console.log(lowOrHi);</pre> +1. Maintenant si vous essayez de jouer, cela ira mieux — tout se déroule correctement, jusqu'à ce que vous arriviez à la fin, soit en devinant le bon chiffre, soit en épuisant le nombre de tentatives permises. +2. Arrivé là, le jeu échoue à nouveau et vous rencontrez la même erreur qu'au début — "TypeError: resetButton.addeventListener is not a function" ! Mais cette fois‑ci, elle vient de la ligne 94. +3. En regardant cette ligne, il est facile de voir que nous avons fait ici la même erreur que précédemment. Il nous suffit de changer `addeventListener` en `addEventListener`. Faites‑le. - <div class="note"> - <p><strong>Note :</strong> <code><a href="/fr/docs/Web/API/Console/log">console.log()</a></code> est vraiment utile pour déboguer une fonction en affichant sa valeur sur la console. Donc, elle affichera sur cette dernière la valeur de <code>lowOrHi</code> que nous avons essayé de définir à la ligne 48.</p> - </div> - </li> - <li>Enregistrez et actualisez la page, et vous verrez le résultat de <code>console.log()</code> sur la console. <img alt="" src="console-log-output.png"> C'est sûr, la valeur de <code>lowOrHi</code> est <code>null</code> à ce niveau ; il y a bien un problème à la ligne 48.</li> - <li>Quel est ce problème ? Réfléchissons. À la ligne 48, nous avons utilisé la méthode <code><a href="/fr/docs/Web/API/Document/querySelector">document.querySelector()</a></code> pour obtenir une référence sur un élément avec un sélecteur CSS. En regardant plus en amont dans notre fichier, nous pouvons trouver le paragraphe en question : - <pre class="brush: js"><p class="lowOrHi"></p></pre> - </li> - <li>Donc, il nous faut un sélecteur de classe ici, précédé d'un point (.), alors que le sélecteur passé à la méthode <code>querySelector()</code> en ligne 48 n'en a pas. Ce pourrait être le problème ! Changeons <code>lowOrHi</code> en <code>.lowOrHi</code> à la ligne 48.</li> - <li>Enregistrons et actualisons à nouveau, et la directive <code>console.log()</code> renvoie bien l'élément <code><p></code> attendu. Pfff ! Une autre erreur corrigée ! On peut enlever la ligne <code>console.log()</code> maintenant, ou bien la garder pour s'y reporter plus tard — comme vous l'entendez.</li> -</ol> +## Une erreur de logique -<div class="note"> -<p><strong>Note :</strong> Voyez la page relative à <a href="/fr/docs/Web/JavaScript/Reference/Errors/Unexpected_type">TypeError: "x" is (not) "y"</a> pour plus de précisions à propos de cette erreur.</p> -</div> +À ce stade, le jeu se déroule correctement, mais après avoir fait quelques parties, vous noterez sans doute que le nombre « aléatoire » à deviner est toujours 0 ou 1. Franchement, de quoi vous dégoûter de jouer ! -<h3 id="Erreurs_de_syntaxe_troisième_tour">Erreurs de syntaxe : troisième tour</h3> +Il y a sûrement un problème dans la logique du jeu quelque part — le jeu ne renvoie pas d'erreur ; il ne fonctionne pas correctement. -<ol> - <li>Maintenant si vous essayez de jouer, cela ira mieux — tout se déroule correctement, jusqu'à ce que vous arriviez à la fin, soit en devinant le bon chiffre, soit en épuisant le nombre de tentatives permises.</li> - <li>Arrivé là, le jeu échoue à nouveau et vous rencontrez la même erreur qu'au début — "TypeError: resetButton.addeventListener is not a function" ! Mais cette fois‑ci, elle vient de la ligne 94.</li> - <li>En regardant cette ligne, il est facile de voir que nous avons fait ici la même erreur que précédemment. Il nous suffit de changer <code>addeventListener</code> en <code>addEventListener</code>. Faites‑le.</li> -</ol> +1. Recherchons les lignes où la variable `randomNumber` est définie. L'instance qui stocke en début de jeu le nombre aléatoire à deviner se situe autour de la ligne 44 : -<h2 id="Une_erreur_de_logique">Une erreur de logique</h2> + ```js + let randomNumber = Math.floor(Math.random()) + 1; + ``` -<p>À ce stade, le jeu se déroule correctement, mais après avoir fait quelques parties, vous noterez sans doute que le nombre « aléatoire » à deviner est toujours 0 ou 1. Franchement, de quoi vous dégoûter de jouer !</p> + Et celle qui génére le nombre aléatoire pour une succession de jeux se situe autour de la ligne 113 : -<p>Il y a sûrement un problème dans la logique du jeu quelque part — le jeu ne renvoie pas d'erreur ; il ne fonctionne pas correctement.</p> + ```js + randomNumber = Math.floor(Math.random()) + 1; + ``` -<ol> - <li>Recherchons les lignes où la variable <code>randomNumber</code> est définie. L'instance qui stocke en début de jeu le nombre aléatoire à deviner se situe autour de la ligne 44 : +2. Pour vérifier si ces lignes sont vraiment à l'origine du problème, faisons appel à nouveau à notre ami `console.log()` — insérons la ligne suivante directement en dessous des deux lignes indiquées plus haut : - <pre class="brush: js">let randomNumber = Math.floor(Math.random()) + 1;</pre> - Et celle qui génére le nombre aléatoire pour une succession de jeux se situe autour de la ligne 113 : + ```js + console.log(randomNumber); + ``` - <pre class="brush: js">randomNumber = Math.floor(Math.random()) + 1;</pre> - </li> - <li>Pour vérifier si ces lignes sont vraiment à l'origine du problème, faisons appel à nouveau à notre ami <code>console.log()</code> — insérons la ligne suivante directement en dessous des deux lignes indiquées plus haut : - <pre class="brush: js">console.log(randomNumber);</pre> - </li> - <li>Enregistrons, actualisons et jouons quelques parties — on constate que <code>randomNumber</code> est égal à 1 quel que soit le point où il est raccordé à la console.</li> -</ol> +3. Enregistrons, actualisons et jouons quelques parties — on constate que `randomNumber` est égal à 1 quel que soit le point où il est raccordé à la console. -<h3 id="Travaillons_la_logique">Travaillons la logique</h3> +### Travaillons la logique -<p>Pour corriger cela, examinons d'abord le fonctionnement de cette ligne. Premièrement, appelons <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a></code>, qui génére un nombre décimal aléatoire compris entre 0 et 1, par exemple 0.5675493843.</p> +Pour corriger cela, examinons d'abord le fonctionnement de cette ligne. Premièrement, appelons [`Math.random()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/random), qui génére un nombre décimal aléatoire compris entre 0 et 1, par exemple 0.5675493843. -<pre class="brush: js">Math.random()</pre> +```js +Math.random() +``` -<p>Puis, nous passons le résultat de l'appel de <code>Math.random()</code> à <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a></code>, qui arrondit le nombre passé à l'entier inférieur le plus proche. Puis, on ajoute 1 au résultat :</p> +Puis, nous passons le résultat de l'appel de `Math.random()` à [`Math.floor()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Math/floor), qui arrondit le nombre passé à l'entier inférieur le plus proche. Puis, on ajoute 1 au résultat : -<pre>Math.floor(Math.random()) + 1</pre> + Math.floor(Math.random()) + 1 -<p>Garder la partie entière d'un nombre décimal compris entre 0 et 1 renvoie toujours 0, y ajouter 1 donne toujours 1. Il faut multiplier le nombre aléatoire par 100 avant de l'arrondir par défaut. La ligne suivante nous donne un entier aléatoire entre 0 et 99 :</p> +Garder la partie entière d'un nombre décimal compris entre 0 et 1 renvoie toujours 0, y ajouter 1 donne toujours 1. Il faut multiplier le nombre aléatoire par 100 avant de l'arrondir par défaut. La ligne suivante nous donne un entier aléatoire entre 0 et 99 : -<pre class="brush: js">Math.floor(Math.random()*100);</pre> +```js +Math.floor(Math.random()*100); +``` -<p>Maintenant ajoutons 1 pour obtenir un nombre aléatoire entre 1 et 100 :</p> +Maintenant ajoutons 1 pour obtenir un nombre aléatoire entre 1 et 100 : -<pre class="brush: js">Math.floor(Math.random()*100) + 1;</pre> +```js +Math.floor(Math.random()*100) + 1; +``` -<p>Modifiez ces deux lignes comme indiqué, enregistrez, actualisez — le jeu devrait maintenant fonctionner comme il faut !</p> +Modifiez ces deux lignes comme indiqué, enregistrez, actualisez — le jeu devrait maintenant fonctionner comme il faut ! -<h2 id="Autres_erreurs_courantes">Autres erreurs courantes</h2> +## Autres erreurs courantes -<p>D'autres erreurs courantes peuvent être commises en écrivant du code. Ce paragraphe attire votre attention sur la plupart d'entre elles.</p> +D'autres erreurs courantes peuvent être commises en écrivant du code. Ce paragraphe attire votre attention sur la plupart d'entre elles. -<h3 id="SyntaxError_missing_before_statement">SyntaxError: missing ; before statement</h3> +### SyntaxError: missing ; before statement -<p>Cette erreur signale généralement l'oubli du point‑virgule à la fin d'une ligne de code ; mais elle peut se révéler parfois plus énigmatique. Par exemple, si, dans la fonction <code>checkGuess(),</code>nous modifions cette ligne :</p> +Cette erreur signale généralement l'oubli du point‑virgule à la fin d'une ligne de code ; mais elle peut se révéler parfois plus énigmatique. Par exemple, si, dans la fonction `checkGuess(),`nous modifions cette ligne : -<pre class="brush: js">let userGuess = Number(guessField.value);</pre> +```js +let userGuess = Number(guessField.value); +``` -<p>en</p> +en -<pre class="brush: js">let userGuess === Number(guessField.value);</pre> +```js +let userGuess === Number(guessField.value); +``` -<p>cela déclenchera cette même erreur car le logiciel pense que vous êtes en train de faire quelque chose d'autre. Vous devez vous assurer que vous n'avez pas confondu l'opérateur d'assignation (<code>=</code>) — qui fixe une valeur donnée à une variable — avec l'opérateur (<code>===</code>) qui teste la stricte égalité de deux valeurs, et renvoie un résultat <code>true</code>/<code>false</code> (vrai/faux).</p> +cela déclenchera cette même erreur car le logiciel pense que vous êtes en train de faire quelque chose d'autre. Vous devez vous assurer que vous n'avez pas confondu l'opérateur d'assignation (`=`) — qui fixe une valeur donnée à une variable — avec l'opérateur (`===`) qui teste la stricte égalité de deux valeurs, et renvoie un résultat `true`/`false` (vrai/faux). -<div class="note"> -<p><strong>Note :</strong> Voyez la page relative à <a href="/fr/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement">SyntaxError: missing ; before statement</a> pour plus de précisions à propos de cette erreur.</p> -</div> +> **Note :** Voyez la page relative à [SyntaxError: missing ; before statement](/fr/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement) pour plus de précisions à propos de cette erreur. -<h3 id="Le_programme_dit_que_vous_avez_gagné_quelle_que_soit_votre_suggestion.">Le programme dit que vous avez gagné quelle que soit votre suggestion.</h3> +### Le programme dit que vous avez gagné quelle que soit votre suggestion. -<p>Voilà un autre symptome de la confusion entre opérateur d'assignation et opérateur de test d'égalité. Ainsi, dans <code>checkGuess()</code>, si vous modifiez cette ligne :</p> +Voilà un autre symptome de la confusion entre opérateur d'assignation et opérateur de test d'égalité. Ainsi, dans `checkGuess()`, si vous modifiez cette ligne : -<pre class="brush: js">if (userGuess === randomNumber) {</pre> +```js +if (userGuess === randomNumber) { +``` -<p>en</p> +en -<pre class="brush: js">if (userGuess = randomNumber) {</pre> +```js +if (userGuess = randomNumber) { +``` -<p>le test renverra toujours <code>true</code> (vrai) et le programme indiquera que vous avez gagné à tout coup. Soyez attentif !</p> +le test renverra toujours `true` (vrai) et le programme indiquera que vous avez gagné à tout coup. Soyez attentif ! -<h3 id="SyntaxError_missing_after_argument_list">SyntaxError: missing ) after argument list</h3> +### SyntaxError: missing ) after argument list -<p>Cette erreur est triviale — elle indique en général que vous avez oublié une parenthèse fermante à la fin de l'appel d'une fonction ou d'une méthode.</p> +Cette erreur est triviale — elle indique en général que vous avez oublié une parenthèse fermante à la fin de l'appel d'une fonction ou d'une méthode. -<div class="note"> -<p><strong>Note :</strong> Voyez la page relative à <a href="/fr/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list">SyntaxError: missing ) after argument list</a> pour plus de précisions à ce propos.</p> -</div> +> **Note :** Voyez la page relative à [SyntaxError: missing ) after argument list](/fr/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list) pour plus de précisions à ce propos. -<h3 id="SyntaxError_missing_after_property_id">SyntaxError: missing : after property id</h3> +### SyntaxError: missing : after property id -<p>Cette erreur concerne généralement un objet JavaScript mal construit, mais dans ce cas nous l'avons déclenchée en modifiant</p> +Cette erreur concerne généralement un objet JavaScript mal construit, mais dans ce cas nous l'avons déclenchée en modifiant -<pre class="brush: js">function checkGuess() {</pre> +```js +function checkGuess() { +``` -<p>en</p> +en -<pre class="brush: js">function checkGuess( {</pre> +```js +function checkGuess( { +``` -<p>Le navigateur pense que vous essayez de passer le contenu d'un fonction comme argument pour l'autre fonction. Soyez attentifs avec les parenthèses !</p> +Le navigateur pense que vous essayez de passer le contenu d'un fonction comme argument pour l'autre fonction. Soyez attentifs avec les parenthèses ! -<h3 id="SyntaxError_missing_after_function_body">SyntaxError: missing } after function body</h3> +### SyntaxError: missing } after function body -<p>Facile — elle signifie généralement que vous avez omis une accolade dans une fonction ou dans une structure conditionnelle. Vous l'obtiendrez en effaçant une des accolades voisines de la terminaison de la fonction <code>checkGuess()</code>.</p> +Facile — elle signifie généralement que vous avez omis une accolade dans une fonction ou dans une structure conditionnelle. Vous l'obtiendrez en effaçant une des accolades voisines de la terminaison de la fonction `checkGuess()`. -<h3 id="SyntaxError_expected_expression_got_string_ou_SyntaxError_unterminated_string_literal">SyntaxError: expected expression, got '<em>string</em>' ou SyntaxError: unterminated string literal</h3> +### SyntaxError: expected expression, got '_string_' ou SyntaxError: unterminated string literal -<p>Ces erreurs signalent généralement l'oubli de guillemets ouvrants ou fermants dans une chaîne littérale. Dans la première erreur du titre, <em>string</em> doit être remplacé par l'un ou les caractères inattendus que l'explorateur a trouvé à la place du guillemet en début de chaîne. La deuxième erreur indique que la chaîne n'a pas été clôturée avec un guillement fermant.</p> +Ces erreurs signalent généralement l'oubli de guillemets ouvrants ou fermants dans une chaîne littérale. Dans la première erreur du titre, _string_ doit être remplacé par l'un ou les caractères inattendus que l'explorateur a trouvé à la place du guillemet en début de chaîne. La deuxième erreur indique que la chaîne n'a pas été clôturée avec un guillement fermant. -<p>Pour toutes ces erreurs, revoyez comment nous avons opéré dans les exemples de ce parcours. Quand une erreur survient, regardez le numéro de ligne indiqué, allez à cette ligne et voyez si vous remarquez ce qui ne va pas. N'oubliez pas que l'erreur n'est pas forcément sur la ligne indiquée, et qu'elle ne provient pas forcément d'un des problèmes évoqués plus haut !</p> +Pour toutes ces erreurs, revoyez comment nous avons opéré dans les exemples de ce parcours. Quand une erreur survient, regardez le numéro de ligne indiqué, allez à cette ligne et voyez si vous remarquez ce qui ne va pas. N'oubliez pas que l'erreur n'est pas forcément sur la ligne indiquée, et qu'elle ne provient pas forcément d'un des problèmes évoqués plus haut ! -<div class="note"> -<p><strong>Note :</strong> Voyez les pages relatives à <a href="/fr/docs/Web/JavaScript/Reference/Errors/Unexpected_token">SyntaxError: Unexpected token</a> et <a href="/fr/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal">SyntaxError: unterminated string literal</a> pour plus de précisions à ce propos.</p> -</div> +> **Note :** Voyez les pages relatives à [SyntaxError: Unexpected token](/fr/docs/Web/JavaScript/Reference/Errors/Unexpected_token) et [SyntaxError: unterminated string literal](/fr/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal) pour plus de précisions à ce propos. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Voilà ce que nous pouvons dire à propos des erreurs basiques pour de simples programmes JavaScript. Il n'est pas toujours aussi simple de détecter ce qui ne va pas dans du code, mais au moins vous économiserez ainsi quelques heures de veille et vous progresserez plus rapidement si les choses ne déraillent pas dès le début de votre parcours d'apprentissage.</p> +Voilà ce que nous pouvons dire à propos des erreurs basiques pour de simples programmes JavaScript. Il n'est pas toujours aussi simple de détecter ce qui ne va pas dans du code, mais au moins vous économiserez ainsi quelques heures de veille et vous progresserez plus rapidement si les choses ne déraillent pas dès le début de votre parcours d'apprentissage. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<div> -<ul> - <li>Il y a nombre d'autres erreurs qui n'ont pas été listées ici ; nous les avons récolées dans un référencement qui les explique en détail — voyez <a href="/fr/docs/Web/JavaScript/Reference/Errors">JavaScript error reference</a>.</li> - <li>Si dans votre code vous rencontrez une erreur, et même après avoir lu cet article, vous ne parvenez pas à la corriger, vous pouvez obtenir de l'aide ! Demandez‑la sur le fil de discussion <a class="external external-icon" href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Learning Area Discourse thread</a> ou par le canal IRC de <a href="irc://irc.mozilla.org/mdn">#mdn</a> sur <a class="external external-icon" href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Dites‑nous quelle est cette erreur, et nous essayerons de vous aider. Un listing de votre code sera aussi utile.</li> -</ul> -</div> +- Il y a nombre d'autres erreurs qui n'ont pas été listées ici ; nous les avons récolées dans un référencement qui les explique en détail — voyez [JavaScript error reference](/fr/docs/Web/JavaScript/Reference/Errors). +- Si dans votre code vous rencontrez une erreur, et même après avoir lu cet article, vous ne parvenez pas à la corriger, vous pouvez obtenir de l'aide ! Demandez‑la sur le fil de discussion [Learning Area Discourse thread](https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294) ou par le canal IRC de [#mdn](irc://irc.mozilla.org/mdn) sur [Mozilla IRC](https://wiki.mozilla.org/IRC). Dites‑nous quelle est cette erreur, et nous essayerons de vous aider. Un listing de votre code sera aussi utile. -<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</p> +{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}} diff --git a/files/fr/learn/javascript/index.md b/files/fr/learn/javascript/index.md index 77f8f6f168..f730e65560 100644 --- a/files/fr/learn/javascript/index.md +++ b/files/fr/learn/javascript/index.md @@ -10,53 +10,45 @@ tags: translation_of: Learn/JavaScript original_slug: Apprendre/JavaScript --- -<p>{{LearnSidebar}}</p> +{{LearnSidebar}} -<p>{{Glossary('JavaScript')}} est un langage de programmation qui vous permet de mettre en œuvre des éléments complexes sur des pages Web (une page Web contenant plus que de simples informations statiques). Chaque fois qu'une page affiche des mises à jour de contenu en temps réel, des cartes interactives, des animations graphiques 2D / 3D ou un juke-box vidéo défilant, etc. — vous pouvez parier que JavaScript est probablement impliqué.</p> +{{Glossary('JavaScript')}} est un langage de programmation qui vous permet de mettre en œuvre des éléments complexes sur des pages Web (une page Web contenant plus que de simples informations statiques). Chaque fois qu'une page affiche des mises à jour de contenu en temps réel, des cartes interactives, des animations graphiques 2D / 3D ou un juke-box vidéo défilant, etc. — vous pouvez parier que JavaScript est probablement impliqué. -<h2 id="Parcours_d'apprentissage">Parcours d'apprentissage</h2> +## Parcours d'apprentissage -<p>JavaScript est sans doute plus difficile à apprendre que les technologies connexes telles que <a href="/fr/Apprendre/HTML">HTML</a> et <a href="/fr/Apprendre/CSS">CSS</a>. Avant d'essayer d'apprendre le JavaScript, il est fortement conseillé de se familiariser d'abord avec au moins ces deux technologies, et peut-être aussi avec d'autres. Commencez par travailler sur les modules suivants :</p> +JavaScript est sans doute plus difficile à apprendre que les technologies connexes telles que [HTML](/fr/Apprendre/HTML) et [CSS](/fr/Apprendre/CSS). Avant d'essayer d'apprendre le JavaScript, il est fortement conseillé de se familiariser d'abord avec au moins ces deux technologies, et peut-être aussi avec d'autres. Commencez par travailler sur les modules suivants : -<ul> - <li><a href="/fr/Apprendre/Commencer_avec_le_web">Commencer avec le Web</a></li> - <li><a href="/fr/Apprendre/HTML/Introduction_%C3%A0_HTML">Introduction au HTML</a></li> - <li><a href="/fr/Apprendre/CSS/Introduction_%C3%A0_CSS">Introduction à CSS</a></li> -</ul> +- [Commencer avec le Web](/fr/Apprendre/Commencer_avec_le_web) +- [Introduction au HTML](/fr/Apprendre/HTML/Introduction_%C3%A0_HTML) +- [Introduction à CSS](/fr/Apprendre/CSS/Introduction_%C3%A0_CSS) -<p>Avoir une expérience antérieure avec d'autres langages de programmation peut également aider.</p> +Avoir une expérience antérieure avec d'autres langages de programmation peut également aider. -<p>Après vous être familiarisé avec les bases de JavaScript, vous devriez être en mesure d'en apprendre davantage sur des sujets plus avancés, par exemple :</p> +Après vous être familiarisé avec les bases de JavaScript, vous devriez être en mesure d'en apprendre davantage sur des sujets plus avancés, par exemple : -<ul> - <li>JavaScript en profondeur, comme enseigné dans notre <a href="/fr/docs/Web/JavaScript/Guide">guide JavaScript</a></li> - <li><a href="/fr/docs/Web/API">API web</a></li> -</ul> +- JavaScript en profondeur, comme enseigné dans notre [guide JavaScript](/fr/docs/Web/JavaScript/Guide) +- [API web](/fr/docs/Web/API) -<h2 id="Modules">Modules</h2> +## Modules -<p>Cette rubrique contient les modules suivants, dans l'ordre suggéré pour les aborder :</p> +Cette rubrique contient les modules suivants, dans l'ordre suggéré pour les aborder : -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas en JavaScript</a></dt> - <dd>Dans notre premier module JavaScript, nous répondons d'abord à des questions fondamentales telles que «qu'est-ce que le JavaScript ?», «à quoi cela ressemble-t-il ?» et «que peut-il faire ?», avant de passer à votre première expérience pratique d'écriture de JavaScript. Après cela, nous discutons en détail de certaines fonctionnalités clés de JavaScript, telles que les variables, les chaînes, les nombres et les tableaux.</dd> - <dt><a href="/fr/Apprendre/JavaScript/Building_blocks">JavaScript les blocs</a></dt> - <dd>Dans ce module, nous continuons de couvrir toutes les fonctions clés fondamentales de JavaScript, en nous concentrant sur les types de blocs de code les plus courants, tels que les instructions conditionnelles, les boucles, les fonctions et les événements. Vous avez déjà vu ce genre de choses dans le cours, mais seulement en passant, nous en discuterons explicitement ici.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Objects">Introduction aux objets JavaScript</a></dt> - <dd>En JavaScript, la plupart des éléments sont des objets, depuis les principales fonctionnalités de JavaScript comme les chaînes et les tableaux jusqu'aux API du navigateur construites sur JavaScript. Vous pouvez même créer vos propres objets pour encapsuler des fonctions et des variables associées dans des paquets efficaces. La nature orientée objet de JavaScript est importante à comprendre, si vous voulez aller plus loin dans la connaissance du langage et rédiger un code plus efficace. C'est pourquoi nous avons conçu ce module pour vous aider. Ici, nous enseignons la théorie et la syntaxe des objets en détail, regardons comment créer vos propres objets et expliquons quelles sont les données JSON et comment les utiliser.</dd> - <dt><a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs">API Web côté client</a></dt> - <dd>Lors de l'écriture de JavaScript côté client, pour des sites Web ou des applications, vous n'irez pas très loin avant de commencer à utiliser des interfaces API, pour manipuler différents aspects du navigateur et du système d'exploitation sur lequel le site fonctionne, ou même des données d'autres sites Web ou des services. Dans ce module, nous explorerons quelles sont les API et comment utiliser certaines des API les plus courantes que vous rencontrerez souvent dans votre travail de développement.</dd> -</dl> +- [Premiers pas en JavaScript](/fr/docs/Learn/JavaScript/First_steps) + - : Dans notre premier module JavaScript, nous répondons d'abord à des questions fondamentales telles que «qu'est-ce que le JavaScript ?», «à quoi cela ressemble-t-il ?» et «que peut-il faire ?», avant de passer à votre première expérience pratique d'écriture de JavaScript. Après cela, nous discutons en détail de certaines fonctionnalités clés de JavaScript, telles que les variables, les chaînes, les nombres et les tableaux. +- [JavaScript les blocs](/fr/Apprendre/JavaScript/Building_blocks) + - : Dans ce module, nous continuons de couvrir toutes les fonctions clés fondamentales de JavaScript, en nous concentrant sur les types de blocs de code les plus courants, tels que les instructions conditionnelles, les boucles, les fonctions et les événements. Vous avez déjà vu ce genre de choses dans le cours, mais seulement en passant, nous en discuterons explicitement ici. +- [Introduction aux objets JavaScript](/fr/docs/Learn/JavaScript/Objects) + - : En JavaScript, la plupart des éléments sont des objets, depuis les principales fonctionnalités de JavaScript comme les chaînes et les tableaux jusqu'aux API du navigateur construites sur JavaScript. Vous pouvez même créer vos propres objets pour encapsuler des fonctions et des variables associées dans des paquets efficaces. La nature orientée objet de JavaScript est importante à comprendre, si vous voulez aller plus loin dans la connaissance du langage et rédiger un code plus efficace. C'est pourquoi nous avons conçu ce module pour vous aider. Ici, nous enseignons la théorie et la syntaxe des objets en détail, regardons comment créer vos propres objets et expliquons quelles sont les données JSON et comment les utiliser. +- [API Web côté client](/fr/docs/Learn/JavaScript/Client-side_web_APIs) + - : Lors de l'écriture de JavaScript côté client, pour des sites Web ou des applications, vous n'irez pas très loin avant de commencer à utiliser des interfaces API, pour manipuler différents aspects du navigateur et du système d'exploitation sur lequel le site fonctionne, ou même des données d'autres sites Web ou des services. Dans ce module, nous explorerons quelles sont les API et comment utiliser certaines des API les plus courantes que vous rencontrerez souvent dans votre travail de développement. -<h2 id="Résoudre_les_problèmes_JavaScript_courants">Résoudre les problèmes JavaScript courants</h2> +## Résoudre les problèmes JavaScript courants -<p><a href="/fr/Apprendre/JavaScript/Howto">Utiliser JavaScript pour résoudre des problèmes courants</a> fournit des liens vers des sections expliquant comment utiliser JavaScript pour résoudre des problèmes très courants lors de la création d'une page Web.</p> +[Utiliser JavaScript pour résoudre des problèmes courants](/fr/Apprendre/JavaScript/Howto) fournit des liens vers des sections expliquant comment utiliser JavaScript pour résoudre des problèmes très courants lors de la création d'une page Web. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<dl> - <dt><a href="/fr/docs/Web/JavaScript">JavaScript sur MDN</a></dt> - <dd>Principal point d'entrée de la documentation JavaScript de base sur MDN, vous y trouverez de nombreux documents de référence sur tous les aspects du langage JavaScript, ainsi que des tutoriels avancés destinés aux programmeurs en JavaScript expérimentés.</dd> - <dt><a href="https://www.youtube.com/user/codingmath">Codage des mathématiques</a></dt> - <dd>Une excellente série de tutoriels vidéo (anglophones) sur les mathématiques que vous devez comprendre pour être un programmeur efficace, par <a href="https://twitter.com/bit101">Keith Peters</a>.</dd> -</dl> +- [JavaScript sur MDN](/fr/docs/Web/JavaScript) + - : Principal point d'entrée de la documentation JavaScript de base sur MDN, vous y trouverez de nombreux documents de référence sur tous les aspects du langage JavaScript, ainsi que des tutoriels avancés destinés aux programmeurs en JavaScript expérimentés. +- [Codage des mathématiques](https://www.youtube.com/user/codingmath) + - : Une excellente série de tutoriels vidéo (anglophones) sur les mathématiques que vous devez comprendre pour être un programmeur efficace, par [Keith Peters](https://twitter.com/bit101). diff --git a/files/fr/learn/javascript/objects/adding_bouncing_balls_features/index.md b/files/fr/learn/javascript/objects/adding_bouncing_balls_features/index.md index 70f35b3642..d749fec99b 100644 --- a/files/fr/learn/javascript/objects/adding_bouncing_balls_features/index.md +++ b/files/fr/learn/javascript/objects/adding_bouncing_balls_features/index.md @@ -14,112 +14,104 @@ translation_of: Learn/JavaScript/Objects/Adding_bouncing_balls_features original_slug: >- Learn/JavaScript/Objects/Ajouter_des_fonctionnalités_à_notre_démo_de_balles_rebondissantes --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</div> - -<p>Dans cet exercice, vous devrez utiliser le jeu des balles rebondissantes de l'article précédent comme base, pour y ajouter de nouvelles fonctionnalitées intéressantes.</p> +Dans cet exercice, vous devrez utiliser le jeu des balles rebondissantes de l'article précédent comme base, pour y ajouter de nouvelles fonctionnalitées intéressantes. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis:</th> - <td>Avant de vous lancer dans cet exercice, il est fortement conseillé d'avoir vus et compris tous les précédents articles de ce module.</td> - </tr> - <tr> - <th scope="row">Objectifs:</th> - <td>Tester votre connaissance du Javascript orienté objet en conception et en pratique.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis:</th> + <td> + Avant de vous lancer dans cet exercice, il est fortement conseillé + d'avoir vus et compris tous les précédents articles de ce module. + </td> + </tr> + <tr> + <th scope="row">Objectifs:</th> + <td> + Tester votre connaissance du Javascript orienté objet en conception et + en pratique. + </td> + </tr> + </tbody> </table> -<h2 id="Pour_commencer">Pour commencer</h2> - -<p>Pour commencer, faite une copie locale de <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index-finished.html">index-finished.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a>, et <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">main-finished.js</a> de l'article précédent, dans un nouveau dossier.</p> +## Pour commencer -<div class="note"> -<p><strong>Note :</strong> Vous pouvez utiliser un site comme <a class="external external-icon" href="http://jsbin.com/">JSBin</a> ou <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a>. Vous pouvez copier vos codes HTML, CSS et JavaScript dans l'un d'entre eux. Si celui que vous utilisez ne possède pas de fenêtres séparées pour les différents langages, ajoutez les dans des balises <code><script></code>/<code><style></code> dans votre code HTML.</p> -</div> +Pour commencer, faite une copie locale de [index-finished.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index-finished.html), [style.css](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css), et [main-finished.js](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js) de l'article précédent, dans un nouveau dossier. -<h2 id="Le_projet_en_bref">Le projet en bref</h2> +> **Note :** Vous pouvez utiliser un site comme [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/). Vous pouvez copier vos codes HTML, CSS et JavaScript dans l'un d'entre eux. Si celui que vous utilisez ne possède pas de fenêtres séparées pour les différents langages, ajoutez les dans des balises `<script>`/`<style>` dans votre code HTML. -<p>Notre jeu des balles est assez sympa, mais maintenant il s'agit de le rendre plus interactif en y ajoutant un viseur controlé par l'utilisateur, qui va détruire une balle si il l'a touche. Nous voulons aussi testé votre capacité en programmation orienté objet en créant un object <code>Shape()</code> dont le viseur et les balles peuvent hériter. Pour terminer nous voulons créer un compteur qui permet d'afficher combien de balle il nous reste encore à détruire.</p> +## Le projet en bref -<p>Ce screenshot vous donne une idée du résultat final:</p> +Notre jeu des balles est assez sympa, mais maintenant il s'agit de le rendre plus interactif en y ajoutant un viseur controlé par l'utilisateur, qui va détruire une balle si il l'a touche. Nous voulons aussi testé votre capacité en programmation orienté objet en créant un object `Shape()` dont le viseur et les balles peuvent hériter. Pour terminer nous voulons créer un compteur qui permet d'afficher combien de balle il nous reste encore à détruire. -<p><img alt="" src="bouncing-evil-circle.png"></p> +Ce screenshot vous donne une idée du résultat final: -<ul> -</ul> + -<p>Si vous voulez en savoir plus regardez l'exemple finit <a href="http://mdn.github.io/learning-area/javascript/oojs/assessment/">finished example</a> (N'en profitez pas pour récupérer le code source !)</p> +Si vous voulez en savoir plus regardez l'exemple finit [finished example](http://mdn.github.io/learning-area/javascript/oojs/assessment/) (N'en profitez pas pour récupérer le code source !) -<h2 id="Vos_objectifs">Vos objectifs</h2> +## Vos objectifs -<p>Cette section décrit ce que vous aurez à faire.</p> +Cette section décrit ce que vous aurez à faire. -<h3 id="Créons_nos_nouveaux_objets">Créons nos nouveaux objets</h3> +### Créons nos nouveaux objets -<p>Pour commencer, modifions le constructeur de l'objet <code>Ball()</code> pour qu'il devienne le constructeur de <code>Shape()</code> puis créons en un nouveau pour <code>Ball()</code> :</p> +Pour commencer, modifions le constructeur de l'objet `Ball()` pour qu'il devienne le constructeur de `Shape()` puis créons en un nouveau pour `Ball()` : -<ol> - <li>Le constructeur <code>Shape()</code> devra définir les propriétés <code>x</code>, <code>y</code>, <code>velX</code>, et <code>velY</code> de la même manière que le constructeur <code>Ball()</code> auparavent, mais sans les propriétés <code>color</code> et <code>size</code>.</li> - <li><code>Shape()</code> doit aussi définir une nouvelle propriété <code>exists</code>, qui servira à identifier les balles qu'il reste à détruire dans la fenêtre (celles qui n'on pas encore été détruites). Elle doit retourner un booléen (<code>true</code>/<code>false</code>).</li> - <li>Le constructeur <code>Ball()</code> doit hériter des propriétés <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, et <code>exists</code> du constructeur <code>Shape()</code>.</li> - <li><code>Ball()</code> doit aussi définir les propriétés <code>color</code> et <code>size</code>, comme à l'origine.</li> - <li>N'oubliez pas de définir le prototype de <code>Ball()</code> et son constructeur de manière approprié.</li> -</ol> +1. Le constructeur `Shape()` devra définir les propriétés `x`, `y`, `velX`, et `velY` de la même manière que le constructeur `Ball()` auparavent, mais sans les propriétés `color` et `size`. +2. `Shape()` doit aussi définir une nouvelle propriété `exists`, qui servira à identifier les balles qu'il reste à détruire dans la fenêtre (celles qui n'on pas encore été détruites). Elle doit retourner un booléen (`true`/`false`). +3. Le constructeur `Ball()` doit hériter des propriétés `x`, `y`, `velX`, `velY`, et `exists` du constructeur `Shape()`. +4. `Ball()` doit aussi définir les propriétés `color` et `size`, comme à l'origine. +5. N'oubliez pas de définir le prototype de `Ball()` et son constructeur de manière approprié. -<p>Les méthodes <code>draw()</code>, <code>update()</code>, et <code>collisionDetect()</code> doivent fonctionnées comme avant, sans être modifiées.</p> +Les méthodes `draw()`, `update()`, et `collisionDetect()` doivent fonctionnées comme avant, sans être modifiées. -<p>Vous devrez ajouter un nouveau paramètre au constructeur <code>new Ball() ( ... )</code> — le paramètre <code>exists</code> doit être le 5ème et être égal à <code>true</code>.</p> +Vous devrez ajouter un nouveau paramètre au constructeur `new Ball() ( ... )` — le paramètre `exists` doit être le 5ème et être égal à `true`. -<p>Vous pouvez recharger la page — Tout doit fonctionner comme avant même après les modifications que vous avez effectuées sur les objets.</p> +Vous pouvez recharger la page — Tout doit fonctionner comme avant même après les modifications que vous avez effectuées sur les objets. -<h3 id="Définition_du_EvilCircle()_(viseur)">Définition du EvilCircle() (viseur)</h3> +### Définition du EvilCircle() (viseur) -<p>Il est temps de vous équipez ! — le <code>EvilCircle()</code>! Dans notre jeu nous allons créer un viseur, mais nous allons nous servir de l'objet <code>Shape()</code> pour le définir. Vous voudrez certainement en ajouter un (plusieurs) autre plus tard, qu'un autre joueur ou l'ordinateur pourra contrôler. Vous n'irez probablement pas bien loin avec un seul viseur, mais ce sera suffisant pour le moment !</p> +Il est temps de vous équipez ! — le `EvilCircle()`! Dans notre jeu nous allons créer un viseur, mais nous allons nous servir de l'objet `Shape()` pour le définir. Vous voudrez certainement en ajouter un (plusieurs) autre plus tard, qu'un autre joueur ou l'ordinateur pourra contrôler. Vous n'irez probablement pas bien loin avec un seul viseur, mais ce sera suffisant pour le moment ! -<p>Le constructeur du <code>EvilCircle()</code> doit hériter des propriétés <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, et <code>exists</code> de <code>Shape()</code>, mais <code>velX</code> et <code>velY</code> doivent toujours être égales à 20.</p> +Le constructeur du `EvilCircle()` doit hériter des propriétés `x`, `y`, `velX`, `velY`, et `exists` de `Shape()`, mais `velX` et `velY` doivent toujours être égales à 20. -<p>Vous devriez utiliser quelque chose comme <code>Shape.call(this, x, y, 20, 20, exists);</code></p> +Vous devriez utiliser quelque chose comme `Shape.call(this, x, y, 20, 20, exists);` -<p>Le constructeur doit aussi définir ses propres propriétés:</p> +Le constructeur doit aussi définir ses propres propriétés: -<ul> - <li><code>color</code> — <code>'white'</code></li> - <li><code>size</code> — <code>10</code></li> -</ul> +- `color` — `'white'` +- `size` — `10` -<p>Une fois de plus, souvenez vous de définir vos propriétés héritées en paramètre du constructeur et de définir le prototype et son constructeur de manière appropriée.</p> +Une fois de plus, souvenez vous de définir vos propriétés héritées en paramètre du constructeur et de définir le prototype et son constructeur de manière appropriée. -<h3 id="Définir_les_méthodes_du_EvilCircle()_(viseur)">Définir les méthodes du EvilCircle() (viseur)</h3> +### Définir les méthodes du EvilCircle() (viseur) -<p><code>EvilCircle()</code> doit avoir quatre méthodes, comme définie en dessous.</p> +`EvilCircle()` doit avoir quatre méthodes, comme définie en dessous. -<h4 id="draw()"><code>draw()</code></h4> +#### `draw()` -<p>Cette méthode doit avoir la même fonction que celle de <code>Ball()</code>: soit dessiner l'objet dans le canvas. Elle fonctionnera quasiment de la même manière, copiez la fonction <code>Ball.prototype.draw</code>. Puis appliquez les modifications suivantes:</p> +Cette méthode doit avoir la même fonction que celle de `Ball()`: soit dessiner l'objet dans le canvas. Elle fonctionnera quasiment de la même manière, copiez la fonction `Ball.prototype.draw`. Puis appliquez les modifications suivantes: -<ul> - <li>On ne veut pas que le viseur soit plein, mais qu'il ait seulement un contour. Changez <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> et <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> pour <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/strokeStyle">strokeStyle</a></code> et <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/stroke">stroke()</a></code>.</li> - <li>On voudrait qu'il soit aussi un peu plus épais, pour être plus facile à voir. Pour ça on doit définir un attribut <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/lineWidth">lineWidth</a></code> à ctx après l'appel à la fonction <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> (avec une valeur de 3).</li> -</ul> +- On ne veut pas que le viseur soit plein, mais qu'il ait seulement un contour. Changez [`fillStyle`](/fr/docs/Web/API/CanvasRenderingContext2D/fillStyle) et [`fill()`](/fr/docs/Web/API/CanvasRenderingContext2D/fill) pour [`strokeStyle`](/fr/docs/Web/API/CanvasRenderingContext2D/strokeStyle) et [`stroke()`](/fr/docs/Web/API/CanvasRenderingContext2D/stroke). +- On voudrait qu'il soit aussi un peu plus épais, pour être plus facile à voir. Pour ça on doit définir un attribut [`lineWidth`](/fr/docs/Web/API/CanvasRenderingContext2D/lineWidth) à ctx après l'appel à la fonction [`beginPath()`](/fr/docs/Web/API/CanvasRenderingContext2D/beginPath) (avec une valeur de 3). -<h4 id="checkBounds()"><code>checkBounds()</code></h4> +#### `checkBounds()` -<p>Cette méthode à la même fonction que la première partie de <code>Ball()</code> <code>update()</code> — Savoir si le viseur va hors de l'écran, et l'arrêter si besoin. Une fois encore, copié la méthode <code>Ball.prototype.update</code>, mais en effectuant quelques changements:</p> +Cette méthode à la même fonction que la première partie de `Ball()` `update()` — Savoir si le viseur va hors de l'écran, et l'arrêter si besoin. Une fois encore, copié la méthode `Ball.prototype.update`, mais en effectuant quelques changements: -<ul> - <li>Débarrassez-vous des deux dernières lignes — on a pas besoin de connaître la position du viseur à chaque frame, car nous le déplacerons d'une manière différente comme vous pourrez le voir.</li> - <li>Dans les conditions en <code>if()</code> , si la condition retourne true on ne veut pas modifier (update) les propriétés <code>velX</code>/<code>velY</code>; mais plutôt changer les valeurs de <code>x</code>/<code>y</code> de manière à ce que le viseur revienne doucement dans l'écran. Ajouter ou soustraire de manière appropriée la taille (<code>size)</code> du viseur sera suffisant.</li> -</ul> +- Débarrassez-vous des deux dernières lignes — on a pas besoin de connaître la position du viseur à chaque frame, car nous le déplacerons d'une manière différente comme vous pourrez le voir. +- Dans les conditions en `if()` , si la condition retourne true on ne veut pas modifier (update) les propriétés `velX`/`velY`; mais plutôt changer les valeurs de `x`/`y` de manière à ce que le viseur revienne doucement dans l'écran. Ajouter ou soustraire de manière appropriée la taille (`size)` du viseur sera suffisant. -<h4 id="setControls()"><code>setControls()</code></h4> +#### `setControls()` -<p>Cette méthode ajoute un écouteur d'évènement <code>onkeydown</code> à l'objet <code>window</code> ce qui permettra en enfonçant certaine touche du clavier de déplacer le viseur dans la fenêtre. Insérez le code suivant dans la méthode:</p> +Cette méthode ajoute un écouteur d'évènement `onkeydown` à l'objet `window` ce qui permettra en enfonçant certaine touche du clavier de déplacer le viseur dans la fenêtre. Insérez le code suivant dans la méthode: -<pre class="brush: js">var _this = this; +```js +var _this = this; window.onkeydown = function(e) { if (e.keyCode === 65) { _this.x -= _this.velX; @@ -130,80 +122,70 @@ window.onkeydown = function(e) { } else if (e.keyCode === 83) { _this.y += _this.velY; } - }</pre> - -<p>Quand une touche est enfoncée, la propriété <a href="/fr/docs/Web/API/KeyboardEvent/keyCode">keyCode</a> de l'objet event est consultée pour savoir quelle touche est enfoncée. Si c'est une des touches spécifiée, alors le viseur ce déplacera à gauche, à droite, en haut ou en bas.</p> - -<ul> - <li>Pour un point bonus, faite apparaître à quel touche correspond le code de celle que l'utilisateur a enfoncé.</li> - <li>Pour un second point bonus, pouvez vous nous dire pourquoi nous devons définir <code>var _this = this;</code> de cette façon ? Cela à quelque chose à voir avec la portée des fonction.</li> -</ul> - -<h4 id="collisionDetect()"><code>collisionDetect()</code></h4> - -<p>Cette méthode fonctionne d'une manière similaire à <code>Ball()</code> <code>collisionDetect()</code>, copier celle-ci pour vous en servir comme base. Il y a deux différences:</p> - -<ul> - <li>Dans la condition extérieure <code>if</code>, nous n'avons plus besoin de vérifier si la balle actuellement dans la boucle est celle actuellement surveiller — Parce que ce n'est plus une balle, mais notre viseur ! A la place, on doit tester si la balle visée existe (avec quelle propriété pourrez vous faire cela?). Si elle n'existe pas, c'est qu'elle a déjà été détruite, on a donc pas besoin de la vérifier encore une fois.</li> - <li>Dans la condition intérieur <code>if</code>, on ne souhaite plus changer un élément de couleur lorsqu'une collision est détéctée — A la place, on veut détruire les balles qui entre en collision avec le viseur (encore une fois, comment pensez-vous faire cela ?).</li> -</ul> - -<h3 id="Insérer_le_viseur_dans_notre_programme">Insérer le viseur dans notre programme</h3> - -<p>Maintenant que nous avons définit notre viseur, on a besoin de le faire apparaître à l'écran. Pour ce faire on doit appliquer quelques modifications à la fonction <code>loop()</code>.</p> - -<ul> - <li>Premièrement, créons une nouvelle instance de l'objet viseur (en spécifiant les paramètres nécessaire), et appelons sa méthode <code>setControls()</code>. On doit seulement effectuer ses deux actions une seule fois, pas à chaque itération.</li> - <li>Au moment où l'on boucle à travers toutes les balles et que l'on appelle les méthodes <code>draw()</code>, <code>update()</code>, et <code>collisionDetect()</code> pour chacune d'entre elle, faite de manière à ce que ces fonctions soit appelées seulement si la balle existe.</li> - <li>Appellez les méthodes de l'instance du viseur <code>draw()</code>, <code>checkBounds()</code>, et <code>collisionDetect()</code> à chaque itération de la boucle.</li> -</ul> - -<h3 id="Implémenter_le_compteur_de_score">Implémenter le compteur de score</h3> - -<p>Pour implémenter le compteur de score, suivez les étapes suivantes:</p> - -<ol> - <li>Dans votre fichier HTML, ajoutez un élement {{HTMLElement("p")}} qui contiendra le texte suivant "Ball count: ", juste en dessous de l'élément {{HTMLElement("h1")}} .</li> - <li>Dans votre fichier CSS, ajouter les règlesz suivantes: - <pre class="brush: css">p { - position: absolute; - margin: 0; - top: 35px; - right: 5px; - color: #aaa; -}</pre> - </li> - <li>Dans votre JavaScript, effectuez les modifications suivante: - <ul> - <li>Créez une variable qui contiendra la référence vers le paragraphe.</li> - <li>Stocker et afficher le nombre de balle présentent à l'écran.</li> - <li>Incrémentez le compteur de balle à chaque fois qu'une balle apparait à l'écran.</li> - <li>Décrementez le compteur à chaque fois qu'une balle est détruite par le viseur.</li> - </ul> - </li> -</ol> - -<h2 id="Conseils_et_astuces">Conseils et astuces</h2> - -<ul> - <li>Cet exercice est un bon challenge. Prenez le temps de faire et de comprendre chaque étape.</li> - <li>Ce serait une bonne idée de garder une copie de chaque étape lorsque vous arrivez à la faire marcher correctement, pour vous y réferrer si vous n'arrivez plus à progresser ensuite.</li> -</ul> - -<h2 id="Evaluation">Evaluation</h2> - -<p>Si vous effectuez cette évalutation dans le cadre d'un cours, vous devriez pouvoir fournir votre travail à votre professeur/mentor pour correction. Si vous apprenez par vous même, vous pouvez obtenir la correction sur <a href="https://discourse.mozilla.org/t/adding-features-to-our-bouncing-balls-demo-assessment/24689">discussion thread for this exercise</a>, ou sur <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC channel sur <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Tout d'abord effectuez cet exercice — vous n'obtiendrez jamais rien en trichant !</p> - -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</p> - -<h2 id="Dans_ce_Module">Dans ce Module</h2> - -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> -</ul> + } +``` + +Quand une touche est enfoncée, la propriété [keyCode](/fr/docs/Web/API/KeyboardEvent/keyCode) de l'objet event est consultée pour savoir quelle touche est enfoncée. Si c'est une des touches spécifiée, alors le viseur ce déplacera à gauche, à droite, en haut ou en bas. + +- Pour un point bonus, faite apparaître à quel touche correspond le code de celle que l'utilisateur a enfoncé. +- Pour un second point bonus, pouvez vous nous dire pourquoi nous devons définir `var _this = this;` de cette façon ? Cela à quelque chose à voir avec la portée des fonction. + +#### `collisionDetect()` + +Cette méthode fonctionne d'une manière similaire à `Ball()` `collisionDetect()`, copier celle-ci pour vous en servir comme base. Il y a deux différences: + +- Dans la condition extérieure `if`, nous n'avons plus besoin de vérifier si la balle actuellement dans la boucle est celle actuellement surveiller — Parce que ce n'est plus une balle, mais notre viseur ! A la place, on doit tester si la balle visée existe (avec quelle propriété pourrez vous faire cela?). Si elle n'existe pas, c'est qu'elle a déjà été détruite, on a donc pas besoin de la vérifier encore une fois. +- Dans la condition intérieur `if`, on ne souhaite plus changer un élément de couleur lorsqu'une collision est détéctée — A la place, on veut détruire les balles qui entre en collision avec le viseur (encore une fois, comment pensez-vous faire cela ?). + +### Insérer le viseur dans notre programme + +Maintenant que nous avons définit notre viseur, on a besoin de le faire apparaître à l'écran. Pour ce faire on doit appliquer quelques modifications à la fonction `loop()`. + +- Premièrement, créons une nouvelle instance de l'objet viseur (en spécifiant les paramètres nécessaire), et appelons sa méthode `setControls()`. On doit seulement effectuer ses deux actions une seule fois, pas à chaque itération. +- Au moment où l'on boucle à travers toutes les balles et que l'on appelle les méthodes `draw()`, `update()`, et `collisionDetect()` pour chacune d'entre elle, faite de manière à ce que ces fonctions soit appelées seulement si la balle existe. +- Appellez les méthodes de l'instance du viseur `draw()`, `checkBounds()`, et `collisionDetect()` à chaque itération de la boucle. + +### Implémenter le compteur de score + +Pour implémenter le compteur de score, suivez les étapes suivantes: + +1. Dans votre fichier HTML, ajoutez un élement {{HTMLElement("p")}} qui contiendra le texte suivant "Ball count: ", juste en dessous de l'élément {{HTMLElement("h1")}} . +2. Dans votre fichier CSS, ajouter les règlesz suivantes: + + ```css + p { + position: absolute; + margin: 0; + top: 35px; + right: 5px; + color: #aaa; + } + ``` + +3. Dans votre JavaScript, effectuez les modifications suivante: + + - Créez une variable qui contiendra la référence vers le paragraphe. + - Stocker et afficher le nombre de balle présentent à l'écran. + - Incrémentez le compteur de balle à chaque fois qu'une balle apparait à l'écran. + - Décrementez le compteur à chaque fois qu'une balle est détruite par le viseur. + +## Conseils et astuces + +- Cet exercice est un bon challenge. Prenez le temps de faire et de comprendre chaque étape. +- Ce serait une bonne idée de garder une copie de chaque étape lorsque vous arrivez à la faire marcher correctement, pour vous y réferrer si vous n'arrivez plus à progresser ensuite. + +## Evaluation + +Si vous effectuez cette évalutation dans le cadre d'un cours, vous devriez pouvoir fournir votre travail à votre professeur/mentor pour correction. Si vous apprenez par vous même, vous pouvez obtenir la correction sur [discussion thread for this exercise](https://discourse.mozilla.org/t/adding-features-to-our-bouncing-balls-demo-assessment/24689), ou sur [#mdn](irc://irc.mozilla.org/mdn) IRC channel sur [Mozilla IRC](https://wiki.mozilla.org/IRC). Tout d'abord effectuez cet exercice — vous n'obtiendrez jamais rien en trichant ! + +{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}} + +## Dans ce Module + +- [Object basics](/fr/docs/Learn/JavaScript/Objects/Basics) +- [Object-oriented JavaScript for beginners](/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS) +- [Object prototypes](/fr/docs/Learn/JavaScript/Objects/Object_prototypes) +- [Inheritance in JavaScript](/fr/docs/Learn/JavaScript/Objects/Inheritance) +- [Working with JSON data](/fr/docs/Learn/JavaScript/Objects/JSON) +- [Object building practice](/fr/docs/Learn/JavaScript/Objects/Object_building_practice) +- [Adding features to our bouncing balls demo](/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features) diff --git a/files/fr/learn/javascript/objects/basics/index.md b/files/fr/learn/javascript/objects/basics/index.md index 483ebba0fc..dfca7d223a 100644 --- a/files/fr/learn/javascript/objects/basics/index.md +++ b/files/fr/learn/javascript/objects/basics/index.md @@ -1,5 +1,5 @@ --- -title: 'Les bases de JavaScript, orienté objet' +title: Les bases de JavaScript, orienté objet slug: Learn/JavaScript/Objects/Basics tags: - API @@ -11,42 +11,56 @@ tags: - this translation_of: Learn/JavaScript/Objects/Basics --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}} -<div>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</div> - -<p>Dans ce premier article sur les objets JavaScript, nous verrons la syntaxe des objets JavaScript ainsi que quelques fonctionnalités JavaScript déjà aperçues dans les cours précédents, rappelant que beaucoup de fonctionnalités que vous utilisez sont en fait des objets.</p> +Dans ce premier article sur les objets JavaScript, nous verrons la syntaxe des objets JavaScript ainsi que quelques fonctionnalités JavaScript déjà aperçues dans les cours précédents, rappelant que beaucoup de fonctionnalités que vous utilisez sont en fait des objets. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Connaissances informatiques de base, connaissances basiques concernant HTML et CSS, bonnes connaissances des bases de JavaScript (cf. <a href="/fr/docs/Learn/JavaScript/First_steps">les premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">les briques de construction</a>).</td> - </tr> - <tr> - <th scope="row">Objectifs :</th> - <td>Comprendre les théories de base derrière la programmation orientée objet, comment l'appliquer à JavaScript, et comment travailler avec des objets JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Connaissances informatiques de base, connaissances basiques concernant + HTML et CSS, bonnes connaissances des bases de JavaScript (cf. + <a href="/fr/docs/Learn/JavaScript/First_steps">les premiers pas</a> et + <a href="/fr/docs/Learn/JavaScript/Building_blocks" + >les briques de construction</a + >). + </td> + </tr> + <tr> + <th scope="row">Objectifs :</th> + <td> + Comprendre les théories de base derrière la programmation orientée + objet, comment l'appliquer à JavaScript, et comment travailler avec des + objets JavaScript. + </td> + </tr> + </tbody> </table> -<h2 id="Les_bases_de_lobjet">Les bases de l'objet</h2> +## Les bases de l'objet -<p>Un objet est une collection de données apparentées et/ou de fonctionnalités (qui, souvent, se composent de plusieurs variables et fonctions, appelées propriétés et méthodes quand elles sont dans des objets). Prenons un exemple pour voir à quoi cela ressemble.</p> +Un objet est une collection de données apparentées et/ou de fonctionnalités (qui, souvent, se composent de plusieurs variables et fonctions, appelées propriétés et méthodes quand elles sont dans des objets). Prenons un exemple pour voir à quoi cela ressemble. -<p>Pour commencer, faites une copie locale de notre fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a>. Il contient peu de choses : un élément {{HTMLElement("script")}} pour écrire notre code à l'intérieur. Nous utiliserons ces éléments de base pour explorer les bases de la syntaxe objet. Durant cette exemple, vous devriez avoir <a href="/fr/docs/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs#La_console_JavaScript">la console JavaScript des outils de développement</a> ouverte et prête, pour y saisir des commandes.</p> +Pour commencer, faites une copie locale de notre fichier [oojs.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html). Il contient peu de choses : un élément {{HTMLElement("script")}} pour écrire notre code à l'intérieur. Nous utiliserons ces éléments de base pour explorer les bases de la syntaxe objet. Durant cette exemple, vous devriez avoir [la console JavaScript des outils de développement](/fr/docs/Apprendre/D%C3%A9couvrir_outils_d%C3%A9veloppement_navigateurs#La_console_JavaScript) ouverte et prête, pour y saisir des commandes. -<p>Comme souvent dans JavaScript, pour créer un objet, on commence avec la définition et l'initialisation d'une variable. Essayez de mettre le code ci-dessous sous le code déjà écrit de votre fichier JavaScript, puis sauvegardez et rafraichissez la page :</p> +Comme souvent dans JavaScript, pour créer un objet, on commence avec la définition et l'initialisation d'une variable. Essayez de mettre le code ci-dessous sous le code déjà écrit de votre fichier JavaScript, puis sauvegardez et rafraichissez la page : -<pre class="brush: js">var personne = {};</pre> +```js +var personne = {}; +``` -<p>Désormais ouvrez la <a href="/fr/docs/Outils/Console_JavaScript#Ouvrir_la_Console_du_navigateur">console JavaScript</a> de votre navigateur, saisissez <code>personne</code> à l'intérieur, et appuyez sur <kbd>Entrée</kbd>. Vous devriez obtenir le résultat suivant :</p> +Désormais ouvrez la [console JavaScript](/fr/docs/Outils/Console_JavaScript#Ouvrir_la_Console_du_navigateur) de votre navigateur, saisissez `personne` à l'intérieur, et appuyez sur <kbd>Entrée</kbd>. Vous devriez obtenir le résultat suivant : -<pre class="brush: js">[object Object]</pre> +```js +[object Object] +``` -<p>Félicitations, vous avez créé votre premier objet ! Mais c'est un objet vide, on ne peut pas faire grand-chose avec. Modifions notre objet pour qu'il ressemble à ceci :</p> +Félicitations, vous avez créé votre premier objet ! Mais c'est un objet vide, on ne peut pas faire grand-chose avec. Modifions notre objet pour qu'il ressemble à ceci : -<pre class="brush: js">var personne = { +```js +var personne = { nom: ['Jean', 'Martin'], age: 32, sexe: 'masculin', @@ -58,151 +72,188 @@ translation_of: Learn/JavaScript/Objects/Basics alert('Bonjour ! Je suis ' + this.nom[0] + '.'); } }; -</pre> +``` -<p>Après avoir sauvegardé et rafraîchit la page, essayez d'entrer les lignes suivantes dans le champ de saisie <code>input</code> :</p> +Après avoir sauvegardé et rafraîchit la page, essayez d'entrer les lignes suivantes dans le champ de saisie `input` : -<pre class="brush: js">personne.nom +```js +personne.nom personne.nom[0] personne.age personne.interets[1] personne.bio() -personne.salutation()</pre> +personne.salutation() +``` -<p>Vous avez désormais des données et des fonctionnalités dans votre objet, et vous pouvez y accéder avec une une syntaxe simple et claire !</p> +Vous avez désormais des données et des fonctionnalités dans votre objet, et vous pouvez y accéder avec une une syntaxe simple et claire ! -<div class="note"> -<p><strong>Note :</strong> Si vous avez des difficultés pour le faire fonctionner, comparez votre code avec notre version — voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-finished.html">oojs-finished.html</a> (ou <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-finished.html">voir en action</a>). Une erreur courante, quand on commence avec les objets, est de mettre une virgule après la dernière propriété — ce qui provoque une erreur.</p> -</div> +> **Note :** Si vous avez des difficultés pour le faire fonctionner, comparez votre code avec notre version — voir [oojs-finished.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-finished.html) (ou [voir en action](https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-finished.html)). Une erreur courante, quand on commence avec les objets, est de mettre une virgule après la dernière propriété — ce qui provoque une erreur. -<p>Alors, comment ça fonctionne ? Un objet est fait de plusieurs membres, qui ont chacun un nom (par exemple <code>nom</code> et <code>age</code> ci-dessus) et une valeur (par exemple. <code>['Jean', 'Martin']</code> et <code>32</code>).</p> +Alors, comment ça fonctionne ? Un objet est fait de plusieurs membres, qui ont chacun un nom (par exemple `nom` et `age` ci-dessus) et une valeur (par exemple. `['Jean', 'Martin']` et `32`). -<p>Chaque paire de nom/valeur doit être séparée par une virgule, et le nom et la valeur de chaque membre sont séparés par deux points. La syntaxe suit ce schéma :</p> +Chaque paire de nom/valeur doit être séparée par une virgule, et le nom et la valeur de chaque membre sont séparés par deux points. La syntaxe suit ce schéma : -<pre class="brush: js">var monObjet = { +```js +var monObjet = { nomDuMembre1: valeurDuMembre1, nomDuMembre2: valeurDuMembre2, nomDuMembre3: valeurDuMembre3 -}</pre> +} +``` -<p>La valeur d'un membre dans un objet peut être n'importe quoi — dans notre objet <code>personne</code>, nous avons du texte, un nombre, deux tableaux et deux fonctions. Les quatre premières éléments sont des données appelées <strong>propriétés</strong> de l'objet, et les deux derniers éléments sont des fonctions qui utilisent les données de l'objet pour faire quelque chose, et sont appelées des <strong>méthodes</strong> de l'objet.</p> +La valeur d'un membre dans un objet peut être n'importe quoi — dans notre objet `personne`, nous avons du texte, un nombre, deux tableaux et deux fonctions. Les quatre premières éléments sont des données appelées **propriétés** de l'objet, et les deux derniers éléments sont des fonctions qui utilisent les données de l'objet pour faire quelque chose, et sont appelées des **méthodes** de l'objet. -<p>Dans cet exemple, l'objet est créé grâce à un<strong> objet littéral</strong> : on écrit littéralement le contenu de l'objet pour le créer. On distinguera cette structure des objets instanciés depuis des classes, que nous verrons plus tard.</p> +Dans cet exemple, l'objet est créé grâce à un **objet littéral** : on écrit littéralement le contenu de l'objet pour le créer. On distinguera cette structure des objets instanciés depuis des classes, que nous verrons plus tard. -<p>C'est une pratique très courante de créer un objet en utilisant un objet littéral : par exemple, quand on envoie une requête au serveur pour transférer des données vers une base de données.</p> +C'est une pratique très courante de créer un objet en utilisant un objet littéral : par exemple, quand on envoie une requête au serveur pour transférer des données vers une base de données. -<p>Envoyer un seul objet est bien plus efficace que d'envoyer ses membres de manière individuelle, et c'est bien plus simple de travailler avec un tableau quand on veut identifier des membres par leur nom.</p> +Envoyer un seul objet est bien plus efficace que d'envoyer ses membres de manière individuelle, et c'est bien plus simple de travailler avec un tableau quand on veut identifier des membres par leur nom. -<h2 id="Notation_avec_un_point">Notation avec un point</h2> +## Notation avec un point -<p>Ci-dessus, on accède aux membres de l'objet en utilisant la <strong>notation avec un point</strong>.</p> +Ci-dessus, on accède aux membres de l'objet en utilisant la **notation avec un point**. -<p>Le nom de l'objet (<code>personne</code>) agit comme un <strong>espace de noms</strong> (ou <em>namespace</em> en anglais) — il doit être entré en premier pour accéder aux membres <strong>encapsulés</strong> dans l'objet. Ensuite, on écrit un point, puis le membre auquel on veut accéder — que ce soit le nom d'une propriété, un élément d'un tableau, ou un appel à une méthode de l'objet. Par exemple :</p> +Le nom de l'objet (`personne`) agit comme un **espace de noms** (ou _namespace_ en anglais) — il doit être entré en premier pour accéder aux membres **encapsulés** dans l'objet. Ensuite, on écrit un point, puis le membre auquel on veut accéder — que ce soit le nom d'une propriété, un élément d'un tableau, ou un appel à une méthode de l'objet. Par exemple : -<pre class="brush: js">personne.age +```js +personne.age personne.interets[1] -personne.bio()</pre> +personne.bio() +``` -<h3 id="Sous-espaces_de_noms">Sous-espaces de noms</h3> +### Sous-espaces de noms -<p>Il est même possible de donner un autre objet comme valeur d'un membre de l'objet. Par exemple, on peut essayer de changer la propriété <code>nom</code> du membre et la faire passer de</p> +Il est même possible de donner un autre objet comme valeur d'un membre de l'objet. Par exemple, on peut essayer de changer la propriété `nom` du membre et la faire passer de -<pre class="brush: js">nom: ['Jean', 'Martin'],</pre> +```js +nom: ['Jean', 'Martin'], +``` -<p>à</p> +à -<pre class="brush: js">nom : { +```js +nom : { prenom: 'Jean', nomFamille: 'Martin' -},</pre> +}, +``` -<p>Ici, nous avons bien créé un <strong>sous-espace de noms</strong>. Ça a l'air compliqué, mais ça ne l'est pas. Pour accéder à ces élements, il suffit de chaîner une étape de plus avec un autre point. Essayez ceci :</p> +Ici, nous avons bien créé un **sous-espace de noms**. Ça a l'air compliqué, mais ça ne l'est pas. Pour accéder à ces élements, il suffit de chaîner une étape de plus avec un autre point. Essayez ceci : -<pre class="brush: js">personne.nom.prenom -personne.nom.nomFamille</pre> +```js +personne.nom.prenom +personne.nom.nomFamille +``` -<p><strong>Important </strong>: à partir de maintenant, vous allez aussi devoir reprendre votre code et modifier toutes les occurrences de :</p> +**Important** : à partir de maintenant, vous allez aussi devoir reprendre votre code et modifier toutes les occurrences de : -<pre class="brush: js">nom[0] -nom[1]</pre> +```js +nom[0] +nom[1] +``` -<p>en</p> +en -<pre class="brush: js">nom.prenom -nom.nomFamille</pre> +```js +nom.prenom +nom.nomFamille +``` -<p>sinon vos méthodes ne fonctionneront plus.</p> +sinon vos méthodes ne fonctionneront plus. -<h2 id="Notation_avec_les_crochets">Notation avec les crochets</h2> +## Notation avec les crochets -<p>Il y a une autre façon d'accéder aux membres de l'objet : la notation avec les crochets. Plutôt que d'utiliser ceci :</p> +Il y a une autre façon d'accéder aux membres de l'objet : la notation avec les crochets. Plutôt que d'utiliser ceci : -<pre class="brush: js">personne.age -personne.nom.prenom</pre> +```js +personne.age +personne.nom.prenom +``` -<p>Vous pouvez utiliser :</p> +Vous pouvez utiliser : -<pre class="brush: js">personne['age'] -personne['nom']['prenom']</pre> +```js +personne['age'] +personne['nom']['prenom'] +``` -<p>Cela ressemble beaucoup à la façon d'accéder aux éléments d'un tableau et c'est bien la même chose — au lieu d'utiliser un indice numérique pour sélectionner un élément, on utilise le nom associé à chaque valeur d'un membre. Ce n'est pas pour rien que les objets sont parfois appelés tableaux associatifs : ils associent des chaînes de caractères (les noms des membres) à des valeurs, de la même façon que les tableaux associent des nombres à des valeurs.</p> +Cela ressemble beaucoup à la façon d'accéder aux éléments d'un tableau et c'est bien la même chose — au lieu d'utiliser un indice numérique pour sélectionner un élément, on utilise le nom associé à chaque valeur d'un membre. Ce n'est pas pour rien que les objets sont parfois appelés tableaux associatifs : ils associent des chaînes de caractères (les noms des membres) à des valeurs, de la même façon que les tableaux associent des nombres à des valeurs. -<h2 id="Définir_les_membres_dun_objet">Définir les membres d'un objet</h2> +## Définir les membres d'un objet -<p>Jusqu'ici, nous avons vu comment <strong>accéder</strong> aux membres d'un objet. Vous pouvez aussi <strong>modifier</strong> la valeur d'un membre de l'objet en déclarant simplement le membre que vous souhaitez modifier(en utilisant la notation avec le point ou par crochet), comme ceci :</p> +Jusqu'ici, nous avons vu comment **accéder** aux membres d'un objet. Vous pouvez aussi **modifier** la valeur d'un membre de l'objet en déclarant simplement le membre que vous souhaitez modifier(en utilisant la notation avec le point ou par crochet), comme ceci : -<pre class="brush: js">personne.age = 45 -personne['nom']['nomFamille'] = 'Rabuchon'</pre> +```js +personne.age = 45 +personne['nom']['nomFamille'] = 'Rabuchon' +``` -<p>Essayez de saisir ces deux lignes précédentes, puis accédez à nouveau aux membres pour voir ce qui a changé :</p> +Essayez de saisir ces deux lignes précédentes, puis accédez à nouveau aux membres pour voir ce qui a changé : -<pre class="brush: js">personne.age -personne['nom']['nomFamille']</pre> +```js +personne.age +personne['nom']['nomFamille'] +``` -<p>Définir les membres ne s'arrête pas à mettre à jour la valeur de propriétés ou méthodes existantes; <strong>vous pouvez aussi créer de nouveaux membres</strong>. Essayez ceci :</p> +Définir les membres ne s'arrête pas à mettre à jour la valeur de propriétés ou méthodes existantes; **vous pouvez aussi créer de nouveaux membres**. Essayez ceci : -<pre class="brush: js">personne['yeux'] = 'noisette' -personne.auRevoir = function() { alert("Bye bye tout le monde !"); }</pre> +```js +personne['yeux'] = 'noisette' +personne.auRevoir = function() { alert("Bye bye tout le monde !"); } +``` -<p>Vous pouvez maintenant tester vos nouveaux membres :</p> +Vous pouvez maintenant tester vos nouveaux membres : -<pre class="brush: js">personne['yeux'] -personne.auRevoir()</pre> +```js +personne['yeux'] +personne.auRevoir() +``` -<p>Un des aspects pratiques de la notation par crochet est qu'elle peut être utilisée pour définir dynamiquement les valeurs des membres, mais aussi pour définir les noms. Imaginons que nous voulions que les utilisateurs puissent saisir des types de valeurs personnalisées pour les données des personnes, en entrant le nom du membre et sa valeur dans deux champs <code>input</code>. On pourrait avoir ses valeurs comme ceci :</p> +Un des aspects pratiques de la notation par crochet est qu'elle peut être utilisée pour définir dynamiquement les valeurs des membres, mais aussi pour définir les noms. Imaginons que nous voulions que les utilisateurs puissent saisir des types de valeurs personnalisées pour les données des personnes, en entrant le nom du membre et sa valeur dans deux champs `input`. On pourrait avoir ses valeurs comme ceci : -<pre class="brush: js">var monNomDeDonnee = nomInput.value -var maValeurDeDonnee = valeurNom.value</pre> +```js +var monNomDeDonnee = nomInput.value +var maValeurDeDonnee = valeurNom.value +``` -<p>On peut alors ajouter le nom et la valeur du nouveau membre de l'objet <code>personne</code> comme ceci :</p> +On peut alors ajouter le nom et la valeur du nouveau membre de l'objet `personne` comme ceci : -<pre class="brush: js">personne[monNomDeDonnee] = maValeurDeDonnee</pre> +```js +personne[monNomDeDonnee] = maValeurDeDonnee +``` -<p>Pour le tester, essayez d'ajouter les lignes ci-dessous dans votre code, juste après le crochet fermante de l'objet <code>personne</code> :</p> +Pour le tester, essayez d'ajouter les lignes ci-dessous dans votre code, juste après le crochet fermante de l'objet `personne` : -<pre class="brush: js">var monNomDeDonnee = 'hauteur' +```js +var monNomDeDonnee = 'hauteur' var maValeurDeDonnee = '1.75m' -personne[monNomDeDonnee] = maValeurDeDonnee</pre> +personne[monNomDeDonnee] = maValeurDeDonnee +``` -<p>Sauvegardez, rafraîchissez et entrez le texte suivant dans le champ de saisie (l'élément <code>input</code>) :</p> +Sauvegardez, rafraîchissez et entrez le texte suivant dans le champ de saisie (l'élément `input`) : -<pre class="brush: js">personne.hauteur</pre> +```js +personne.hauteur +``` -<p>Nous n'aurions pas pu construire ce membre avec la notation avec un point, car celle-ci n'accepte qu'un nom et pas une variable pointant vers un nom.</p> +Nous n'aurions pas pu construire ce membre avec la notation avec un point, car celle-ci n'accepte qu'un nom et pas une variable pointant vers un nom. -<h2 id="Quest-ce_que_«_this_»">Qu'est-ce que « <code>this</code> » ?</h2> +## Qu'est-ce que « `this` » ? -<p>Vous avez dû remarquer quelque chose d'un peu étrange dans vos méthodes. Celle-ci, par exemple :</p> +Vous avez dû remarquer quelque chose d'un peu étrange dans vos méthodes. Celle-ci, par exemple : -<pre class="brush: js">salutation: function() { +```js +salutation: function() { alert('Bonjour! Je suis ' + this.nom.prenom + '.'); -}</pre> +} +``` -<p>Vous vous demandez probablement ce que signifie « <code>this</code> ». Le mot-clé <code>this</code> se réfère à l'objet courant dans lequel le code est écrit — dans notre cas, <code>this</code> est l'équivalent de <code>personne</code>. Alors, pourquoi ne pas écrire <code>personne</code> à la place ? Comme vous le verrez dans l'article <a href="/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS">la programmation JavaScript orientée objet pour les débutants</a>, <code>this</code> est très utile — il permet de s'assurer que les bonnes valeurs sont utilisées quand le contexte d'un membre change (on peut par exemple avoir deux personnes, sous la forme de deux objets, avec des noms différents).</p> +Vous vous demandez probablement ce que signifie « `this` ». Le mot-clé `this` se réfère à l'objet courant dans lequel le code est écrit — dans notre cas, `this` est l'équivalent de `personne`. Alors, pourquoi ne pas écrire `personne` à la place ? Comme vous le verrez dans l'article [la programmation JavaScript orientée objet pour les débutants](/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS), `this` est très utile — il permet de s'assurer que les bonnes valeurs sont utilisées quand le contexte d'un membre change (on peut par exemple avoir deux personnes, sous la forme de deux objets, avec des noms différents). -<p>Essayons d'illustrer nos propos par une paire d'objet <code>personne</code> simplifiée :</p> +Essayons d'illustrer nos propos par une paire d'objet `personne` simplifiée : -<pre class="brush: js">var personne1 = { +```js +var personne1 = { nom: 'Christophe', salutation: function() { alert('Bonjour ! Je suis ' + this.nom + '.'); @@ -214,45 +265,50 @@ var personne2 = { salutation: function() { alert('Bonjour ! Je suis ' + this.nom + '.'); } -}</pre> +} +``` -<p>Dans ce cas, <code>personne1.salutation()</code> affichera "Bonjour ! Je suis Christophe.", tandis que <code>personne2.salutation()</code> affichera "Bonjour ! Je suis Bruno." alors que le code est le même dans les deux cas. Comme expliqué plus tôt, <code>this</code> est égal à l'objet dans lequel se situe le code. Ce n'est pas très utile quand on écrit des objets littéraux à la main, mais ça prend tout son sens quand on génère des objets dynamiques (avec des constructeurs par exemple).</p> +Dans ce cas, `personne1.salutation()` affichera "Bonjour ! Je suis Christophe.", tandis que `personne2.salutation()` affichera "Bonjour ! Je suis Bruno." alors que le code est le même dans les deux cas. Comme expliqué plus tôt, `this` est égal à l'objet dans lequel se situe le code. Ce n'est pas très utile quand on écrit des objets littéraux à la main, mais ça prend tout son sens quand on génère des objets dynamiques (avec des constructeurs par exemple). -<h2 id="Vous_utilisiez_des_objets_depuis_le_début_!">Vous utilisiez des objets depuis le début !</h2> +## Vous utilisiez des objets depuis le début ! -<p>Tout au long de ces exemples, vous vous êtes probablement dit que la notation avec un point vous était très familière. C'est parce que vous l'avez utilisée tout au long du cours ! À chaque fois que vous avez travaillé avec un exemple qui utilise une API ou un objet JavaScript natif, nous avons utilisé des objets. Ces fonctionnalités sont construites exactement comme les objets que nous avons manipulés ici, mais sont parfois plus complexes que dans nos exemples.</p> +Tout au long de ces exemples, vous vous êtes probablement dit que la notation avec un point vous était très familière. C'est parce que vous l'avez utilisée tout au long du cours ! À chaque fois que vous avez travaillé avec un exemple qui utilise une API ou un objet JavaScript natif, nous avons utilisé des objets. Ces fonctionnalités sont construites exactement comme les objets que nous avons manipulés ici, mais sont parfois plus complexes que dans nos exemples. -<p>Ainsi, quand vous utilisez une méthode comme :</p> +Ainsi, quand vous utilisez une méthode comme : -<pre class="brush: js">maChaineDeCaracteres.split(',');</pre> +```js +maChaineDeCaracteres.split(','); +``` -<p>Vous utilisez une méthode disponible dans une instance du type {{jsxref("String")}}. Dès que vous créez une chaîne de caractères dans votre code, cette chaîne est automatiquement créée comme une instance de <code>String</code> et possède donc plusieurs méthodes/propriétés communes.</p> +Vous utilisez une méthode disponible dans une instance du type {{jsxref("String")}}. Dès que vous créez une chaîne de caractères dans votre code, cette chaîne est automatiquement créée comme une instance de `String` et possède donc plusieurs méthodes/propriétés communes. -<p>Quand vous accédez au DOM (<em>Document Object Model</em> ou « modèle objet du document ») avec <code>document</code> et des lignes telles que :</p> +Quand vous accédez au DOM (_Document Object Model_ ou « modèle objet du document ») avec `document` et des lignes telles que : -<pre class="brush: js">var monDiv = document.createElement('div'); -var maVideo = document.querySelector('video');</pre> +```js +var monDiv = document.createElement('div'); +var maVideo = document.querySelector('video'); +``` -<p>Vous utilisez une méthode disponible dans l'instance de la classe {{domxref("Document")}}. Pour chaque page web chargée, une instance de <code>Document</code> est créée, appelée <code>document</code> et qui représente la structure entière de la page, son contenu et d'autres caractéristiques telles que son URL. Encore une fois, cela signifie qu'elle possède plusieurs méthodes/propriétés communes.</p> +Vous utilisez une méthode disponible dans l'instance de la classe {{domxref("Document")}}. Pour chaque page web chargée, une instance de `Document` est créée, appelée `document` et qui représente la structure entière de la page, son contenu et d'autres caractéristiques telles que son URL. Encore une fois, cela signifie qu'elle possède plusieurs méthodes/propriétés communes. -<p>C'est également vrai pour beaucoup d'autres objets/API natifs que vous avez utilisé — {{jsxref("Array")}}, {{jsxref("Math")}}, etc.</p> +C'est également vrai pour beaucoup d'autres objets/API natifs que vous avez utilisé — {{jsxref("Array")}}, {{jsxref("Math")}}, etc. -<p>On notera que les objets/API natifs ne créent pas toujours automatiquement des instances d'objet. Par exemple, <a href="/fr/docs/Web/API/Notifications_API">l'API Notifications</a> — qui permet aux navigateurs modernes de déclencher leurs propres notifications — vous demande d'instancier vous-même une nouvelle instance d'objet en utilisant le constructeur pour chaque notification que vous souhaitez lancer. Essayez d'entrer le code ci-dessous dans la console JavaScript :</p> +On notera que les objets/API natifs ne créent pas toujours automatiquement des instances d'objet. Par exemple, [l'API Notifications](/fr/docs/Web/API/Notifications_API) — qui permet aux navigateurs modernes de déclencher leurs propres notifications — vous demande d'instancier vous-même une nouvelle instance d'objet en utilisant le constructeur pour chaque notification que vous souhaitez lancer. Essayez d'entrer le code ci-dessous dans la console JavaScript : -<pre class="brush: js">var maNotification = new Notification('Bonjour !');</pre> +```js +var maNotification = new Notification('Bonjour !'); +``` -<p>Nous verrons les constructeurs dans un prochain article.</p> +Nous verrons les constructeurs dans un prochain article. -<div class="note"> -<p><strong>Note :</strong> On peut voir le mode de communication des objets comme un <strong>envoi de message</strong>. Quand un objet a besoin d'un autre pour faire une action, souvent il va envoyer un message à un autre objet via l'une de ses méthode et attendre une réponse, qui retournera une valeur.</p> -</div> +> **Note :** On peut voir le mode de communication des objets comme un **envoi de message**. Quand un objet a besoin d'un autre pour faire une action, souvent il va envoyer un message à un autre objet via l'une de ses méthode et attendre une réponse, qui retournera une valeur. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Félicitations, vous avez terminé notre premier article sur les objets JavaScript — vous devriez maintenant mieux comprendre comment on travaille avec des objets en JavaScript. Vous avez pu créer vos propres objets basiques. Vous devriez aussi voir que les objets sont très pratiques pour stocker des données et des fonctionnalités. Si on ne passe pas par un objet et qu'on a une variable différente pour chaque propriété et méthode de notre objet <code>personne</code>, cela sera inefficace et frustrant et vous prendrez le risque de créer des conflits avec d'autres variables et fonctions du même nom.</p> +Félicitations, vous avez terminé notre premier article sur les objets JavaScript — vous devriez maintenant mieux comprendre comment on travaille avec des objets en JavaScript. Vous avez pu créer vos propres objets basiques. Vous devriez aussi voir que les objets sont très pratiques pour stocker des données et des fonctionnalités. Si on ne passe pas par un objet et qu'on a une variable différente pour chaque propriété et méthode de notre objet `personne`, cela sera inefficace et frustrant et vous prendrez le risque de créer des conflits avec d'autres variables et fonctions du même nom. -<p>Les objets permettent de conserver les informations de façon sûre, enfermées dans leur propre « paquet », hors de danger.</p> +Les objets permettent de conserver les informations de façon sûre, enfermées dans leur propre « paquet », hors de danger. -<p>Dans le prochain article, nous commencerons à voir la théorie de la programmation orientée objet (POO) et comment utiliser ces techniques en JavaScript.</p> +Dans le prochain article, nous commencerons à voir la théorie de la programmation orientée objet (POO) et comment utiliser ces techniques en JavaScript. -<p>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</p> +{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}} diff --git a/files/fr/learn/javascript/objects/index.md b/files/fr/learn/javascript/objects/index.md index 5c7aed54cd..ae25197ce7 100644 --- a/files/fr/learn/javascript/objects/index.md +++ b/files/fr/learn/javascript/objects/index.md @@ -12,59 +12,39 @@ tags: - Tutoriel translation_of: Learn/JavaScript/Objects --- -<div> -<div>{{JsSidebar}}</div> +{{JsSidebar}}{{PreviousNext("Apprendre/JavaScript/Building_blocks", "Learn/JavaScript/Objects/Basics")}} -<div>{{PreviousNext("Apprendre/JavaScript/Building_blocks", "Learn/JavaScript/Objects/Basics")}}</div> -</div> +En JavaScript, la plupart des choses sont des objets, des éléments du cœur de JavaScript, comme les chaînes de caractères et les tableaux, aux interfaces de programmation (APIs) des navigateurs construites sur la base de JavaScript. Vous pouvez même créer vos propres objets pour encapsuler des fonctions liées et des variables au sein de paquets efficaces, et se comportant comme des conteneurs de données. Il est important de comprendre la nature orientée objet du JavaScript si vous souhaitez aller loin dans votre connaissance du langage, aussi, avons-nous fourni ce module afin de vous aider. Ici, nous enseignons la théorie de l’objet et sa syntaxe en détail, ensuite, ce sera à vous de voir comment vous souhaitez créer vos propres objets. -<p>En JavaScript, la plupart des choses sont des objets, des éléments du cœur de JavaScript, comme les chaînes de caractères et les tableaux, aux interfaces de programmation (APIs) des navigateurs construites sur la base de JavaScript. Vous pouvez même créer vos propres objets pour encapsuler des fonctions liées et des variables au sein de paquets efficaces, et se comportant comme des conteneurs de données. Il est important de comprendre la nature orientée objet du JavaScript si vous souhaitez aller loin dans votre connaissance du langage, aussi, avons-nous fourni ce module afin de vous aider. Ici, nous enseignons la théorie de l’objet et sa syntaxe en détail, ensuite, ce sera à vous de voir comment vous souhaitez créer vos propres objets. </p> +## Prérequis -<h2 id="Prérequis">Prérequis</h2> +Avant de commencer ce module, vous devriez avoir quelques familiarités avec le HTML et le CSS. Il serait raisonnable de travailler sur les modules [Introduction au HTML](/fr/Apprendre/HTML/Introduction_%C3%A0_HTML) et [Introduction au CSS](/fr/Apprendre/CSS/Introduction_%C3%A0_CSS) avant de commencer avec le JavaScript. -<p>Avant de commencer ce module, vous devriez avoir quelques familiarités avec le HTML et le CSS. Il serait raisonnable de travailler sur les modules <a href="/fr/Apprendre/HTML/Introduction_%C3%A0_HTML">Introduction au HTML</a> et <a href="/fr/Apprendre/CSS/Introduction_%C3%A0_CSS">Introduction au CSS</a> avant de commencer avec le JavaScript.</p> +Vous devriez également être familiarisé avec les bases du JavaScript avant de poursuivre en détails avec les objets JavaScript. Avant de commencer ce module, travaillez sur [Premiers pas avec JavaScript](/fr/docs/Learn/JavaScript/First_steps) et [Les blocs de construction en JavaScript](/fr/Apprendre/JavaScript/Building_blocks). -<p>Vous devriez également être familiarisé avec les bases du JavaScript avant de poursuivre en détails avec les objets JavaScript. Avant de commencer ce module, travaillez sur <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas avec JavaScript</a> et <a href="/fr/Apprendre/JavaScript/Building_blocks">Les blocs de construction en JavaScript</a>.</p> +> **Note :** Si vous travaillez sur un ordinateur, une tablette ou un autre appareil où vous n’avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer les (la plupart des) exemples de code grâce à un programme en ligne comme [JSBin](http://jsbin.com/) ou [Thimble](https://thimble.mozilla.org/). -<div class="note"> -<p><strong>Note :</strong> Si vous travaillez sur un ordinateur, une tablette ou un autre appareil où vous n’avez pas la possibilité de créer vos propres fichiers, vous pouvez essayer les (la plupart des) exemples de code grâce à un programme en ligne comme <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> -</div> +## Guides -<h2 id="Guides">Guides</h2> +- [Les bases de JavaScript orienté objet](/fr/docs/Learn/JavaScript/Objects/Basics) + - : Dans le premier article concernant les objets JavaScript, nous découvrirons la syntaxe fondamentale d’un objet JavaScript, et nous revisiterons certaines fonctionnalités du JavaScript que nous avions vues précédemment dans le cours, en insistant sur le fait que bon nombre d'éléments précedemment abordés sont en fait des objets. -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases de JavaScript orienté objet</a></dt> - <dd>Dans le premier article concernant les objets JavaScript, nous découvrirons la syntaxe fondamentale d’un objet JavaScript, et nous revisiterons certaines fonctionnalités du JavaScript que nous avions vues précédemment dans le cours, en insistant sur le fait que bon nombre d'éléments précedemment abordés sont en fait des objets.</dd> -</dl> +<!----> -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/JS_orient%C3%A9-objet">JavaScript orienté objet pour les débutants</a></dt> - <dd> - <p>Après avoir vu les notions de base, nous nous pencherons sur le JavaScript orienté objet (JSOO) — cet article présente une vue basique de la théorie de la programmation orientée objet (POO), et explore ensuite comment le JavaScript émule les classes d’objet via les fonctions des constructeurs et comment créer des instances d’objet.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/Prototypes_Objet">Objets prototypes</a></dt> - <dd> - <p>Les prototypes sont des mécanismes par lesquels les objets JavaScript héritent les fonctionnalités d’un autre objet, et ils fonctionnent différemment des mécanismes d’héritage des langages classiques de programmation orientée objet. Dans cet article, nous explorons cette différence, expliquant comment les chaînes de prototypes fonctionnent et jetant un regard sur comment la propriété prototype peut être utilisée pour ajouter des méthodes aux constructeurs existants.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/Heritage">L’héritage au sein de JavaScript</a></dt> - <dd> - <p>Avec la plupart des redoutables détails du JSOO maintenant expliqués, cet article montre comment créer les classes (constructeurs) d’objet “enfant” qui héritent des fonctionnalités de leur classes “parents”. De plus, nous présentons certains conseils sur où et comment utiliser le JSOO.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/JSON">Manipuler des données JSON</a></dt> - <dd> - <p>JavaScript Object Notation (JSON) est un format standard pour la représentation de données structurées comme les objets JavaScript, qui est communément utilisé pour représenter et transmettre les données sur les sites web (ex. : Envoyer certaines données du serveur au client, afin d’être affichées sur une page web). Vous le rencontrerez assez souvent. Aussi, dans cet article, nous vous donnons tout ce dont vous avez besoin pour travailler avec le format JSON utilisant le JavaScript, incluant l’accès aux éléments des données dans un objet JSON et l’écriture de votre propre JSON.</p> - </dd> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/Object_building_practice">Pratiques sur la construction d’objet</a></dt> - <dd> - <p>Dans l’article précédent nous avons fait le tour de l’essentiel de la théorie de l’objet JavaScript et les détails de sa syntaxe, vous donnant ainsi une solide base sur laquelle débuter. Dans cet article nous plongeons dans un exercice, vous donnant plus de pratique dans la construction d’objets JavaScript personnalisés, qui produisent quelque chose d’amusant et de plus coloré — quelques balles colorées et bondissantes.</p> - </dd> -</dl> +- [JavaScript orienté objet pour les débutants](/fr/docs/Learn/JavaScript/Objects/JS_orient%C3%A9-objet) + - : Après avoir vu les notions de base, nous nous pencherons sur le JavaScript orienté objet (JSOO) — cet article présente une vue basique de la théorie de la programmation orientée objet (POO), et explore ensuite comment le JavaScript émule les classes d’objet via les fonctions des constructeurs et comment créer des instances d’objet. +- [Objets prototypes](/fr/docs/Learn/JavaScript/Objects/Prototypes_Objet) + - : Les prototypes sont des mécanismes par lesquels les objets JavaScript héritent les fonctionnalités d’un autre objet, et ils fonctionnent différemment des mécanismes d’héritage des langages classiques de programmation orientée objet. Dans cet article, nous explorons cette différence, expliquant comment les chaînes de prototypes fonctionnent et jetant un regard sur comment la propriété prototype peut être utilisée pour ajouter des méthodes aux constructeurs existants. +- [L’héritage au sein de JavaScript](/fr/docs/Learn/JavaScript/Objects/Heritage) + - : Avec la plupart des redoutables détails du JSOO maintenant expliqués, cet article montre comment créer les classes (constructeurs) d’objet “enfant” qui héritent des fonctionnalités de leur classes “parents”. De plus, nous présentons certains conseils sur où et comment utiliser le JSOO. +- [Manipuler des données JSON](/fr/docs/Learn/JavaScript/Objects/JSON) + - : JavaScript Object Notation (JSON) est un format standard pour la représentation de données structurées comme les objets JavaScript, qui est communément utilisé pour représenter et transmettre les données sur les sites web (ex. : Envoyer certaines données du serveur au client, afin d’être affichées sur une page web). Vous le rencontrerez assez souvent. Aussi, dans cet article, nous vous donnons tout ce dont vous avez besoin pour travailler avec le format JSON utilisant le JavaScript, incluant l’accès aux éléments des données dans un objet JSON et l’écriture de votre propre JSON. +- [Pratiques sur la construction d’objet](/fr/docs/Learn/JavaScript/Objects/Object_building_practice) + - : Dans l’article précédent nous avons fait le tour de l’essentiel de la théorie de l’objet JavaScript et les détails de sa syntaxe, vous donnant ainsi une solide base sur laquelle débuter. Dans cet article nous plongeons dans un exercice, vous donnant plus de pratique dans la construction d’objets JavaScript personnalisés, qui produisent quelque chose d’amusant et de plus coloré — quelques balles colorées et bondissantes. -<h2 id="Auto-évaluation">Auto-évaluation</h2> +## Auto-évaluation -<dl> - <dt><a href="/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Ajoutez des fonctionnalités à notre démo des ballons bondissants</a></dt> - <dd>Dans cette évaluation, vous devrez utiliser la démo des balles bondissantes de l’article précédent comme un point de départ et y ajouter quelques nouvelles et intéressantes fonctionnalités.</dd> -</dl> +- [Ajoutez des fonctionnalités à notre démo des ballons bondissants](/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features) + - : Dans cette évaluation, vous devrez utiliser la démo des balles bondissantes de l’article précédent comme un point de départ et y ajouter quelques nouvelles et intéressantes fonctionnalités. -<p>{{PreviousNext("Apprendre/JavaScript/Building_blocks", "JavaScript/Guide")}} </p> +{{PreviousNext("Apprendre/JavaScript/Building_blocks", "JavaScript/Guide")}} diff --git a/files/fr/learn/javascript/objects/inheritance/index.md b/files/fr/learn/javascript/objects/inheritance/index.md index ededf06c2e..89668811fa 100644 --- a/files/fr/learn/javascript/objects/inheritance/index.md +++ b/files/fr/learn/javascript/objects/inheritance/index.md @@ -14,248 +14,245 @@ tags: translation_of: Learn/JavaScript/Objects/Inheritance original_slug: Learn/JavaScript/Objects/Heritage --- -<div> -<p>{{LearnSidebar}}</p> +{{LearnSidebar}} -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}} -<p>Les présentations ayant été faites pour les concepts du JavaScript orienté objet, cet article détaille comment il est possible de créer une classe fille qui hérite des propriétés de sa classe mère. Nous verrons ensuite quelques conseils quant à l'utilisation du JavaScript orienté objet.</p> +Les présentations ayant été faites pour les concepts du JavaScript orienté objet, cet article détaille comment il est possible de créer une classe fille qui hérite des propriétés de sa classe mère. Nous verrons ensuite quelques conseils quant à l'utilisation du JavaScript orienté objet. <table> - <tbody> - <tr> - <th scope="row">Pré-requis :</th> - <td>Une connaissance générale de l'informatique, des notions d'HTML et CSS, une connaissance des bases en JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction</a>) ainsi que des notions de JavaScript orienté objet (JSOO) (voir <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>).</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre comment implémenter l'héritage en JavaScript.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td> + Une connaissance générale de l'informatique, des notions d'HTML et CSS, + une connaissance des bases en JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et + <a href="/fr/docs/Learn/JavaScript/Building_blocks" + >Blocs de construction</a + >) ainsi que des notions de JavaScript orienté objet (JSOO) (voir + <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction" + >Introduction aux objets</a + >). + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td>Comprendre comment implémenter l'héritage en JavaScript.</td> + </tr> + </tbody> </table> -<h2 id="Héritage_prototypique">Héritage prototypique</h2> +## Héritage prototypique -<p>Nous avons déjà vu le concept d'héritage en action, nous avons vu comment la chaîne de prototypage fonctionnait, et comment les propriétés de cette chaîne sont lues de manière ascendante. En revanche,nous n'avons utilisé pratiquement que quelques fonctionnalités déjà intégrées dans le navigateur pour le faire. Comment créer un objet JavaScript qui hérite d'un autre objet ?</p> +Nous avons déjà vu le concept d'héritage en action, nous avons vu comment la chaîne de prototypage fonctionnait, et comment les propriétés de cette chaîne sont lues de manière ascendante. En revanche,nous n'avons utilisé pratiquement que quelques fonctionnalités déjà intégrées dans le navigateur pour le faire. Comment créer un objet JavaScript qui hérite d'un autre objet ? -<p>Certains pensent que JavaScript n'est pas un véritable langage orienté objet. Dans les langages orientés objets classiques, on définit des classes objet et on peut ensuite définir laquelle hérite d'une autre (voir <a href="http://www.tutorialspoint.com/cplusplus/cpp_inheritance.htm">C++ inheritance</a> en anglais pour des exemples simples). JavasScript utilise une approche différente : les objets héritant d'un autre n'ont pas de fonctionnalités copiées d'un autre objet, au lieu de ça, ils héritent des fonctionnalités via les liens de la chaîne de prototypage (on parle alors d'un <strong>héritage prototypique</strong>).</p> +Certains pensent que JavaScript n'est pas un véritable langage orienté objet. Dans les langages orientés objets classiques, on définit des classes objet et on peut ensuite définir laquelle hérite d'une autre (voir [C++ inheritance](http://www.tutorialspoint.com/cplusplus/cpp_inheritance.htm) en anglais pour des exemples simples). JavasScript utilise une approche différente : les objets héritant d'un autre n'ont pas de fonctionnalités copiées d'un autre objet, au lieu de ça, ils héritent des fonctionnalités via les liens de la chaîne de prototypage (on parle alors d'un **héritage prototypique**). -<p>Voyons comment cela se passe avec un exemple concret.</p> +Voyons comment cela se passe avec un exemple concret. -<h2 id="Pour_commencer">Pour commencer</h2> +## Pour commencer -<p>Tout d'abord, faites une copie du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> (voir la <a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">démo</a>). Vous y trouverez le constructeur <code>Personne()</code> que nous avons utilisé jusque là dans l'ensemble des modules, néanmoins il y a un léger changement : nous n'avons défini que les attributs au sein du constructeur.</p> +Tout d'abord, faites une copie du fichier [oojs-class-inheritance-start.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html) (voir la [démo](https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html)). Vous y trouverez le constructeur `Personne()` que nous avons utilisé jusque là dans l'ensemble des modules, néanmoins il y a un léger changement : nous n'avons défini que les attributs au sein du constructeur. -<pre>function Personne(prenom, nom, age, genre, interets) { - this.nom = { - prenom, - nom - }; - this.age = age; - this.genre = genre; - this.interets = interets; -};</pre> + function Personne(prenom, nom, age, genre, interets) { + this.nom = { + prenom, + nom + }; + this.age = age; + this.genre = genre; + this.interets = interets; + }; -<p>L'ensemble des méthodes est défini dans le prototype :</p> +L'ensemble des méthodes est défini dans le prototype : -<pre>Personne.prototype.saluer = function() { - alert('Salut! Je suis ' + this.nom.prenom + '.'); -};</pre> + Personne.prototype.saluer = function() { + alert('Salut! Je suis ' + this.nom.prenom + '.'); + }; -<p>Essayons de créer une classe <code>Professeur</code> similaire à celle que nous avons utilisée jusqu'ici dans les autres modules d'initiations à l'approche objet. Ainsi, cette classe hérite de <code>Personne</code> mais possède aussi :</p> +Essayons de créer une classe `Professeur` similaire à celle que nous avons utilisée jusqu'ici dans les autres modules d'initiations à l'approche objet. Ainsi, cette classe hérite de `Personne` mais possède aussi : -<ol> - <li>Un nouvel attribut <code>matière</code> — qui contiendra la matière que le professeur enseigne.</li> - <li>Une méthode <code>saluer</code> un peu plus élaborée, qui sera un peu plus formelle que la méthode de base, cela sera plus approprié, lorsque le professeur s'adrressera à des étudiants, par exemple.</li> -</ol> +1. Un nouvel attribut `matière` — qui contiendra la matière que le professeur enseigne. +2. Une méthode `saluer` un peu plus élaborée, qui sera un peu plus formelle que la méthode de base, cela sera plus approprié, lorsque le professeur s'adrressera à des étudiants, par exemple. -<h2 id="Définissons_le_constructeur_Professeur()">Définissons le constructeur Professeur()</h2> +## Définissons le constructeur Professeur() -<p>La première chose à faire est de créer le constructeur <code>Professeur()</code> via l'ajout du code suivant :</p> +La première chose à faire est de créer le constructeur `Professeur()` via l'ajout du code suivant : -<pre>function Professeur(prenom, nom, age, genre, interets, matiere) { - Personne.call(this, prenom, nom, age, genre, interets); + function Professeur(prenom, nom, age, genre, interets, matiere) { + Personne.call(this, prenom, nom, age, genre, interets); - this.matiere = matiere; -}</pre> + this.matiere = matiere; + } -<p>Cela ressemble beaucoup au constructeur <code>Personne</code> mais il y a quelque chose que nous n'avons pas encore vu : la fonction <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call()</a></code>. Cette fonction permet d'appeler une fonction définie ailleurs dans le contexte actuel. Le premier paramètre spécifie la valeur de <code>this</code> que l'on souhaite utiliser lors que l'on utilisera la fonction, les paramètres suivants seront les paramètres qui pourront être passés en arguments lorsqu'elle sera appelée.</p> +Cela ressemble beaucoup au constructeur `Personne` mais il y a quelque chose que nous n'avons pas encore vu : la fonction [`call()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Function/call). Cette fonction permet d'appeler une fonction définie ailleurs dans le contexte actuel. Le premier paramètre spécifie la valeur de `this` que l'on souhaite utiliser lors que l'on utilisera la fonction, les paramètres suivants seront les paramètres qui pourront être passés en arguments lorsqu'elle sera appelée. -<p>Nous voulons que le constructeur <code>Professeur()</code> aie les mêmes attributs que <code>Personne()</code>, nous les spécifions donc dans l'appel fait via la fonction <code>call()</code>.</p> +Nous voulons que le constructeur `Professeur()` aie les mêmes attributs que `Personne()`, nous les spécifions donc dans l'appel fait via la fonction `call()`. -<p>La dernière ligne au sein du constructeur sert simplement à définir l'attribut <code>matière</code> que les professeurs enseignent, ce qui n'est pas valable pour les personnes génériques.</p> +La dernière ligne au sein du constructeur sert simplement à définir l'attribut `matière` que les professeurs enseignent, ce qui n'est pas valable pour les personnes génériques. -<p>Notez que nous aurions très bien pu écrire tout simplement ceci :</p> +Notez que nous aurions très bien pu écrire tout simplement ceci : -<pre>function Professeur(prenom, nom, age, genre, interets, matiere) { - this.nom_complet = { - prenom, - nom - }; - this.age = age; - this.genre = genre; - this.interets = interets; - this.matiere = matiere; -}</pre> + function Professeur(prenom, nom, age, genre, interets, matiere) { + this.nom_complet = { + prenom, + nom + }; + this.age = age; + this.genre = genre; + this.interets = interets; + this.matiere = matiere; + } -<p>Cependant cela aurait eu pour effet de redéfinir les attributs à nouveau, sans les hériter de <code>Personne()</code>, ce qui n'est pas vraiment le but que nous voulons atteindre lorsque l'on parle de l'héritage, cela rajoute aussi des lignes de code inutiles.</p> +Cependant cela aurait eu pour effet de redéfinir les attributs à nouveau, sans les hériter de `Personne()`, ce qui n'est pas vraiment le but que nous voulons atteindre lorsque l'on parle de l'héritage, cela rajoute aussi des lignes de code inutiles. -<p> </p> -<h3 id="Hériter_d'un_constructeur_sans_paramètres">Hériter d'un constructeur sans paramètres</h3> -<p>Notez que si les valeurs des propriétés du constructeur dont vous héritez ne proviennent pas de paramètres, vous n'avez nullement besoin de les specifier comme arguments additionnels dans l'appel de la fonction <code>call()</code>. Donc, par exemple, si vous avez quelque chose d'aussi simple que ceci :</p> +### Hériter d'un constructeur sans paramètres -<pre class="brush: js">function Brick() { +Notez que si les valeurs des propriétés du constructeur dont vous héritez ne proviennent pas de paramètres, vous n'avez nullement besoin de les specifier comme arguments additionnels dans l'appel de la fonction `call()`. Donc, par exemple, si vous avez quelque chose d'aussi simple que ceci : + +```js +function Brick() { this.width = 10; this.height = 20; -}</pre> +} +``` -<p>Vous pouvez hériter des propriétés <code>width</code> et <code>height</code> en procédant comme ceci (Mais également en suivant bien sûr les différentes étapes décrites ci dessous) :</p> +Vous pouvez hériter des propriétés `width` et `height` en procédant comme ceci (Mais également en suivant bien sûr les différentes étapes décrites ci dessous) : -<pre class="brush: js">function BlueGlassBrick() { +```js +function BlueGlassBrick() { Brick.call(this); this.opacity = 0.5; this.color = 'blue'; -}</pre> +} +``` + +Notez que nous n'avons spécifié que `this` au sein de `call()` — Aucun autre paramètre n'est requis puisque nous n'héritons ici d'aucune propriété provenant de la classe parente qui soit spécifiée via paramètres. + +## Définir le prototype de Professeur() et son constructeur référent. -<p>Notez que nous n'avons spécifié que <code>this</code> au sein de <code>call()</code> — Aucun autre paramètre n'est requis puisque nous n'héritons ici d'aucune propriété provenant de la classe parente qui soit spécifiée via paramètres. </p> +Pour le moment tout va bien, mais nous avons un petit problème. Nous avons défini un nouveau constructeur et ce dernier possède une propriété `prototype`, qui par défaut ne contient qu'une référence à la fonction constructrice elle même. En revanche il ne contient pas les méthodes de la propriété `prototype` du constructeur `Personne()`. Pour le constater, vous pouvez par exemple entrer `Professeur.prototype.constructor` dans la console JavaScript pour voir ce qu'il en est. Le nouveau constructeur n'a en aucun cas hérité de ces méthodes. Pour le constater, comparez les sorties de `Personne.prototype.saluer` et de `Professeur.prototype.saluer` -<h2 id="Définir_le_prototype_de_Professeur()_et_son_constructeur_référent.">Définir le prototype de Professeur() et son constructeur référent.</h2> +Notre classe `Professeur()` doit hériter des méthodes définies dans le prototype de `Personne()`. Aussi comment procéder pour obtenir ce résultat ? -<p>Pour le moment tout va bien, mais nous avons un petit problème. Nous avons défini un nouveau constructeur et ce dernier possède une propriété <code>prototype</code>, qui par défaut ne contient qu'une référence à la fonction constructrice elle même. En revanche il ne contient pas les méthodes de la propriété <code>prototype</code> du constructeur <code>Personne()</code>. Pour le constater, vous pouvez par exemple entrer <code>Professeur.prototype.constructor</code> dans la console JavaScript pour voir ce qu'il en est. Le nouveau constructeur n'a en aucun cas hérité de ces méthodes. Pour le constater, comparez les sorties de <code>Personne.prototype.saluer</code> et de <code>Professeur.prototype.saluer</code></p> +Ajoutez la ligne suivante à la suite du bloc de code que nous venons d'ajouter : -<p>Notre classe <code>Professeur()</code> doit hériter des méthodes définies dans le prototype de <code>Personne()</code>. Aussi comment procéder pour obtenir ce résultat ?</p> + Professeur.prototype = Object.create(Personne.prototype); -<p>Ajoutez la ligne suivante à la suite du bloc de code que nous venons d'ajouter :</p> +1. Ici, notre ami [`create()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create) vient nous aider à nouveau. Dans ce cas, on l'utilise afin de créer un nouvel objet que nous assignons à `Professeur.prototype`. Le nouvel objet possède `Personne.prototype` désormais comme son prototype et héritera ainsi, si et quand le besoin se fera sentir, de toutes les méthodes disponible sur `Personne.prototype`. +2. Nous avons également besoin de faire encore une chose avant de continuer. Après avoir ajouté la ligne précédente, le constructeur du prototype de `Professeur()` est désormais équivalent à celui de `Personne()`, parce que nous avons défini `Professeur.prototype` pour référencer un objet qui hérite ses propriétés de `Personne.prototype` ! Essayez, après avoir sauvegardé votre code et rechargé la page, d'entrer `Professeur.prototype.constructor` dans la console pour vérifier. +3. Cela peut devenir problématique, autant le corriger dès maintenant. C'est possible via l'ajout de la ligne de code suivante à la fin : -<pre>Professeur.prototype = Object.create(Personne.prototype);</pre> + Professeur.prototype.constructor = Professeur; -<ol> - <li>Ici, notre ami <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> vient nous aider à nouveau. Dans ce cas, on l'utilise afin de créer un nouvel objet que nous assignons à <code>Professeur.prototype</code>. Le nouvel objet possède <code>Personne.prototype</code> désormais comme son prototype et héritera ainsi, si et quand le besoin se fera sentir, de toutes les méthodes disponible sur <code>Personne.prototype</code>. </li> - <li>Nous avons également besoin de faire encore une chose avant de continuer. Après avoir ajouté la ligne précédente, le constructeur du prototype de <code>Professeur()</code> est désormais équivalent à celui de <code>Personne()</code>, parce que nous avons défini <code>Professeur.prototype</code> pour référencer un objet qui hérite ses propriétés de <code>Personne.prototype</code> ! Essayez, après avoir sauvegardé votre code et rechargé la page, d'entrer <code>Professeur.prototype.constructor</code> dans la console pour vérifier.</li> - <li>Cela peut devenir problématique, autant le corriger dès maintenant. C'est possible via l'ajout de la ligne de code suivante à la fin : - <pre>Professeur.prototype.constructor = Professeur;</pre> - </li> - <li> - <p>A présent, si vous sauvegardez et rafraichissez après avoir écrit <code>Professeur.prototype.constructor</code>, cela devrait retourner <code>Professeur()</code>, et en plus nous héritons maintenant de <code>Personne()</code> !</p> - </li> -</ol> +4. A présent, si vous sauvegardez et rafraichissez après avoir écrit `Professeur.prototype.constructor`, cela devrait retourner `Professeur()`, et en plus nous héritons maintenant de `Personne()` ! -<h2 id="Donner_au_prototype_de_Professeur()_une_nouvelle_fonction_saluer()">Donner au prototype de Professeur() une nouvelle fonction saluer()</h2> +## Donner au prototype de Professeur() une nouvelle fonction saluer() -<p>Pour terminer notre code, nous devons définir une nouvelle fonction <code>saluer()</code> sur le constructeur de <code>Professeur()</code>.</p> +Pour terminer notre code, nous devons définir une nouvelle fonction `saluer()` sur le constructeur de `Professeur()`. -<p>La façon la plus facile d'accomplir cela est de la définir sur le prototype de Professeur() — ajoutez ceci à la suite de votre code :</p> +La façon la plus facile d'accomplir cela est de la définir sur le prototype de Professeur() — ajoutez ceci à la suite de votre code : -<pre>Professeur.prototype.saluer = function() { - var prefix; + Professeur.prototype.saluer = function() { + var prefix; - if (this.genre === 'mâle' || this.genre === 'Mâle' || this.genre === 'm' || this.genre === 'M') { - prefix = 'M.'; - } else if (this.genre === 'femelle' || this.genre === 'Femelle' || this.genre === 'f' || this.genre === 'F') { - prefix = 'Mme'; - } else { - prefix = ''; - } + if (this.genre === 'mâle' || this.genre === 'Mâle' || this.genre === 'm' || this.genre === 'M') { + prefix = 'M.'; + } else if (this.genre === 'femelle' || this.genre === 'Femelle' || this.genre === 'f' || this.genre === 'F') { + prefix = 'Mme'; + } else { + prefix = ''; + } - alert('Bonjour. Mon nom est ' + prefix + ' ' + this.nom_complet.nom + ', et j\'enseigne ' + this.matiere + '.'); -};</pre> + alert('Bonjour. Mon nom est ' + prefix + ' ' + this.nom_complet.nom + ', et j\'enseigne ' + this.matiere + '.'); + }; -<p>Ceci affiche la salutation du professeur, qui utilise le titre de civilité approprié à son genre, au moyen d'une instruction conditionnelle.</p> +Ceci affiche la salutation du professeur, qui utilise le titre de civilité approprié à son genre, au moyen d'une instruction conditionnelle. -<p> </p> -<h2 id="Exécuter_l'exemple">Exécuter l'exemple</h2> -<p>Une fois tout le code saisi, essayez de créer une instance d'objet <code>Professeur()</code> en ajoutant à la fin de votre JavaScript (ou à l'endroit de votre choix) :</p> +## Exécuter l'exemple -<pre>var professeur1 = new Professeur('Cédric', 'Villani', 44, 'm', ['football', 'cuisine'], 'les mathématiques');</pre> +Une fois tout le code saisi, essayez de créer une instance d'objet `Professeur()` en ajoutant à la fin de votre JavaScript (ou à l'endroit de votre choix) : -<p>Sauvegardez et actualisez, et essayez d'accéder aux propriétés et méthodes de votre nouvel objet <code>professeur1</code>, par exemple :</p> + var professeur1 = new Professeur('Cédric', 'Villani', 44, 'm', ['football', 'cuisine'], 'les mathématiques'); -<pre>professeur1.nom_complet.nom; -professeur1.interets[0]; -professeur1.bio(); -professeur1.matiere; -professeur1.saluer();Ffa</pre> +Sauvegardez et actualisez, et essayez d'accéder aux propriétés et méthodes de votre nouvel objet `professeur1`, par exemple : -<p>Tout cela devrait parfaitement fonctionner. Les instructions des lignes 1,2,3 et 6 accèdent à des membres hérités de la classe générique <code>Personne()</code> via son constructeur, tandis que la ligne 4 accède de façon plus spécifique à un membre qui n'est disponible que via le constructeur de la classe spécialisée <code>Professeur()</code>.</p> + professeur1.nom_complet.nom; + professeur1.interets[0]; + professeur1.bio(); + professeur1.matiere; + professeur1.saluer();Ffa -<p><strong>Note</strong>: Si vous rencontrez un problème afin de faire fonctionner ce code comparez le à notre <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">version finalisée</a> (Ou regarder tourner <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">notre demo en ligne</a>).</p> +Tout cela devrait parfaitement fonctionner. Les instructions des lignes 1,2,3 et 6 accèdent à des membres hérités de la classe générique `Personne()` via son constructeur, tandis que la ligne 4 accède de façon plus spécifique à un membre qui n'est disponible que via le constructeur de la classe spécialisée `Professeur()`. -<p>La méthode que nous avons détaillée ici n'est pas la seule permettant de mettre en place l'héritage de classes en JavaScript, mais elle fonctionne parfaitement et elle vous permet d'avoir une bonne idée de comment implémenter l'héritage en JavaScript.</p> +**Note**: Si vous rencontrez un problème afin de faire fonctionner ce code comparez le à notre [version finalisée](http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html) (Ou regarder tourner [notre demo en ligne](http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html)). -<p>Vous pourriez également être intéressé par certaines des nouvelles fonctionnalités de {{glossary("ECMAScript")}} qui nous permettent de mettre en place l'héritage d'une façon beaucoup plus élégante en JavaScript (Voir <a href="/fr/docs/Web/JavaScript/Reference/Classes">Classes</a>). Nous ne les avons pas développées ici parce qu'elles ne sont actuellement pas supportées par tous les navigateurs. Toutes les autres constructions dont nous avons discuté dans cette série d'articles sont supportées par IE9 et les versions moins récentes et il existe des méthodes qui prennent plus en charge les navigateurs moins récents.</p> +La méthode que nous avons détaillée ici n'est pas la seule permettant de mettre en place l'héritage de classes en JavaScript, mais elle fonctionne parfaitement et elle vous permet d'avoir une bonne idée de comment implémenter l'héritage en JavaScript. -<p>Un moyen habituel est d'utiliser les librairies JavaScript — La plupart des options populaires ont une sélection de fonctionnalités disponibles pour réaliser l'héritage plus facilement et plus rapidement.</p> +Vous pourriez également être intéressé par certaines des nouvelles fonctionnalités de {{glossary("ECMAScript")}} qui nous permettent de mettre en place l'héritage d'une façon beaucoup plus élégante en JavaScript (Voir [Classes](/fr/docs/Web/JavaScript/Reference/Classes)). Nous ne les avons pas développées ici parce qu'elles ne sont actuellement pas supportées par tous les navigateurs. Toutes les autres constructions dont nous avons discuté dans cette série d'articles sont supportées par IE9 et les versions moins récentes et il existe des méthodes qui prennent plus en charge les navigateurs moins récents. -<p><a href="http://coffeescript.org/#classes">CoffeeScript</a> par exemple fournit les fonctionnalités <code>class</code>, <code>extends</code>, etc.</p> +Un moyen habituel est d'utiliser les librairies JavaScript — La plupart des options populaires ont une sélection de fonctionnalités disponibles pour réaliser l'héritage plus facilement et plus rapidement. -<h2 id="Un_exercice_plus_complexe.">Un exercice plus complexe.</h2> +[CoffeeScript](http://coffeescript.org/#classes) par exemple fournit les fonctionnalités `class`, `extends`, etc. -<p>Dans notre <a href="/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">section sur la programmation orientée objet</a> nous avons également inclus une classe <code>Etudiant</code> comme un concept qui hérite de toutes les fonctionnalités de la classe <code>Personne</code>, et qui a également une méthode <code>saluer()</code> differente de celle de <code>Personne</code> qui est beaucoup moins formelle que la méthode <code>saluer()</code> de <code>Professeur()</code>. Jetez un oeil à ce à quoi ressemble la méthode <code>saluer()</code> de la classe <code>Etudiant</code> dans cette section et essayez d'implémenter votre propre constructeur <code>Etudiant()</code> qui hérite de toutes les fonctionnalités de <code>Personne()</code> et la fonction <code>saluer()</code> différente.</p> +## Un exercice plus complexe. -<p><strong>Note</strong>: Si vous rencontrez un problème afin de faire fonctionner ce code comparez le à notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html">version finalisée</a> (Ou regarder tourner <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">notre demo en ligne</a>).</p> +Dans notre [section sur la programmation orientée objet](/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters) nous avons également inclus une classe `Etudiant` comme un concept qui hérite de toutes les fonctionnalités de la classe `Personne`, et qui a également une méthode `saluer()` differente de celle de `Personne` qui est beaucoup moins formelle que la méthode `saluer()` de `Professeur()`. Jetez un oeil à ce à quoi ressemble la méthode `saluer()` de la classe `Etudiant` dans cette section et essayez d'implémenter votre propre constructeur `Etudiant()` qui hérite de toutes les fonctionnalités de `Personne()` et la fonction `saluer()` différente. -<h2 id="Résumé_sur_les_membres_de_l'Objet">Résumé sur les membres de l'Objet</h2> +**Note**: Si vous rencontrez un problème afin de faire fonctionner ce code comparez le à notre [version finalisée](https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html) (Ou regarder tourner [notre demo en ligne](http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html)). -<p>Pour résumer, vous avez de façon basique trois types de propriétés/méthodes à prendre en compte :</p> +## Résumé sur les membres de l'Objet -<ol> - <li>Celles définies au sein d'un constructeur et passées en paramètres aux instances de l'objet. Celles là ne sont pas difficiles à repérer — Dans votre propre code personnalisé, elles sont les membres définis en utilisant les lignes comme <code>this.x = x</code> ; Dans les codes préconstruits propres aux navigateurs, ils sont les membres seulement accessibles aux instances d'objet (usuellement créés en appelant un constructeur via l'utilisation du mot clé <code>new</code>, exemple : <code>var myInstance = new myConstructor()</code>).</li> - <li>Celles définies directement sur les constructeurs eux mêmes et accessibles uniquement sur les constructeurs. Celles là sont communément présentes uniquement dans les objets préconstruits des navigateurs et sont reconnus par le fait d'être directement chaînées sur un constructeur et non sur une instance. Par exemple, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>.</li> - <li>Celles définies sur un prototype de constructeur qui sont héritées par toutes les instances des classes d'objet. Celles là incluent n'importe quel membre défini sur un prototype de constructeur, exemple : <code>myConstructor.prototype.x()</code>.</li> -</ol> +Pour résumer, vous avez de façon basique trois types de propriétés/méthodes à prendre en compte : -<p>Si vous êtes encore dans la confusion par rapport aux différents types ne vous inquiétez pas c'est normal — vous êtes encore entrain d'apprendre et la familiarité apparaîtra avec la pratique.</p> +1. Celles définies au sein d'un constructeur et passées en paramètres aux instances de l'objet. Celles là ne sont pas difficiles à repérer — Dans votre propre code personnalisé, elles sont les membres définis en utilisant les lignes comme `this.x = x` ; Dans les codes préconstruits propres aux navigateurs, ils sont les membres seulement accessibles aux instances d'objet (usuellement créés en appelant un constructeur via l'utilisation du mot clé `new`, exemple : `var myInstance = new myConstructor()`). +2. Celles définies directement sur les constructeurs eux mêmes et accessibles uniquement sur les constructeurs. Celles là sont communément présentes uniquement dans les objets préconstruits des navigateurs et sont reconnus par le fait d'être directement chaînées sur un constructeur et non sur une instance. Par exemple, [`Object.keys()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/keys). +3. Celles définies sur un prototype de constructeur qui sont héritées par toutes les instances des classes d'objet. Celles là incluent n'importe quel membre défini sur un prototype de constructeur, exemple : `myConstructor.prototype.x()`. -<h2 id="Quand_devez-vous_utiliser_l'héritage_en_JavaScript">Quand devez-vous utiliser l'héritage en JavaScript?</h2> +Si vous êtes encore dans la confusion par rapport aux différents types ne vous inquiétez pas c'est normal — vous êtes encore entrain d'apprendre et la familiarité apparaîtra avec la pratique. -<p>Particulièrement après ce dernier article, vous pourriez penser "woa c'est compliqué". Bien, vous avez vu juste, prototypes et héritages représentent une partie des aspects les plus complexes de JavaScript, mais une bonne partie de la puissance et de la flexibilité de JavaScript vient de sa structure Objet et de l'héritage et il est vraiment très important de comprendre comment cela fonctionne. </p> +## Quand devez-vous utiliser l'héritage en JavaScript? -<p>D'une certaine manière, vous utilisez l'héritage à plein temps — Que vous utilisiez différentes fonctionnalités d'une WebAPI , ou une méthode/propriété définie par défaut sur un objet prédéfini du navigateur que vous invoquez sur vos chaînes de caractères, tableaux etc., vous utilisez de façon implicite l'héritage. </p> +Particulièrement après ce dernier article, vous pourriez penser "woa c'est compliqué". Bien, vous avez vu juste, prototypes et héritages représentent une partie des aspects les plus complexes de JavaScript, mais une bonne partie de la puissance et de la flexibilité de JavaScript vient de sa structure Objet et de l'héritage et il est vraiment très important de comprendre comment cela fonctionne. -<p>En termes d'utilisation de l'héritage dans votre propre code, vous ne l'utiliserez probablement pas si souvent et spécialement pour débuter avec, et dans les petits projets — C'est une perte de temps d'utiliser les objets et l'héritage par amour pour cette pratique quand vous n'en avez pas besoin. Mais à mesure que les bases de votre code s'élargissent vous trouverez cette façon de faire probablement très utile. Si vous trouvez utile et plus pratique de commencer en créant un certain nombre d'objets spécialisés partageant les mêmes fonctionnalités, alors créer un objet générique qui contiendra toutes les fonctionnalités communes dont les objets spécialisés hériteront vous apparaîtra être une pratique peut être plus confortable et efficace par la suite. </p> +D'une certaine manière, vous utilisez l'héritage à plein temps — Que vous utilisiez différentes fonctionnalités d'une WebAPI , ou une méthode/propriété définie par défaut sur un objet prédéfini du navigateur que vous invoquez sur vos chaînes de caractères, tableaux etc., vous utilisez de façon implicite l'héritage. -<p><strong>Note</strong>: A cause de la manière dont JavaScript fonctionne, avec la chaîne de prototype, etc., le partage de fonctionnalités entre objet est souvent appelée <strong>délégation</strong> — Les objets spécialisés délèguent cette fonctionnalité à l'objet de type générique. C'est certainement beaucoup plus précis que de l'appeler héritage, puisque la fonctionnalité "héritée" n'est pas copiée dans les objets qui "héritent". Au contraire, elle demeure dans l'objet générique.</p> +En termes d'utilisation de l'héritage dans votre propre code, vous ne l'utiliserez probablement pas si souvent et spécialement pour débuter avec, et dans les petits projets — C'est une perte de temps d'utiliser les objets et l'héritage par amour pour cette pratique quand vous n'en avez pas besoin. Mais à mesure que les bases de votre code s'élargissent vous trouverez cette façon de faire probablement très utile. Si vous trouvez utile et plus pratique de commencer en créant un certain nombre d'objets spécialisés partageant les mêmes fonctionnalités, alors créer un objet générique qui contiendra toutes les fonctionnalités communes dont les objets spécialisés hériteront vous apparaîtra être une pratique peut être plus confortable et efficace par la suite. -<p>Lorsque vous utilisez l'héritage, il est conseillé de ne pas avoir trop de degrés d'héritage et de toujours garder minutieusement trace de l'endroit où vous définissez vos propriétés et méthodes. Il est possible de commencer à écrire un code qui modifie temporairement les prototypes des objets prédéfinis du navigateur mais vous ne devriez pas le faire à moins que n'ayiez une très bonne raison. Trop de degrés d'héritages peut conduire à une confusion sans fin et une peine sans fin quand vous essayez de déboguer un tel code. </p> +**Note**: A cause de la manière dont JavaScript fonctionne, avec la chaîne de prototype, etc., le partage de fonctionnalités entre objet est souvent appelée **délégation** — Les objets spécialisés délèguent cette fonctionnalité à l'objet de type générique. C'est certainement beaucoup plus précis que de l'appeler héritage, puisque la fonctionnalité "héritée" n'est pas copiée dans les objets qui "héritent". Au contraire, elle demeure dans l'objet générique. -<p>En définitive, les objets sont juste une autre forme de réutilisation de code comme les fonctions et les boucles avec leurs propres rôles et avantages. Si vous trouvez utile de créer un lot de variables et fonctions relatives et que vous voulez les retracer ensemble et les empaqueter de façon ordonnée, un objet est une bonne idée. Les objets sont également très utiles quand vous souhaitez passer une collection de données d'un endroit à un autre. Toutes ces choses peuvent être accomplies sans l'utilisation d'un constructeur ou de l'héritage. Si vous n'avez besoin que d'une seule instance, l'utilisation d'un simple objet littéral serait certainement un choix beaucoup plus judicieux et vous n'avez certainement pas besoin de l'héritage.</p> +Lorsque vous utilisez l'héritage, il est conseillé de ne pas avoir trop de degrés d'héritage et de toujours garder minutieusement trace de l'endroit où vous définissez vos propriétés et méthodes. Il est possible de commencer à écrire un code qui modifie temporairement les prototypes des objets prédéfinis du navigateur mais vous ne devriez pas le faire à moins que n'ayiez une très bonne raison. Trop de degrés d'héritages peut conduire à une confusion sans fin et une peine sans fin quand vous essayez de déboguer un tel code. -<h2 id="Résumé">Résumé</h2> +En définitive, les objets sont juste une autre forme de réutilisation de code comme les fonctions et les boucles avec leurs propres rôles et avantages. Si vous trouvez utile de créer un lot de variables et fonctions relatives et que vous voulez les retracer ensemble et les empaqueter de façon ordonnée, un objet est une bonne idée. Les objets sont également très utiles quand vous souhaitez passer une collection de données d'un endroit à un autre. Toutes ces choses peuvent être accomplies sans l'utilisation d'un constructeur ou de l'héritage. Si vous n'avez besoin que d'une seule instance, l'utilisation d'un simple objet littéral serait certainement un choix beaucoup plus judicieux et vous n'avez certainement pas besoin de l'héritage. -<p>Cet article a couvert le reste du coeur de la théorie du JSOO et des syntaxes que nous pensons que vous devriez connaître maintenant. A cet stade vous devriez comprendre l'objet JavaScript et les bases de la POO, les prototypes et l'héritage par prototype, comment créer les classes (constructeurs) et les instances d'objet, ajouter des fonctionnalités aux classes, et créer des sous classes qui héritent d'autres classes. </p> +## Résumé -<p>Dans le prochain article, nous jetterons un regard sur comment travailler avec le (JSON), un format commun d'échange de données écrit en utilisant les objets JavaScript.</p> +Cet article a couvert le reste du coeur de la théorie du JSOO et des syntaxes que nous pensons que vous devriez connaître maintenant. A cet stade vous devriez comprendre l'objet JavaScript et les bases de la POO, les prototypes et l'héritage par prototype, comment créer les classes (constructeurs) et les instances d'objet, ajouter des fonctionnalités aux classes, et créer des sous classes qui héritent d'autres classes. -<h2 id="Voir_aussi">Voir aussi</h2> +Dans le prochain article, nous jetterons un regard sur comment travailler avec le (JSON), un format commun d'échange de données écrit en utilisant les objets JavaScript. -<ul> - <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — Un site interactif d'appentissage très utile pour en savoir plus sur les Objets.</li> - <li><a href="https://www.amazon.com/gp/product/193398869X/">Secrets of the JavaScript Ninja</a>, Chapitre 6 — Un bon livre sur les concepts et techniques avancées du JavaScript par John Resig et Bear Bibeault. Le chapitre 6 couvre très bien les divers aspects des prototypes et de l'héritage ; vous trouverez sûrement facilement une version imprimée ou une version en ligne.</li> - <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes">You Don't Know JS: this & Object Prototypes</a> — Une partie de l'excellente série de manuels sur le JavaScript de Kyle Simpson. Le chapitre 5 en particulier jette un regard beaucoup plus approfondi sur les prototypes que nous ne l'avons fait ici. Nous avons présenté ici une vue simplifiée dans cette série d'articles dédiée aux débutants tandis que Kyle est allé dans les détails les plus profonds et fournit une image beaucoup plus complexe et plus précise.</li> -</ul> +## Voir aussi -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> +- [ObjectPlayground.com](http://www.objectplayground.com/) — Un site interactif d'appentissage très utile pour en savoir plus sur les Objets. +- [Secrets of the JavaScript Ninja](https://www.amazon.com/gp/product/193398869X/), Chapitre 6 — Un bon livre sur les concepts et techniques avancées du JavaScript par John Resig et Bear Bibeault. Le chapitre 6 couvre très bien les divers aspects des prototypes et de l'héritage ; vous trouverez sûrement facilement une version imprimée ou une version en ligne. +- [You Don't Know JS: this & Object Prototypes](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes) — Une partie de l'excellente série de manuels sur le JavaScript de Kyle Simpson. Le chapitre 5 en particulier jette un regard beaucoup plus approfondi sur les prototypes que nous ne l'avons fait ici. Nous avons présenté ici une vue simplifiée dans cette série d'articles dédiée aux débutants tandis que Kyle est allé dans les détails les plus profonds et fournit une image beaucoup plus complexe et plus précise. -<p> </p> +{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}} -<h2 id="Dans_ce_module">Dans ce module</h2> -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases de l'Objet</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript Orienté Objet pour débutants</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object_prototypes">Prototypes d'Objet</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Inheritance">L'héritage en JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/JSON">Travailler avec les données JSON</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object_building_practice">Construire les Objets dans la pratique</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Ajouter des fonctionnalités à la démo de nos balles bondissantes</a></li> -</ul> -<p> </p> -</div> +## Dans ce module -<p> </p> +- [Les bases de l'Objet](/fr/docs/Learn/JavaScript/Objects/Basics) +- [JavaScript Orienté Objet pour débutants](/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS) +- [Prototypes d'Objet](/fr/docs/Learn/JavaScript/Objects/Object_prototypes) +- [L'héritage en JavaScript](/fr/docs/Learn/JavaScript/Objects/Inheritance) +- [Travailler avec les données JSON](/fr/docs/Learn/JavaScript/Objects/JSON) +- [Construire les Objets dans la pratique](/fr/docs/Learn/JavaScript/Objects/Object_building_practice) +- [Ajouter des fonctionnalités à la démo de nos balles bondissantes](/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features) diff --git a/files/fr/learn/javascript/objects/json/index.md b/files/fr/learn/javascript/objects/json/index.md index 8fa5a7e935..e531f12030 100644 --- a/files/fr/learn/javascript/objects/json/index.md +++ b/files/fr/learn/javascript/objects/json/index.md @@ -12,42 +12,51 @@ tags: - Tutoriel translation_of: Learn/JavaScript/Objects/JSON --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</div> - -<p>Le JavaScript Object Notation (JSON) est un format standard utilisé pour représenter des données structurées de façon semblable aux objets Javascript. Il est habituellement utilisé pour structurer et transmettre des données sur des sites web (par exemple, envoyer des données depuis un serveur vers un client afin de les afficher sur une page web ou vice versa). Comme cette notation est extrêmement courante, cet article a pour but de vous donner les connaissances nécessaires pour travailler avec JSON en JavaScript, vous apprendre à analyser la syntaxe du JSON afin d'en extraire des données et écrire vos propres objets JSON.</p> +Le JavaScript Object Notation (JSON) est un format standard utilisé pour représenter des données structurées de façon semblable aux objets Javascript. Il est habituellement utilisé pour structurer et transmettre des données sur des sites web (par exemple, envoyer des données depuis un serveur vers un client afin de les afficher sur une page web ou vice versa). Comme cette notation est extrêmement courante, cet article a pour but de vous donner les connaissances nécessaires pour travailler avec JSON en JavaScript, vous apprendre à analyser la syntaxe du JSON afin d'en extraire des données et écrire vos propres objets JSON. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Prérequis :</th> - <td>Vocabulaire de base d'informatique, connaissances de base en HTML et CSS, connaissances de base en JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Les blocs</a>) et en Javascript orienté objets (voir <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>).</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre comment utiliser les données stockées dans un objet JSON, et créer vos propres objets JSON.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Prérequis :</th> + <td> + Vocabulaire de base d'informatique, connaissances de base en HTML et + CSS, connaissances de base en JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et + <a href="/fr/docs/Learn/JavaScript/Building_blocks">Les blocs</a>) et en + Javascript orienté objets (voir + <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction" + >Introduction aux objets</a + >). + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Comprendre comment utiliser les données stockées dans un objet JSON, et + créer vos propres objets JSON. + </td> + </tr> + </tbody> </table> -<h2 id="Plus_sérieusement_quest_ce_que_le_JSON">Plus sérieusement, qu'est ce que le JSON ?</h2> +## Plus sérieusement, qu'est ce que le JSON ? -<p>{{glossary("JSON")}} est un format de données semblable à la syntaxe des objets JavaScript, qui a été popularisé par <a href="https://en.wikipedia.org/wiki/Douglas_Crockford">Douglas Crockford</a>. Malgré sa syntaxe très similaire à celle des objets littéraux JavaScript, JSON peut être utilisé indépendamment de ce langage et ainsi, de nombreux autres langages de programmation disposent de fonctionnalités permettant d'analyser la syntaxe du JSON et d'en générer.</p> +{{glossary("JSON")}} est un format de données semblable à la syntaxe des objets JavaScript, qui a été popularisé par [Douglas Crockford](https://en.wikipedia.org/wiki/Douglas_Crockford). Malgré sa syntaxe très similaire à celle des objets littéraux JavaScript, JSON peut être utilisé indépendamment de ce langage et ainsi, de nombreux autres langages de programmation disposent de fonctionnalités permettant d'analyser la syntaxe du JSON et d'en générer. -<p>Le JSON se présente sous la forme d'une chaîne de caractères —utile lorsque vous souhaitez transmettre les données sur un réseau. Il a donc besoin d'être converti en un objet JavaScript natif lorsque vous souhaitez accéder aux données. Ce n'est pas vraiment un souci puisque le JavaScript fournit un objet global <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> disposant des méthodes pour assurer la conversion entre les deux.</p> +Le JSON se présente sous la forme d'une chaîne de caractères —utile lorsque vous souhaitez transmettre les données sur un réseau. Il a donc besoin d'être converti en un objet JavaScript natif lorsque vous souhaitez accéder aux données. Ce n'est pas vraiment un souci puisque le JavaScript fournit un objet global [JSON](/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON) disposant des méthodes pour assurer la conversion entre les deux. -<div class="note"> -<p><strong>Note :</strong> Convertir une chaîne de caractères en un objet natif se nomme <strong>analyse syntaxique (parsage)</strong> tandis que le contraire porte le nom de la <strong>linéarisation (stringification)</strong>.</p> -</div> +> **Note :** Convertir une chaîne de caractères en un objet natif se nomme **analyse syntaxique (parsage)** tandis que le contraire porte le nom de la **linéarisation (stringification)**. -<p>Un objet JSON peut être stocké dans son propre fichier qui se présente simplement sous la forme d'un fichier texte avec l'extension <code>.json</code> et le {{glossary("MIME type")}} <code>application/json</code>.</p> +Un objet JSON peut être stocké dans son propre fichier qui se présente simplement sous la forme d'un fichier texte avec l'extension `.json` et le {{glossary("MIME type")}} `application/json`. -<h3 id="Structure_du_JSON">Structure du JSON</h3> +### Structure du JSON -<p>Nous disions tout à l'heure qu'un objet JSON n'était ni plus ni moins qu'un objet Javascript tout à fait normal et c'est généralement le cas. Un objet JSON accepte comme valeur les mêmes types de données de base que tout autre objet Javascript — chaînes de caractères, nombres, tableaux, booléens et tout autre objet littéral. Cela vous permet de hiérarchiser vos données comme ceci :</p> +Nous disions tout à l'heure qu'un objet JSON n'était ni plus ni moins qu'un objet Javascript tout à fait normal et c'est généralement le cas. Un objet JSON accepte comme valeur les mêmes types de données de base que tout autre objet Javascript — chaînes de caractères, nombres, tableaux, booléens et tout autre objet littéral. Cela vous permet de hiérarchiser vos données comme ceci : -<pre class="brush: json">{ +```json +{ "squadName": "Super hero squad", "homeTown": "Metro City", "formed": 2016, @@ -87,34 +96,36 @@ translation_of: Learn/JavaScript/Objects/JSON ] } ] -}</pre> +} +``` -<p>Si nous chargeons cet objet dans un fichier Javascript au sein d'une variable appelée <code>superHeroes</code> par exemple, nous pouvons accéder à ses données de la même façon que nous l'avons fait dans l'article <a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases de JavaScript orienté objets</a> à l'aide de la notation point / crochets. Par exemple :</p> +Si nous chargeons cet objet dans un fichier Javascript au sein d'une variable appelée `superHeroes` par exemple, nous pouvons accéder à ses données de la même façon que nous l'avons fait dans l'article [Les bases de JavaScript orienté objets](/fr/docs/Learn/JavaScript/Objects/Basics) à l'aide de la notation point / crochets. Par exemple : -<pre class="brush: js">superHeroes.hometown -superHeroes['active']</pre> +```js +superHeroes.hometown +superHeroes['active'] +``` -<p>Pour accéder aux données plus profondes de la hiérarchie, vous n'avez qu'à enchaîner à la fois les noms des propriétés et les indexes des tableaux. Par exemple, l'expression suivante pointe vers le troisième superpouvoir du second super héros présent dans la liste :</p> +Pour accéder aux données plus profondes de la hiérarchie, vous n'avez qu'à enchaîner à la fois les noms des propriétés et les indexes des tableaux. Par exemple, l'expression suivante pointe vers le troisième superpouvoir du second super héros présent dans la liste : -<pre class="brush: js">superHeroes['members'][1]['powers'][2]</pre> +```js +superHeroes['members'][1]['powers'][2] +``` -<ol> - <li>D'abord, nous partons de la variable — <code>superHeroes</code></li> - <li>À l'intérieur de laquelle nous désirons accéder à la propriété <code>members</code>, donc, nous tapons <code>["members"]</code>.</li> - <li><code>members</code> contient un tableau renfermant des objets. Nous désirons accéder au second de ces objets, donc nous utilisons <code>[1]</code>.</li> - <li>À l'intérieur de cet objet, nous souhaitons accéder à la propriété <code>powers</code>, donc, nous utilisons <code>["powers"]</code>.</li> - <li>Enfin, à l'intérieur de cette propriété <code>powers</code> nous trouvons un nouveau tableau qui contient les super pouvoirs de ce héros. Nous désirons obtenir le troisième, donc nous tapons <code>[2]</code>.</li> -</ol> +1. D'abord, nous partons de la variable — `superHeroes` +2. À l'intérieur de laquelle nous désirons accéder à la propriété `members`, donc, nous tapons `["members"]`. +3. `members` contient un tableau renfermant des objets. Nous désirons accéder au second de ces objets, donc nous utilisons `[1]`. +4. À l'intérieur de cet objet, nous souhaitons accéder à la propriété `powers`, donc, nous utilisons `["powers"]`. +5. Enfin, à l'intérieur de cette propriété `powers` nous trouvons un nouveau tableau qui contient les super pouvoirs de ce héros. Nous désirons obtenir le troisième, donc nous tapons `[2]`. -<div class="note"> -<p><strong>Note :</strong> L'objet JSON vu ci-dessus est disponible au sein d'une variable dans notre exemple <a href="http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html">JSONTest.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html">code source</a>). Essayez de le charger et d'accéder aux données en utilisant la console Javascript de votre navigateur.</p> -</div> +> **Note :** L'objet JSON vu ci-dessus est disponible au sein d'une variable dans notre exemple [JSONTest.html](http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html)). Essayez de le charger et d'accéder aux données en utilisant la console Javascript de votre navigateur. -<h3 id="Des_tableaux_en_tant_que_JSON">Des tableaux en tant que JSON</h3> +### Des tableaux en tant que JSON -<p>Un peu plus haut, nous avons dit qu'un objet JSON n'était ni plus ni moins qu'un objet Javascript tout à fait normal et c'est généralement le cas. La raison pour laquelle nous avons dit "généralement le cas" est qu'un tableau peut également être un objet JSON valide, par exemple :</p> +Un peu plus haut, nous avons dit qu'un objet JSON n'était ni plus ni moins qu'un objet Javascript tout à fait normal et c'est généralement le cas. La raison pour laquelle nous avons dit "généralement le cas" est qu'un tableau peut également être un objet JSON valide, par exemple : -<pre class="brush: json">[ +```json +[ { "name": "Molecule Man", "age": 29, @@ -135,88 +146,102 @@ superHeroes['active']</pre> "Superhuman reflexes" ] } -]</pre> +] +``` -<p>Le code ci dessus est une notation JSON parfaitement valide. Vous n'aurez qu'à accéder aux éléments de votre tableau en commençant avec un index, par exemple : <code>[0]["powers"][0]</code>.</p> +Le code ci dessus est une notation JSON parfaitement valide. Vous n'aurez qu'à accéder aux éléments de votre tableau en commençant avec un index, par exemple : `[0]["powers"][0]`. -<h3 id="Notes_diverses">Notes diverses</h3> +### Notes diverses -<ul> - <li>Un objet JSON est uniquement un format de données — il ne contient que des propriétés mais pas de méthodes.</li> - <li>La notation JSON nécessite l'usage des guillemets pour être valide. Il est obligatoire d'utiliser des guillemets et non les apostrophes autour des chaînes de caractères et des noms de propriétés.</li> - <li>Une simple virgule ou un double point mal placé peut rendre votre fichier JSON invalide et non fonctionnel. Soyez très attentif aux données que vous utilisez (bien que le JSON généré automatiquement par un programme sera moins enclin à contenir des erreurs, à partir du moment où le programme est codé correctement). Vous pouvez utiliser une application comme <a href="http://jsonlint.com/">JSONLint</a> pour valider votre code JSON.</li> - <li>Dans l'absolu, le JSON peut prendre la forme de n'importe quel type de données qui serait valide pour être contenu dans du JSON et non juste des tableaux ou des objets. Ainsi, par exemple, une simple chaîne de caractères ou un nombre serait un objet JSON valide.</li> - <li>Contrairement au JavaScript dans lequel les propriétés (<em>keys</em>) non entourées de guillemets peuvent être utilisées, en JSON, seules les chaînes de caractères entourées de guillemets peuvent être utilisées en tant que propriétés.</li> -</ul> +- Un objet JSON est uniquement un format de données — il ne contient que des propriétés mais pas de méthodes. +- La notation JSON nécessite l'usage des guillemets pour être valide. Il est obligatoire d'utiliser des guillemets et non les apostrophes autour des chaînes de caractères et des noms de propriétés. +- Une simple virgule ou un double point mal placé peut rendre votre fichier JSON invalide et non fonctionnel. Soyez très attentif aux données que vous utilisez (bien que le JSON généré automatiquement par un programme sera moins enclin à contenir des erreurs, à partir du moment où le programme est codé correctement). Vous pouvez utiliser une application comme [JSONLint](http://jsonlint.com/) pour valider votre code JSON. +- Dans l'absolu, le JSON peut prendre la forme de n'importe quel type de données qui serait valide pour être contenu dans du JSON et non juste des tableaux ou des objets. Ainsi, par exemple, une simple chaîne de caractères ou un nombre serait un objet JSON valide. +- Contrairement au JavaScript dans lequel les propriétés (_keys_) non entourées de guillemets peuvent être utilisées, en JSON, seules les chaînes de caractères entourées de guillemets peuvent être utilisées en tant que propriétés. -<h2 id="Activité_Manipuler_le_JSON_au_travers_dun_exemple">Activité : Manipuler le JSON au travers d'un exemple</h2> +## Activité : Manipuler le JSON au travers d'un exemple -<p>Allez ! Un petit exemple pour voir comment nous pouvons nous servir de données JSON sur un site web.</p> +Allez ! Un petit exemple pour voir comment nous pouvons nous servir de données JSON sur un site web. -<h3 id="Lançons_nous">Lançons nous</h3> +### Lançons nous -<p>Pour commencer, faites une copie locale de nos fichiers <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html">heroes.html</a> et <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css">style.css</a>. Le dernier contient simplement quelques instructions CSS pour la mise en forme de notre page alors que le premier n'est ni plus ni moins qu'un squelette HTML de base :</p> +Pour commencer, faites une copie locale de nos fichiers [heroes.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html) et [style.css](https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css). Le dernier contient simplement quelques instructions CSS pour la mise en forme de notre page alors que le premier n'est ni plus ni moins qu'un squelette HTML de base : -<pre class="brush: html"><header> -</header> +```html +<header> +</header> -<section> -</section></pre> +<section> +</section> +``` -<p>Nous trouvons également un élément {{HTMLElement("script")}} dans lequel nous écrirons le code Javascript de cet exercice. Pour le moment, il ne contient que deux lignes destinées à récuperer les éléments {{HTMLElement("header")}} et {{HTMLElement("section")}} pour les stocker dans des variables :</p> +Nous trouvons également un élément {{HTMLElement("script")}} dans lequel nous écrirons le code Javascript de cet exercice. Pour le moment, il ne contient que deux lignes destinées à récuperer les éléments {{HTMLElement("header")}} et {{HTMLElement("section")}} pour les stocker dans des variables : -<pre class="brush: js">var header = document.querySelector('header'); -var section = document.querySelector('section');</pre> +```js +var header = document.querySelector('header'); +var section = document.querySelector('section'); +``` -<p>Nos données JSON sont disponibles sur notre GitHub ici : <a href="https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json</a>.</p> +Nos données JSON sont disponibles sur notre GitHub ici : <https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json>. -<p>Nous souhaitons les récupérer et, après quelques manipulations du DOM, les afficher comme ceci :</p> +Nous souhaitons les récupérer et, après quelques manipulations du DOM, les afficher comme ceci : -<p><img alt="" src="json-superheroes.png"></p> + -<h3 id="Chargeons_notre_JSON">Chargeons notre JSON</h3> +### Chargeons notre JSON -<p>Pour charger nos données JSON, nous allons utiliser l'API {{domxref("XMLHttpRequest")}} (qu'on appelle plus couramment <strong>XHR</strong>). Il s'agit d'un objet JavaScript extrêmement utile qui nous permet de construire une requête afin d'interroger un serveur pour obtenir des ressources diverses (images, texte, JSON, ou n'importe quel extrait HTML) le tout en Javascript. En d'autres termes, cela nous permet de mettre à jour de petites sections de contenu sans avoir à recharger notre page toute entière. Ceci conduit à des pages web plus réactives. Mais même si le sujet est très tentant, il dépasse largement l'objet de cet article pour être expliqué plus en détails.</p> +Pour charger nos données JSON, nous allons utiliser l'API {{domxref("XMLHttpRequest")}} (qu'on appelle plus couramment **XHR**). Il s'agit d'un objet JavaScript extrêmement utile qui nous permet de construire une requête afin d'interroger un serveur pour obtenir des ressources diverses (images, texte, JSON, ou n'importe quel extrait HTML) le tout en Javascript. En d'autres termes, cela nous permet de mettre à jour de petites sections de contenu sans avoir à recharger notre page toute entière. Ceci conduit à des pages web plus réactives. Mais même si le sujet est très tentant, il dépasse largement l'objet de cet article pour être expliqué plus en détails. -<ol> - <li>Donc, pour commencer, nous allons charger l'URL du fichier JSON que nous voulons récupérer dans une variable. Aussi, ajouter la ligne suivante à votre code Javascript : - <pre class="brush: js">var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';</pre> - </li> - <li>Afin de créer une requête, nous avons besoin d'instancier un nouvel objet <code>XMLHttpRequest</code> à partir de son constructeur en utilisant le mot clé new. Ajouter la ligne suivante à votre script : - <pre class="brush: js">var request = new XMLHttpRequest();</pre> - </li> - <li>Maintenant, nous avons besoin d'ouvrir une nouvelle requête grâce à la méthode <code><a href="/fr/docs/Web/API/XMLHttpRequest/open">open()</a></code>. Ajoutez la ligne suivante : - <pre class="brush: js">request.open('GET', requestURL);</pre> +1. Donc, pour commencer, nous allons charger l'URL du fichier JSON que nous voulons récupérer dans une variable. Aussi, ajouter la ligne suivante à votre code Javascript : - <p>Cette méthode prend au moins deux paramètres — il y a d'autres paramètres optionnels disponibles. Deux suffiront pour notre exemple :</p> + ```js + var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json'; + ``` - <ul> - <li>La méthode HTTP à utiliser sur le réseau pour notre requête. Dans notre cas, la méthode <code><a href="/fr/docs/Web/HTTP/Methods/GET">GET</a></code> est appropriée dans la mesure où nous voulons simplement récupérer quelques données.</li> - <li>L'URL où adresser notre requête — il s'agit de l'URL du fichier JSON dont nous parlions tout à l'heure.</li> - </ul> - </li> - <li>Ensuite, ajoutez les deux lignes suivantes — ici, nous attribuons la valeur <code>'json'</code><strong> </strong>à <code><a href="/fr/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code>, signalant ainsi au serveur que nous attendons une réponse au format JSON. Puis, nous envoyons notre requête à l'aide de la méthode <code><a href="/fr/docs/Web/API/XMLHttpRequest/send">send()</a></code> : - <pre class="brush: js">request.responseType = 'json'; -request.send();</pre> - </li> - <li>La dernière partie de cette section concerne la réponse du serveur et son traitement. Ajoutez les lignes suivantes à la fin de votre code : - <pre class="brush: js">request.onload = function() { - var superHeroes = request.response; - populateHeader(superHeroes); - showHeroes(superHeroes); -}</pre> - </li> -</ol> +2. Afin de créer une requête, nous avons besoin d'instancier un nouvel objet `XMLHttpRequest` à partir de son constructeur en utilisant le mot clé new. Ajouter la ligne suivante à votre script : + + ```js + var request = new XMLHttpRequest(); + ``` + +3. Maintenant, nous avons besoin d'ouvrir une nouvelle requête grâce à la méthode [`open()`](/fr/docs/Web/API/XMLHttpRequest/open). Ajoutez la ligne suivante : + + ```js + request.open('GET', requestURL); + ``` + + Cette méthode prend au moins deux paramètres — il y a d'autres paramètres optionnels disponibles. Deux suffiront pour notre exemple : + + - La méthode HTTP à utiliser sur le réseau pour notre requête. Dans notre cas, la méthode [`GET`](/fr/docs/Web/HTTP/Methods/GET) est appropriée dans la mesure où nous voulons simplement récupérer quelques données. + - L'URL où adresser notre requête — il s'agit de l'URL du fichier JSON dont nous parlions tout à l'heure. + +4. Ensuite, ajoutez les deux lignes suivantes — ici, nous attribuons la valeur `'json'`\*\* \*\*à [`responseType`](/fr/docs/Web/API/XMLHttpRequest/responseType), signalant ainsi au serveur que nous attendons une réponse au format JSON. Puis, nous envoyons notre requête à l'aide de la méthode [`send()`](/fr/docs/Web/API/XMLHttpRequest/send) : + + ```js + request.responseType = 'json'; + request.send(); + ``` + +5. La dernière partie de cette section concerne la réponse du serveur et son traitement. Ajoutez les lignes suivantes à la fin de votre code : + + ```js + request.onload = function() { + var superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); + } + ``` -<p>Ici, nous stockons la réponse à notre requête (disponible au travers de la propriété <code><a href="/fr/docs/Web/API/XMLHttpRequest/response">response</a></code>) dans la variable <code>superHeroes</code> ; cette variable contiendra désormais l'objet JavaScript basé sur le JSON ! Nous passerons ensuite cet objet en paramètre à deux fonctions — la première remplira le <<code>header></code> avec les données correspondantes tandis que la seconde créera une carte d'identité pour chaque héros de l'équipe et l'ajoutera dans la <code><section></code>.</p> +Ici, nous stockons la réponse à notre requête (disponible au travers de la propriété [`response`](/fr/docs/Web/API/XMLHttpRequest/response)) dans la variable `superHeroes` ; cette variable contiendra désormais l'objet JavaScript basé sur le JSON ! Nous passerons ensuite cet objet en paramètre à deux fonctions — la première remplira le <`header>` avec les données correspondantes tandis que la seconde créera une carte d'identité pour chaque héros de l'équipe et l'ajoutera dans la `<section>`. -<p>Nous avons encapsulé ce code dans un gestionnaire d'évènements qui s'exécutera quand l'évènement load sera déclenché sur l'objet request (voir <code><a href="/fr/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) — simplement parce que l'évènement load est déclenché quand une réponse a été renvoyée avec succès ; en procédant de la sorte, nous serons certains que la propriété <code>request.response</code> sera disponible au moment où nous essayerons d'en faire quelque chose.</p> +Nous avons encapsulé ce code dans un gestionnaire d'évènements qui s'exécutera quand l'évènement load sera déclenché sur l'objet request (voir [`onload`](/fr/docs/Web/API/XMLHttpRequestEventTarget/onload)) — simplement parce que l'évènement load est déclenché quand une réponse a été renvoyée avec succès ; en procédant de la sorte, nous serons certains que la propriété `request.response` sera disponible au moment où nous essayerons d'en faire quelque chose. -<h3 id="Remplissage_de_len-tête">Remplissage de l'en-tête</h3> +### Remplissage de l'en-tête -<p>Maintenant que nous avons récupéré et converti en objet JavaScript nos données JSON, il est temps d'en faire bon usage : implémentons donc les deux fonctions évoquées ci-dessus. Avant tout, ajoutons les lignes suivantes en dessous de notre code :</p> +Maintenant que nous avons récupéré et converti en objet JavaScript nos données JSON, il est temps d'en faire bon usage : implémentons donc les deux fonctions évoquées ci-dessus. Avant tout, ajoutons les lignes suivantes en dessous de notre code : -<pre class="brush: js">function populateHeader(jsonObj) { +```js +function populateHeader(jsonObj) { var myH1 = document.createElement('h1'); myH1.textContent = jsonObj['squadName']; header.appendChild(myH1); @@ -224,18 +249,20 @@ request.send();</pre> var myPara = document.createElement('p'); myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + jsonObj['formed']; header.appendChild(myPara); -}</pre> +} +``` -<p>Nous avons appelé le paramètre de cette fonction <code>jsonObj</code> afin de garder en tête que cet objet JavaScript provient du JSON. Ici, nous créons tout d'abord un élément {{HTMLElement("h1")}} à l'aide de <code><a href="/fr/docs/Web/API/Document/createElement">createElement()</a></code>, nous fixons son <code><a href="/fr/docs/Web/API/Node/textContent">textContent</a></code> à la valeur de la propriété <code>squadName</code> de l'objet, puis nous l'ajoutons à l'en-tête en utilisant <code><a href="/fr/docs/Web/API/Node/appendChild">appendChild()</a></code>. Ensuite, nous faisons quelque chose de relativement similaire avec un élément paragraphe : nous le créons, fixons son contenu et l'ajoutons à l'en-tête. La seule différence est que pour son contenu, nous avons concaténé la chaîne de caractère <code>homeTown</code> et la propriété <code>formed</code> de l'objet.</p> +Nous avons appelé le paramètre de cette fonction `jsonObj` afin de garder en tête que cet objet JavaScript provient du JSON. Ici, nous créons tout d'abord un élément {{HTMLElement("h1")}} à l'aide de [`createElement()`](/fr/docs/Web/API/Document/createElement), nous fixons son [`textContent`](/fr/docs/Web/API/Node/textContent) à la valeur de la propriété `squadName` de l'objet, puis nous l'ajoutons à l'en-tête en utilisant [`appendChild()`](/fr/docs/Web/API/Node/appendChild). Ensuite, nous faisons quelque chose de relativement similaire avec un élément paragraphe : nous le créons, fixons son contenu et l'ajoutons à l'en-tête. La seule différence est que pour son contenu, nous avons concaténé la chaîne de caractère `homeTown` et la propriété `formed` de l'objet. -<h3 id="Création_des_fiches_des_héros">Création des fiches des héros</h3> +### Création des fiches des héros -<p>Maintenant, ajoutons la fonction suivante qui crée et affiche les fiches de nos super-héros en dessous de notre code :</p> +Maintenant, ajoutons la fonction suivante qui crée et affiche les fiches de nos super-héros en dessous de notre code : -<pre class="brush: js">function showHeroes(jsonObj) { +```js +function showHeroes(jsonObj) { var heroes = jsonObj['members']; - for (var i = 0; i < heroes.length; i++) { + for (var i = 0; i < heroes.length; i++) { var myArticle = document.createElement('article'); var myH2 = document.createElement('h2'); var myPara1 = document.createElement('p'); @@ -249,7 +276,7 @@ request.send();</pre> myPara3.textContent = 'Superpowers:'; var superPowers = heroes[i].powers; - for (var j = 0; j < superPowers.length; j++) { + for (var j = 0; j < superPowers.length; j++) { var listItem = document.createElement('li'); listItem.textContent = superPowers[j]; myList.appendChild(listItem); @@ -263,45 +290,41 @@ request.send();</pre> section.appendChild(myArticle); } -}</pre> +} +``` -<p>Pour commencer, on stocke la propriété <code>members</code> de l'objet JavaScript dans une nouvelle variable. Ce tableau contient plusieurs objets contenant les informations relatives à chaque héros.</p> +Pour commencer, on stocke la propriété `members` de l'objet JavaScript dans une nouvelle variable. Ce tableau contient plusieurs objets contenant les informations relatives à chaque héros. -<p>Maintenant, on utilise une <a href="/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code">boucle for</a> pour parcourir chaque object du tableau. Pour chaque cas, il faut :</p> +Maintenant, on utilise une [boucle for](/fr/docs/Apprendre/JavaScript/Building_blocks/Looping_code) pour parcourir chaque object du tableau. Pour chaque cas, il faut : -<ol> - <li>Créer plusieurs nouveaux éléments : un <code><article></code>, un <code><h2></code>, trois <code><p></code>s, et un <code><ul></code>.</li> - <li>Mettre le <code>name</code> du héros actuel dans le <code><h2></code>.</li> - <li>Remplir les trois paragraphes avec leur <code>secretIdentity</code>, leur <code>age</code>, et une ligne nommée "Superpowers:" pour présenter la liste des super-pouvoirs.</li> - <li>Stocker la propriété <code>powers</code> dans une nouvelle variable nommée <code>superPowers</code> contenant un tableau listant les super-pouvoirs du héros actuel.</li> - <li>Utiliser une autre boucle <code>for</code> pour parcourir les super-pouvoirs du héros actuel — créer pour chacun d'entre eux un élément <code><li></code>, y placer le super-pouvoir et placer le <code>listItem</code> dans l'élément <code><ul></code> (<code>myList</code>) en utilisant <code>appendChild()</code>.</li> - <li>Pour finir, on ajoute <code><h2></code>, les <code><p></code>s et <code><ul></code> à <code><article></code> (<code>myArticle</code>), et on ajoute <code><article></code> à <code><section></code>. L'ordre d'ajout est important, c'est l'ordre dans lequel les éléments seront affichés dans le HTML.</li> -</ol> +1. Créer plusieurs nouveaux éléments : un `<article>`, un `<h2>`, trois `<p>`s, et un `<ul>`. +2. Mettre le `name` du héros actuel dans le `<h2>`. +3. Remplir les trois paragraphes avec leur `secretIdentity`, leur `age`, et une ligne nommée "Superpowers:" pour présenter la liste des super-pouvoirs. +4. Stocker la propriété `powers` dans une nouvelle variable nommée `superPowers` contenant un tableau listant les super-pouvoirs du héros actuel. +5. Utiliser une autre boucle `for` pour parcourir les super-pouvoirs du héros actuel — créer pour chacun d'entre eux un élément `<li>`, y placer le super-pouvoir et placer le `listItem` dans l'élément `<ul>` (`myList`) en utilisant `appendChild()`. +6. Pour finir, on ajoute `<h2>`, les `<p>`s et `<ul>` à `<article>` (`myArticle`), et on ajoute `<article>` à `<section>`. L'ordre d'ajout est important, c'est l'ordre dans lequel les éléments seront affichés dans le HTML. -<div class="note"> -<p><strong>Note :</strong> Si vous ne parvenez pas à faire fonctionner l'exemple, consultez notre code source <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html">heroes-finished.html</a> (ou regardez-le <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html">en action</a>.)</p> -</div> +> **Note :** Si vous ne parvenez pas à faire fonctionner l'exemple, consultez notre code source [heroes-finished.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html) (ou regardez-le [en action](http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html).) -<div class="note"> -<p><strong>Note :</strong> Si vous comprenez difficilement la notation avec un point/une accolade utilisée pour accéder au JSON, ouvrez le fichier <a href="http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">superheroes.json</a> dans un nouvel onglet ou dans votre éditeur de texte et consultez-le pendant la lecture de notre code Javascript. Vous pouvez également vous reporter à notre article <a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases du JavaScript orienté objet</a> pour obtenir plus de détails sur la notation avec un point et avec une accolade.</p> -</div> +> **Note :** Si vous comprenez difficilement la notation avec un point/une accolade utilisée pour accéder au JSON, ouvrez le fichier [superheroes.json](http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json) dans un nouvel onglet ou dans votre éditeur de texte et consultez-le pendant la lecture de notre code Javascript. Vous pouvez également vous reporter à notre article [Les bases du JavaScript orienté objet](/fr/docs/Learn/JavaScript/Objects/Basics) pour obtenir plus de détails sur la notation avec un point et avec une accolade. -<h2 id="Conversion_entre_objets_et_textes">Conversion entre objets et textes</h2> +## Conversion entre objets et textes -<p>Dans l'exemple ci-dessus, accéder au JSON est simple, il suffit de définir la requête XHR pour renvoyer la réponse au format JSON en écrivant :</p> +Dans l'exemple ci-dessus, accéder au JSON est simple, il suffit de définir la requête XHR pour renvoyer la réponse au format JSON en écrivant : -<pre class="brush: js">request.responseType = 'json';</pre> +```js +request.responseType = 'json'; +``` -<p>Mais on n'a pas toujours cette chance — il est possible de recevoir la réponse JSON sous la forme d'une chaîne de caractères et il faut alors la convertir en objet. À l'inverse, lorsqu'on veut envoyer un objet JavaScript à travers le réseau il faut au préalable le convertir en JSON (une chaîne de caractères). Heureusement, ces deux problèmes sont tellement communs dans le développement web qu'un objet <a href="/fr/docs/Web/JavaScript/Reference/Objets_globaux/JSON">JSON</a> interne a été ajouté aux navigateurs depuis longtemps, contenant les deux méthodes suivantes :</p> +Mais on n'a pas toujours cette chance — il est possible de recevoir la réponse JSON sous la forme d'une chaîne de caractères et il faut alors la convertir en objet. À l'inverse, lorsqu'on veut envoyer un objet JavaScript à travers le réseau il faut au préalable le convertir en JSON (une chaîne de caractères). Heureusement, ces deux problèmes sont tellement communs dans le développement web qu'un objet [JSON](/fr/docs/Web/JavaScript/Reference/Objets_globaux/JSON) interne a été ajouté aux navigateurs depuis longtemps, contenant les deux méthodes suivantes : -<ul> - <li><code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">parse()</a></code> qui accepte un objet JSON sous la forme d'une chaîne de caractères en paramètre et renvoie l'objet JavaScript correspondant.</li> - <li><code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringify()</a></code> qui accepte un objet JavaScript en paramètre et renvoie son équivalent sous la forme d'une chaîne de caractères JSON.</li> -</ul> +- [`parse()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) qui accepte un objet JSON sous la forme d'une chaîne de caractères en paramètre et renvoie l'objet JavaScript correspondant. +- [`stringify()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) qui accepte un objet JavaScript en paramètre et renvoie son équivalent sous la forme d'une chaîne de caractères JSON. -<p>Vous pouvez voir la première méthode en action dans notre exemple <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html">heroes-finished-json-parse.html</a> (voir le <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html">code source</a>) — C'est la même chose que pour l'exemple que nous avons écrit un peu plus tôt, à ceci près qu'on indique à la requête XHR de renvoyer la réponse en JSON sous forme de texte avant d'utiliser la méthode <code>parse()</code> pour la convertir en objet JavaScript. La partie du code correspondante se trouve ci-dessous :</p> +Vous pouvez voir la première méthode en action dans notre exemple [heroes-finished-json-parse.html](http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html) (voir le [code source](https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html)) — C'est la même chose que pour l'exemple que nous avons écrit un peu plus tôt, à ceci près qu'on indique à la requête XHR de renvoyer la réponse en JSON sous forme de texte avant d'utiliser la méthode `parse()` pour la convertir en objet JavaScript. La partie du code correspondante se trouve ci-dessous : -<pre class="brush: js">request.open('GET', requestURL); +```js +request.open('GET', requestURL); request.responseType = 'text'; // now we're getting a string! request.send(); @@ -310,29 +333,30 @@ request.onload = function() { var superHeroes = JSON.parse(superHeroesText); // convert it to an object populateHeader(superHeroes); showHeroes(superHeroes); -}</pre> +} +``` -<p>Comme vous pouvez le deviner, <code>stringify()</code> fait exactement le contraire. Essayez d'entrer les lignes ci-dessous une par une dans la console Javascript de votre navigateur pour voir la méthode en action :</p> +Comme vous pouvez le deviner, `stringify()` fait exactement le contraire. Essayez d'entrer les lignes ci-dessous une par une dans la console Javascript de votre navigateur pour voir la méthode en action : -<pre class="brush: js">var myJSON = { "name": "Chris", "age": "38" }; +```js +var myJSON = { "name": "Chris", "age": "38" }; myJSON var myString = JSON.stringify(myJSON); -myString</pre> +myString +``` -<p>On commence par créer un objet JavaScript puis on vérifie son contenu avant de le convertir en chaîne de caractères JSON avec <code>stringify()</code> — en sauvegardant au passage le résultat dans une nouvelle variable avant d'effectuer à nouveau une vérification du contenu.</p> +On commence par créer un objet JavaScript puis on vérifie son contenu avant de le convertir en chaîne de caractères JSON avec `stringify()` — en sauvegardant au passage le résultat dans une nouvelle variable avant d'effectuer à nouveau une vérification du contenu. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Dans cet article, nous vous donnons un manuel simple pour utiliser le JSON dans vos programmes, incluant les méthodes de création et d'analyse syntaxique (parsage) du JSON et d'accès aux données qu'il contient. Dans le prochain article, nous débuterons l'apprentissage du Javascript orienté objet.</p> +Dans cet article, nous vous donnons un manuel simple pour utiliser le JSON dans vos programmes, incluant les méthodes de création et d'analyse syntaxique (parsage) du JSON et d'accès aux données qu'il contient. Dans le prochain article, nous débuterons l'apprentissage du Javascript orienté objet. -<h2 id="Voir_aussi">Voir aussi</h2> +## Voir aussi -<ul> - <li><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON">La page de référence sur l'objet JSON</a></li> - <li><a href="/fr/docs/Web/API/XMLHttpRequest">La page de référence sur l'objet XMLHttpRequest</a></li> - <li><a href="/fr/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Utiliser XMLHttpRequest</a></li> - <li><a href="/fr/docs/Web/HTTP/Methods">Les méthodes de requêtes HTTP </a></li> - <li><a href="http://json.org">Le site web officiel avec un lien vers les normes de l' ECMA</a></li> -</ul> +- [La page de référence sur l'objet JSON](/fr/docs/Web/JavaScript/Reference/Global_Objects/JSON) +- [La page de référence sur l'objet XMLHttpRequest](/fr/docs/Web/API/XMLHttpRequest) +- [Utiliser XMLHttpRequest](/fr/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) +- [Les méthodes de requêtes HTTP ](/fr/docs/Web/HTTP/Methods) +- [Le site web officiel avec un lien vers les normes de l' ECMA](http://json.org) -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}} diff --git a/files/fr/learn/javascript/objects/object-oriented_js/index.md b/files/fr/learn/javascript/objects/object-oriented_js/index.md index a264d9063b..be3d5ffacd 100644 --- a/files/fr/learn/javascript/objects/object-oriented_js/index.md +++ b/files/fr/learn/javascript/objects/object-oriented_js/index.md @@ -12,147 +12,166 @@ tags: translation_of: Learn/JavaScript/Objects/Object-oriented_JS original_slug: Learn/JavaScript/Objects/JS_orienté-objet --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</div> - -<p>Après avoir parcouru les fondamentaux, nous allons aborder en détail le JavaScript orienté objet (JSOO). Cet article présente une approche simple de la programmation orientée objet (POO) et détaille comment JavaScript émule des classes objet au travers des méthodes constructeur et comment instancier ces objets.</p> +Après avoir parcouru les fondamentaux, nous allons aborder en détail le JavaScript orienté objet (JSOO). Cet article présente une approche simple de la programmation orientée objet (POO) et détaille comment JavaScript émule des classes objet au travers des méthodes constructeur et comment instancier ces objets. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Pré-requis :</th> - <td>Connaissances de base en informatique et compréhension des notions HTML et CSS, notions de JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction</a>)</td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td>Comprendre les concepts de base derrière la programmation orientée objet et comment ils s'appliquent à JavaScript ( « tout est objet » ) et comment créer des constructeurs et instancier des objets.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td> + Connaissances de base en informatique et compréhension des notions HTML + et CSS, notions de JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et + <a href="/fr/docs/Learn/JavaScript/Building_blocks" + >Blocs de construction</a + >) + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + Comprendre les concepts de base derrière la programmation orientée objet + et comment ils s'appliquent à JavaScript ( « tout est objet » ) et + comment créer des constructeurs et instancier des objets. + </td> + </tr> + </tbody> </table> -<h2 id="La_programmation_orientée_objet_de_loin">La programmation orientée objet de loin</h2> +## La programmation orientée objet de loin -<p>Pour commencer, donnons une vue simplifiée et de haut niveau de ce qu'est la programmation orientée objet (POO). On parle d'une vision simplifiée étant donnée que la POO peut devenir très vite complexe et qu'être exhaustif rendrait probablement la découverte plus confuse et difficile qu'autre chose. L'idée de base de la POO consiste à utiliser des objets pour modéliser les objets du monde réel que l'on souhaite représenter dans nos programmes et/ou de fournir un moyen simple d'accéder à une fonctionnalité qu'il serait difficile d'utiliser autrement.</p> +Pour commencer, donnons une vue simplifiée et de haut niveau de ce qu'est la programmation orientée objet (POO). On parle d'une vision simplifiée étant donnée que la POO peut devenir très vite complexe et qu'être exhaustif rendrait probablement la découverte plus confuse et difficile qu'autre chose. L'idée de base de la POO consiste à utiliser des objets pour modéliser les objets du monde réel que l'on souhaite représenter dans nos programmes et/ou de fournir un moyen simple d'accéder à une fonctionnalité qu'il serait difficile d'utiliser autrement. -<p>Les objets peuvent contenir des données et du code représentant de l'information au sujet de la chose que l'on essaie de modéliser ainsi que des fonctionnalités ou un comportement que l'on souhaite lui appliquer. Les données (et bien souvent les fonctions) associées à un objet peuvent être stockées (le terme officiel est <strong>encapsulé</strong>) à l'intérieur d'un paquet objet. Il est possible de donner un nom spécifique à un paquet objet afin d'y faire référence, on parle alors d'<strong>espace de noms</strong> ou <em>namespace</em>, il sera ainsi plus facile de le manipuler et d'y accéder. Les objets peuvent aussi servir pour stocker des données et les transférer facilement sur un réseau.</p> +Les objets peuvent contenir des données et du code représentant de l'information au sujet de la chose que l'on essaie de modéliser ainsi que des fonctionnalités ou un comportement que l'on souhaite lui appliquer. Les données (et bien souvent les fonctions) associées à un objet peuvent être stockées (le terme officiel est **encapsulé**) à l'intérieur d'un paquet objet. Il est possible de donner un nom spécifique à un paquet objet afin d'y faire référence, on parle alors d'**espace de noms** ou _namespace_, il sera ainsi plus facile de le manipuler et d'y accéder. Les objets peuvent aussi servir pour stocker des données et les transférer facilement sur un réseau. -<h3 id="Définissons_un_modèle_objet">Définissons un modèle objet</h3> +### Définissons un modèle objet -<p>Nous allons voir un programme simple qui affiche des informations à propos des élèves et des professeurs d'une école. Nous allons aborder la théorie de la programmation orientée objet de manière générale sans l'appliquer à un langage particulier.</p> +Nous allons voir un programme simple qui affiche des informations à propos des élèves et des professeurs d'une école. Nous allons aborder la théorie de la programmation orientée objet de manière générale sans l'appliquer à un langage particulier. -<p>Pour débuter, nous pouvons réutiliser l'objet Personne que nous avons créé dans notre <a href="/fr/docs/Learn/JavaScript/Objects/Basics">premier article</a>, il définit un ensemble de données et actions d'une personne. Il existe tout un tas de choses que nous pourrions savoir au sujet d'une personne (son adresse, sa taille, sa pointure, son ADN, son numéro de passeport, ses traits particuliers significatifs… ). En l'occurrence, nous souhaitons uniquement afficher son nom, son âge, ses passions, écrire une petite introduction à son sujet en utilisant ces données et lui apprendre à se présenter. On parle alors d'<strong>abstraction </strong>: créer un modèle simplifié de quelque chose de complexe mais qui ne contient que les aspects qui nous intéressent. Il sera alors plus simple de manipuler ce modèle objet simplifié dans le cadre de notre programme.</p> +Pour débuter, nous pouvons réutiliser l'objet Personne que nous avons créé dans notre [premier article](/fr/docs/Learn/JavaScript/Objects/Basics), il définit un ensemble de données et actions d'une personne. Il existe tout un tas de choses que nous pourrions savoir au sujet d'une personne (son adresse, sa taille, sa pointure, son ADN, son numéro de passeport, ses traits particuliers significatifs… ). En l'occurrence, nous souhaitons uniquement afficher son nom, son âge, ses passions, écrire une petite introduction à son sujet en utilisant ces données et lui apprendre à se présenter. On parle alors d'**abstraction** : créer un modèle simplifié de quelque chose de complexe mais qui ne contient que les aspects qui nous intéressent. Il sera alors plus simple de manipuler ce modèle objet simplifié dans le cadre de notre programme. -<p><img alt="Classe Personne avec attributs élémentaires" src="ClassePersonne.png"></p> + -<p>Dans plusieurs langages de POO, la définition d'un objet est appelé une <strong>classe </strong>(comme on le verra ci-après, JavaScript se base sur un mécanisme et une terminologie différente). En réalité ce n'est pas vraiment un objet mais plutôt un modèle qui définit les propriétés que notre objet doit avoir.</p> +Dans plusieurs langages de POO, la définition d'un objet est appelé une **classe** (comme on le verra ci-après, JavaScript se base sur un mécanisme et une terminologie différente). En réalité ce n'est pas vraiment un objet mais plutôt un modèle qui définit les propriétés que notre objet doit avoir. -<h3 id="Créons_des_objets">Créons des objets</h3> +### Créons des objets -<p>À partir de notre classe, nous pouvons créer des objets, on parle alors d'<strong>instancier des objets</strong>, une classe objet a alors <strong>une instance</strong>. Il s'agit d'objets qui contiennent les données et attributs définis dans une classe. À partir de notre classe Personne, nous pouvons modéliser des personnes réelles :</p> +À partir de notre classe, nous pouvons créer des objets, on parle alors d'**instancier des objets**, une classe objet a alors **une instance**. Il s'agit d'objets qui contiennent les données et attributs définis dans une classe. À partir de notre classe Personne, nous pouvons modéliser des personnes réelles : -<p><img alt="Instantiation on a Personn Class for JS examples (fr)" src="InstancePersonne.png"></p> + -<p>Lorsque l'instance d'un objet est créée, on appelle la <strong>fonction</strong> <strong>constructeur </strong>de la classe pour la créer. On parle d'<strong>instanciation</strong> d'un objet — l'objet ainsi créé est <strong>instancié</strong> à partir de la classe.</p> +Lorsque l'instance d'un objet est créée, on appelle la **fonction** **constructeur** de la classe pour la créer. On parle d'**instanciation** d'un objet — l'objet ainsi créé est **instancié** à partir de la classe. -<h3 id="Classes_filles">Classes filles</h3> +### Classes filles -<p>Pour notre exemple, nous n'allons pas nous contenter de personnes génériques — nous pourrions utiliser des professeurs, des étudiants, qui sont des types un peu plus spécifiques de personnes. En POO, il est possible de créer de nouvelles classes à partir d'autres classes — ces <strong>classes filles</strong> nouvellement créées peuvent <strong>hériter</strong> des propriétés et des attributs de leur <strong>classe mère</strong>. Il est donc possible d'avoir des attributs partagés à l'ensemble des classes plutôt que de les dupliquer. Si besoin, il est possible d'ajouter des fonctions et attributs spécifiques sur chaque classe fille.</p> +Pour notre exemple, nous n'allons pas nous contenter de personnes génériques — nous pourrions utiliser des professeurs, des étudiants, qui sont des types un peu plus spécifiques de personnes. En POO, il est possible de créer de nouvelles classes à partir d'autres classes — ces **classes filles** nouvellement créées peuvent **hériter** des propriétés et des attributs de leur **classe mère**. Il est donc possible d'avoir des attributs partagés à l'ensemble des classes plutôt que de les dupliquer. Si besoin, il est possible d'ajouter des fonctions et attributs spécifiques sur chaque classe fille. -<p><img alt="Inheritance principle with French text for JS example" src="HeritageClasse.PNG"></p> + -<p>Cela s'avère très utile puisque les étudiants et les professeurs se ressemblent sur de nombreux aspects : ils ont un nom, un genre, un âge, il est donc utile de ne définir ces attributs qu'une seule fois. Il est aussi possible de redéfinir le même attribut dans différentes classes étant donné que l'attribut appartiendra à chaque fois à un nom d'espace différent. On pourra ainsi avoir différentes formes de salutations : « Hey, je m'appelle [prénom] » pour les étudiants ( « Hey je m'appelle Sam » ) tandis que les professeurs pourront dire quelque chose d'un peu plus formel comme « Bonjour, mon nom est [Titre][Nom] et j'enseigne [matière] » par exemple « Bonjour mon nom est M. Griffiths et j'enseigne la chimie ».</p> +Cela s'avère très utile puisque les étudiants et les professeurs se ressemblent sur de nombreux aspects : ils ont un nom, un genre, un âge, il est donc utile de ne définir ces attributs qu'une seule fois. Il est aussi possible de redéfinir le même attribut dans différentes classes étant donné que l'attribut appartiendra à chaque fois à un nom d'espace différent. On pourra ainsi avoir différentes formes de salutations : « Hey, je m'appelle \[prénom] » pour les étudiants ( « Hey je m'appelle Sam » ) tandis que les professeurs pourront dire quelque chose d'un peu plus formel comme « Bonjour, mon nom est \[Titre]\[Nom] et j'enseigne \[matière] » par exemple « Bonjour mon nom est M. Griffiths et j'enseigne la chimie ». -<div class="note"> -<p><strong>Note :</strong> On parle de <strong>polymorphisme</strong>, lorsque des objets réutilisent la même propriété, mais c'est juste pour info, vous embêtez pas.</p> -</div> +> **Note :** On parle de **polymorphisme**, lorsque des objets réutilisent la même propriété, mais c'est juste pour info, vous embêtez pas. -<p>Une fois la classe fille créée il est alors possible de l'instancier et de créer des objets. Par exemple :</p> +Une fois la classe fille créée il est alors possible de l'instancier et de créer des objets. Par exemple : -<p><img alt="Professor instantiation example for JS fr" src="InstanceProf.png"></p> + -<p>Dans la suite de l'article, nous nous intéresserons à la mise en œuvre de la programmation orientée objet (POO) au sein de JavaScript.</p> +Dans la suite de l'article, nous nous intéresserons à la mise en œuvre de la programmation orientée objet (POO) au sein de JavaScript. -<h2 id="Constructeurs_et_instances_dobjet">Constructeurs et instances d'objet</h2> +## Constructeurs et instances d'objet -<p>Certains disent que le JavaScript n'est pas vraiment un langage de programmation orienté objet — Il n'existe pas, en JavaScript d'élément <code>class</code> pour créer des classes alors que c'est le cas dans plusieurs langages orientés objet. JavaScript quant à lui, utilise des fonctions spéciales appelées <strong>constructeurs</strong> pour définir les objets et leurs propriétés. Ces constructeurs s'avèrent utiles, puisque bien souvent, nous ne savons pas combien d'objets nous allons définir, les constructeurs nous permettent de créer autant d'objets que nécessaire et d'y associer des données et des fonctions au fur et à mesure.</p> +Certains disent que le JavaScript n'est pas vraiment un langage de programmation orienté objet — Il n'existe pas, en JavaScript d'élément `class` pour créer des classes alors que c'est le cas dans plusieurs langages orientés objet. JavaScript quant à lui, utilise des fonctions spéciales appelées **constructeurs** pour définir les objets et leurs propriétés. Ces constructeurs s'avèrent utiles, puisque bien souvent, nous ne savons pas combien d'objets nous allons définir, les constructeurs nous permettent de créer autant d'objets que nécessaire et d'y associer des données et des fonctions au fur et à mesure. -<p>Lorsqu'un objet est instancié à partir d'une fonction constructeur, les fonctions de la classe ne sont pas copiées directement dans l'objet comme dans la plupart des langages orientés objet (OO). En JavaScript, les fonctions sont liées grâce à une chaîne de référence appelée chaîne prototype (voir <a href="/fr/docs/Learn/JavaScript/Objects/Object_prototypes">Prototypes Objet</a>). Il ne s'agit donc pas d'une véritable instanciation au sens strict puisque JavaScript utilise un mécanisme différent pour partager des fonctionnalités entre les objets.</p> +Lorsqu'un objet est instancié à partir d'une fonction constructeur, les fonctions de la classe ne sont pas copiées directement dans l'objet comme dans la plupart des langages orientés objet (OO). En JavaScript, les fonctions sont liées grâce à une chaîne de référence appelée chaîne prototype (voir [Prototypes Objet](/fr/docs/Learn/JavaScript/Objects/Object_prototypes)). Il ne s'agit donc pas d'une véritable instanciation au sens strict puisque JavaScript utilise un mécanisme différent pour partager des fonctionnalités entre les objets. -<div class="note"> -<p><strong>Note :</strong> Ne pas être un "langage classique de POO" n'est pas nécessairement un défaut. Comme nous le mentionnions au début de l'article, la POO peut très vite devenir compliquée et JavaScript, grâce à ses différences parvient à utiliser certains concepts avancés tout en restant abordable.</p> -</div> +> **Note :** Ne pas être un "langage classique de POO" n'est pas nécessairement un défaut. Comme nous le mentionnions au début de l'article, la POO peut très vite devenir compliquée et JavaScript, grâce à ses différences parvient à utiliser certains concepts avancés tout en restant abordable. -<p>Voyons comment créer des classes via les constructeurs et les utiliser pour instancier des objets en JavaScript. Nous allons commencer par faire une copie locale du fichier <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html">oojs.html</a> que nous avons vu dans notre premier article sur les objets.</p> +Voyons comment créer des classes via les constructeurs et les utiliser pour instancier des objets en JavaScript. Nous allons commencer par faire une copie locale du fichier [oojs.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html) que nous avons vu dans notre premier article sur les objets. -<h3 id="Un_exemple_simple">Un exemple simple</h3> +### Un exemple simple -<ol> - <li>Tout d'abord ; voyons comment définir une personne au travers d'une fonction classique. Vous pouvez ajouter l'exemple ci-dessous dans votre code existant : - <pre class="brush: js">function creerNouvellePersonne(nom) { - var obj = {}; - obj.nom = nom; - obj.salutation = function() { - alert('Salut ! Je m\'appelle ' + this.nom + '.'); - }; - return obj; -}</pre> - </li> - <li>Vous pouvez désormais créer une personne en appelant cette fonction, essayez en copiant les lignes suivantes dans la console JavaScript de votre navigateur : - <pre class="brush: js">var salva = creerNouvellePersonne('Salva'); -salva.nom; -salva.salutation();</pre> - Ça fonctionne bien, mais on peut améliorer notre exemple. Si l'on sait que l'on va créer un objet, pourquoi créer un objet vide pour l'utiliser ensuite ? Heureusement, JavaScript est là et possède des fonctions adaptées comme les constructeurs. À l'abordage !</li> - <li>Remplacez la fonction précédente par celle-ci : - <pre class="brush: js">function Personne(nom) { - this.nom = nom; - this.salutation = function() { - alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); - }; -}</pre> - </li> -</ol> +1. Tout d'abord ; voyons comment définir une personne au travers d'une fonction classique. Vous pouvez ajouter l'exemple ci-dessous dans votre code existant : + + ```js + function creerNouvellePersonne(nom) { + var obj = {}; + obj.nom = nom; + obj.salutation = function() { + alert('Salut ! Je m\'appelle ' + this.nom + '.'); + }; + return obj; + } + ``` + +2. Vous pouvez désormais créer une personne en appelant cette fonction, essayez en copiant les lignes suivantes dans la console JavaScript de votre navigateur : + + ```js + var salva = creerNouvellePersonne('Salva'); + salva.nom; + salva.salutation(); + ``` -<p>Le constructeur est l'équivalent JavaScript d'une classe. Il possède l'ensemble des fonctionnalités d'une fonction, cependant il ne renvoie rien et ne crée pas d'objet explicitement. Il se contente de définir les propriétés et les méthodes associées. Il y a aussi l'utilisation du mot-clé <code>this</code>, ce mot-clé sert au sein d'une instance qui sera créée à y faire référence, ainsi l'attribut nom sera, pour l'instance, égal au nom passé en argument de la fonction constructrice, la méthode <code>salutation</code><code>()</code> retournera elle aussi le nom passé en argument de la fonction constructrice.</p> + Ça fonctionne bien, mais on peut améliorer notre exemple. Si l'on sait que l'on va créer un objet, pourquoi créer un objet vide pour l'utiliser ensuite ? Heureusement, JavaScript est là et possède des fonctions adaptées comme les constructeurs. À l'abordage ! -<div class="note"> -<p><strong>Note :</strong> Les fonctions de type constructeur commencent généralement par une majuscule. Cette convention d'écriture permet de repérer les constructeurs plus facilement dans le code.</p> -</div> +3. Remplacez la fonction précédente par celle-ci : -<p>Comment pouvons-nous utiliser un constructeur ?</p> + ```js + function Personne(nom) { + this.nom = nom; + this.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + }; + } + ``` -<ol> - <li>Ajoutez les lignes suivantes au code déjà existant : - <pre class="brush: js">var personne1 = new Personne('Bob'); -var personne2 = new Personne('Sarah');</pre> - </li> - <li>Enregistrez votre code et relancez le dans votre navigateur puis essayez d'entrer les lignes suivantes dans la console : - <pre class="brush: js">personne1.nom -personne1.salutation() -personne2.nom -personne2.salutation()</pre> - </li> -</ol> +Le constructeur est l'équivalent JavaScript d'une classe. Il possède l'ensemble des fonctionnalités d'une fonction, cependant il ne renvoie rien et ne crée pas d'objet explicitement. Il se contente de définir les propriétés et les méthodes associées. Il y a aussi l'utilisation du mot-clé `this`, ce mot-clé sert au sein d'une instance qui sera créée à y faire référence, ainsi l'attribut nom sera, pour l'instance, égal au nom passé en argument de la fonction constructrice, la méthode ` salutation``() ` retournera elle aussi le nom passé en argument de la fonction constructrice. -<p>Pas mal ! Vous voyez désormais que nous avons deux nouveaux objets sur cette page, chaque objet étant stocké dans un espace de nom différent, pour y accéder il faut utiliser <code>personne1</code> et <code>personne2</code> pour préfixer les fonctions et attributs. Ce rangement permet de ne pas tout casser et de ne pas rentrer en collision avec d'autres fonctionnalités. Cependant les objets disposent du même attribut <code>nom</code> et de la même méthode <code>salutation()</code>. Heureusement, les attributs et les méthodes utilisent <code>this</code> ce qui leur permet d'utiliser les valeurs propres à chaque instance et de ne pas les mélanger.</p> +> **Note :** Les fonctions de type constructeur commencent généralement par une majuscule. Cette convention d'écriture permet de repérer les constructeurs plus facilement dans le code. -<p>Revoyons l'appel au constructeur :</p> +Comment pouvons-nous utiliser un constructeur ? -<pre class="brush: js">var personne1 = new Personne('Bob'); -var personne2 = new Personne('Sarah');</pre> +1. Ajoutez les lignes suivantes au code déjà existant : -<p>Dans chaque cas, le mot clé <code>new</code> est utilisé pour dire au navigateur que nous souhaitons définir une nouvelle instance, il est suivi du nom de la fonction que l'on utilise et de ses paramètres fournis entre parenthèses, le résultat est stocké dans une variable. Chaque instance est créée à partir de cette définition :</p> + ```js + var personne1 = new Personne('Bob'); + var personne2 = new Personne('Sarah'); + ``` -<pre class="brush: js">function Personne(nom) { +2. Enregistrez votre code et relancez le dans votre navigateur puis essayez d'entrer les lignes suivantes dans la console : + + ```js + personne1.nom + personne1.salutation() + personne2.nom + personne2.salutation() + ``` + +Pas mal ! Vous voyez désormais que nous avons deux nouveaux objets sur cette page, chaque objet étant stocké dans un espace de nom différent, pour y accéder il faut utiliser `personne1` et `personne2` pour préfixer les fonctions et attributs. Ce rangement permet de ne pas tout casser et de ne pas rentrer en collision avec d'autres fonctionnalités. Cependant les objets disposent du même attribut `nom` et de la même méthode `salutation()`. Heureusement, les attributs et les méthodes utilisent `this` ce qui leur permet d'utiliser les valeurs propres à chaque instance et de ne pas les mélanger. + +Revoyons l'appel au constructeur : + +```js +var personne1 = new Personne('Bob'); +var personne2 = new Personne('Sarah'); +``` + +Dans chaque cas, le mot clé `new` est utilisé pour dire au navigateur que nous souhaitons définir une nouvelle instance, il est suivi du nom de la fonction que l'on utilise et de ses paramètres fournis entre parenthèses, le résultat est stocké dans une variable. Chaque instance est créée à partir de cette définition : + +```js +function Personne(nom) { this.nom = nom; this.salutation = function() { alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); }; -}</pre> +} +``` -<p>Une fois les objets créés, les variables <code>personne1</code> et <code>personne2</code> contiennent les objets suivants :</p> +Une fois les objets créés, les variables `personne1` et `personne2` contiennent les objets suivants : -<pre class="brush: js">{ +```js +{ nom: 'Bob', salutation: function() { alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); @@ -164,116 +183,127 @@ var personne2 = new Personne('Sarah');</pre> salutation: function() { alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); } -}</pre> +} +``` -<p>On peut remarquer qu'à chaque appel de notre fonction constructrice nous définissons <code>salutation()</code> à chaque fois. Cela peut être évité via la définition de la fonction au sein du prototype, ce que nous verrons plus tard.</p> +On peut remarquer qu'à chaque appel de notre fonction constructrice nous définissons `salutation()` à chaque fois. Cela peut être évité via la définition de la fonction au sein du prototype, ce que nous verrons plus tard. -<h3 id="Créons_une_version_finalisée_de_notre_constructeur">Créons une version finalisée de notre constructeur</h3> +### Créons une version finalisée de notre constructeur -<p>L'exemple que nous avons utilisé jusqu'à présent était destiné à aborder les notions de base des constructeurs. Créons un constructeur digne de ce nom pour notre fonction constructrice <code>Personne()</code>.</p> +L'exemple que nous avons utilisé jusqu'à présent était destiné à aborder les notions de base des constructeurs. Créons un constructeur digne de ce nom pour notre fonction constructrice `Personne()`. -<ol> - <li>Vous pouvez retirer le code que vous aviez ajouté précédemment pour le remplacer par le constructeur suivant, c'est la même fonction, ça reste un constructeur, nous avons juste ajouté quelques détails : - <pre class="brush: js">function Personne(prenom, nom, age, genre, interets) { - this.nom = { - prenom, - nom - }; - this.age = age; - this.genre = genre; - this.interets = interets; - this.bio = function() { - alert(this.nom.prenom + ' ' + this.nom.nom + ' a ' + this.age + ' ans. Il aime ' + this.interets[0] + ' et ' + this.interets[1] + '.'); - }; - this.salutation = function() { - alert('Bonjour ! Je m\'appelle ' + this.nom.prenom + '.'); - }; -};</pre> - </li> - <li>Vous pouvez ajouter la ligne ci-dessous pour créer une instance à partir du constructeur : - <pre class="brush: js">var personne1 = new Personne('Bob', 'Smith', 32, 'homme', ['musique', 'ski']);</pre> - </li> -</ol> +1. Vous pouvez retirer le code que vous aviez ajouté précédemment pour le remplacer par le constructeur suivant, c'est la même fonction, ça reste un constructeur, nous avons juste ajouté quelques détails : + + ```js + function Personne(prenom, nom, age, genre, interets) { + this.nom = { + prenom, + nom + }; + this.age = age; + this.genre = genre; + this.interets = interets; + this.bio = function() { + alert(this.nom.prenom + ' ' + this.nom.nom + ' a ' + this.age + ' ans. Il aime ' + this.interets[0] + ' et ' + this.interets[1] + '.'); + }; + this.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom.prenom + '.'); + }; + }; + ``` -<p>Vous pouvez accéder aux fonctions des objets instanciés de la même manière qu'avant :</p> +2. Vous pouvez ajouter la ligne ci-dessous pour créer une instance à partir du constructeur : -<pre class="brush: js">personne1['age'] + ```js + var personne1 = new Personne('Bob', 'Smith', 32, 'homme', ['musique', 'ski']); + ``` + +Vous pouvez accéder aux fonctions des objets instanciés de la même manière qu'avant : + +```js +personne1['age'] personne1.interets[1] personne1.bio() -// etc.</pre> +// etc. +``` -<div class="note"> -<p><strong>Note :</strong> Si vous avez du mal à faire fonctionner cet exemple, vous pouvez comparez votre travail avec notre version (voir <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html">oojs-class-finished.html</a> (vous pouvez aussi jeter un œil à la <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html">démo</a>)</p> -</div> +> **Note :** Si vous avez du mal à faire fonctionner cet exemple, vous pouvez comparez votre travail avec notre version (voir [oojs-class-finished.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html) (vous pouvez aussi jeter un œil à la [démo](https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html)) -<h3 id="Exercices">Exercices</h3> +### Exercices -<p>Vous pouvez démarrer en instanciant de nouveaux objets puis en essayant de modifier et d'accéder à leurs attributs respectifs.</p> +Vous pouvez démarrer en instanciant de nouveaux objets puis en essayant de modifier et d'accéder à leurs attributs respectifs. -<p>D'autre part, il y a quelques améliorations possibles pour notre méthode <code>bio().</code> En effet elle affiche systématiquement le pronom 'il', même si votre personne est une femme ou bien préfère se définir par un autre genre. De plus, la biographie n'inclut que deux passions, même s'il y en a plus dans la liste. Essayez d'améliorer cette méthode. Vous pourrez mettre votre code à l'intérieur du constructeur (vous aurez probablement besoin de quelques structures conditionnelles et d'une boucle). Réflechissez à la syntaxe des phrases qui devra s'adapter en fonction du genre et du nombre de passions listées.</p> +D'autre part, il y a quelques améliorations possibles pour notre méthode `bio().` En effet elle affiche systématiquement le pronom 'il', même si votre personne est une femme ou bien préfère se définir par un autre genre. De plus, la biographie n'inclut que deux passions, même s'il y en a plus dans la liste. Essayez d'améliorer cette méthode. Vous pourrez mettre votre code à l'intérieur du constructeur (vous aurez probablement besoin de quelques structures conditionnelles et d'une boucle). Réflechissez à la syntaxe des phrases qui devra s'adapter en fonction du genre et du nombre de passions listées. -<div class="note"> -<p><strong>Note :</strong> Si vous êtes bloqués, nous avons mis une réponse possible sur notre dépôt <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">GitHub </a>(<a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">la démo</a>) —tentez d'abord l'aventure avant d'aller regarder la réponse !</p> -</div> +> **Note :** Si vous êtes bloqués, nous avons mis une réponse possible sur notre dépôt [GitHub ](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html)([la démo](https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html)) —tentez d'abord l'aventure avant d'aller regarder la réponse ! -<h2 id="Dautres_manières_dinstancier_des_objets">D'autres manières d'instancier des objets</h2> +## D'autres manières d'instancier des objets -<p>Jusque là nous n'avons abordé que deux manières différentes pour créer une instance d'objet, la déclarer de manière explicite et en utilisant le constructeur.</p> +Jusque là nous n'avons abordé que deux manières différentes pour créer une instance d'objet, la déclarer de manière explicite et en utilisant le constructeur. -<p>Elles sont toutes les deux valables, mais il en existe d'autres. Afin que vous les reconnaissiez lorsque vous vous baladez sur le Web, nous en avons listées quelques unes.</p> +Elles sont toutes les deux valables, mais il en existe d'autres. Afin que vous les reconnaissiez lorsque vous vous baladez sur le Web, nous en avons listées quelques unes. -<h3 id="Le_constructeur_Object">Le constructeur Object()</h3> +### Le constructeur Object() -<p>Vous pouvez en premier lieu utiliser le constructeur <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object()</a></code> pour créer un nouvel objet. Oui, même les objets génériques ont leur propre constructeur, qui génère un objet vide.</p> +Vous pouvez en premier lieu utiliser le constructeur [`Object()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object) pour créer un nouvel objet. Oui, même les objets génériques ont leur propre constructeur, qui génère un objet vide. -<ol> - <li>Essayez la commande suivante dans la console JavaScript de votre navigateur : - <pre class="brush: js">var personne1 = new Object();</pre> - </li> - <li>On stocke ainsi un objet vide dans la variable personne1. Vous pouvez ensuite ajouter des attributs et des méthodes à cet objet en utilisant la notation point ou parenthèses comme vous le souhaitez. - <pre class="brush: js">personne1.nom = 'Chris'; -personne1['age'] = 38; -personne1.salutation = function() { - alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); -};</pre> - </li> - <li>Vous pouvez aussi passer un objet en paramètre du constructeur <code>Object()</code>, afin de prédéfinir certains attributs et méthodes. - <pre class="brush: js">var personne1 = new Object({ - nom: 'Chris', - age: 38, - salutation: function() { - alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); - } -});</pre> - </li> -</ol> +1. Essayez la commande suivante dans la console JavaScript de votre navigateur : + + ```js + var personne1 = new Object(); + ``` + +2. On stocke ainsi un objet vide dans la variable personne1. Vous pouvez ensuite ajouter des attributs et des méthodes à cet objet en utilisant la notation point ou parenthèses comme vous le souhaitez. + + ```js + personne1.nom = 'Chris'; + personne1['age'] = 38; + personne1.salutation = function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + }; + ``` + +3. Vous pouvez aussi passer un objet en paramètre du constructeur `Object()`, afin de prédéfinir certains attributs et méthodes. + + ```js + var personne1 = new Object({ + nom: 'Chris', + age: 38, + salutation: function() { + alert('Bonjour ! Je m\'appelle ' + this.nom + '.'); + } + }); + ``` + +### Via la méthode create() + +Les constructeurs permettent de structurer le code : vous pouvez avoir l'ensemble de vos constructeurs au même endroit et ensuite créer les instances suivant vos besoins, en identifiant clairement leur origine. + +Cependant, on peut vouloir créér des instances d'un objet, sans forcément définir un constructeur au préalable. (Particulierement si l'on a peu d'instances de cet object). JavaScript intègre directement une méthode appelée [`create()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create) qui rend cela possible. Elle permet d'instancier un objet à partir d'un objet existant . -<h3 id="Via_la_méthode_create">Via la méthode create()</h3> +1. Essayez d'ajouter la ligne suivante dans votre console JavaScript : -<p>Les constructeurs permettent de structurer le code : vous pouvez avoir l'ensemble de vos constructeurs au même endroit et ensuite créer les instances suivant vos besoins, en identifiant clairement leur origine. </p> + ```js + var personne2 = Object.create(personne1); + ``` -<p>Cependant, on peut vouloir créér des instances d'un objet, sans forcément définir un constructeur au préalable. (Particulierement si l'on a peu d'instances de cet object). JavaScript intègre directement une méthode appelée <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> qui rend cela possible. Elle permet d'instancier un objet à partir d'un objet existant .</p> +2. Maintenant : -<ol> - <li>Essayez d'ajouter la ligne suivante dans votre console JavaScript : - <pre class="brush: js">var personne2 = Object.create(personne1);</pre> - </li> - <li>Maintenant : - <pre class="brush: js">personne2.nom -personne2.salutation()</pre> - </li> -</ol> + ```js + personne2.nom + personne2.salutation() + ``` -<p><code>personne2</code> a été créée à partir de <code>personne1</code> — et elle possède les mêmes propriétés. </p> +`personne2` a été créée à partir de `personne1` — et elle possède les mêmes propriétés. -<p>L'inconvénient de <code>create()</code> est qu'elle n'est pas supportée par IE8. Ainsi, utiliser les constructeurs peut s'avérer plus judicieux lorsqu'il s'agit de supporter les anciens navigateurs Web.</p> +L'inconvénient de `create()` est qu'elle n'est pas supportée par IE8. Ainsi, utiliser les constructeurs peut s'avérer plus judicieux lorsqu'il s'agit de supporter les anciens navigateurs Web. -<p>Nous verrons les détails et les effets de <code>create()</code> plus tard.</p> +Nous verrons les détails et les effets de `create()` plus tard. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Cet article vous a donné un aperçu simplifié de la programmation orientée objet. Tout n'y a pas été détaillé mais ça vous permet de vous faire une idée. Nous avons vu comment JavaScript s'appuyait sur un certain nombre de principes orienté objet tout en ayant un certain nombre de particularités. Nous avons aussi vu comment implémenter des classes en JavaScript via la fonction constructeur ainsi que les différentes manières de générer des instances d'objets.</p> +Cet article vous a donné un aperçu simplifié de la programmation orientée objet. Tout n'y a pas été détaillé mais ça vous permet de vous faire une idée. Nous avons vu comment JavaScript s'appuyait sur un certain nombre de principes orienté objet tout en ayant un certain nombre de particularités. Nous avons aussi vu comment implémenter des classes en JavaScript via la fonction constructeur ainsi que les différentes manières de générer des instances d'objets. -<p>Dans le prochain article, nous explorerons le monde des objets prototypes en JavaScript.</p> +Dans le prochain article, nous explorerons le monde des objets prototypes en JavaScript. -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}} diff --git a/files/fr/learn/javascript/objects/object_building_practice/index.md b/files/fr/learn/javascript/objects/object_building_practice/index.md index 7028077f88..858880b11b 100644 --- a/files/fr/learn/javascript/objects/object_building_practice/index.md +++ b/files/fr/learn/javascript/objects/object_building_practice/index.md @@ -13,305 +13,315 @@ tags: translation_of: Learn/JavaScript/Objects/Object_building_practice original_slug: Learn/JavaScript/Objects/la_construction_d_objet_en_pratique --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</div> - -<p>Dans l'article précédent, nous avons passé en revue l'essentiel de la théorie de l'objet Javascript et sa syntaxe détaillée, vous donnant ainsi des bases solides sur lesquelles commencer. Dans le présent article nous plongeons dans un exercice pratique afin d'accroître votre savoir-faire dans la construction d'objets entièrement personnalisés donnant un résultat plutôt amusant et très coloré.</p> +Dans l'article précédent, nous avons passé en revue l'essentiel de la théorie de l'objet Javascript et sa syntaxe détaillée, vous donnant ainsi des bases solides sur lesquelles commencer. Dans le présent article nous plongeons dans un exercice pratique afin d'accroître votre savoir-faire dans la construction d'objets entièrement personnalisés donnant un résultat plutôt amusant et très coloré. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Pré-requis :</th> - <td> - <p>Connaissance basique de l'informatique, une compréhension basique du HTML et du CSS, une familiarité avec les bases du JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Les blocs de construction</a>) et les bases de la programmation objet en JavaScript (voir <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>). </p> - </td> - </tr> - <tr> - <th scope="row">Objectif :</th> - <td> - <p>Acquérir plus de pratique dans l'utilisation des objets et des techniques orientées objet dans un contexte "monde réel".</p> - </td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td> + <p> + Connaissance basique de l'informatique, une compréhension basique du + HTML et du CSS, une familiarité avec les bases du JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et + <a href="/fr/docs/Learn/JavaScript/Building_blocks" + >Les blocs de construction</a + >) et les bases de la programmation objet en JavaScript (voir <a + href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction" + >Introduction aux objets</a + >). + </p> + </td> + </tr> + <tr> + <th scope="row">Objectif :</th> + <td> + <p> + Acquérir plus de pratique dans l'utilisation des objets et des + techniques orientées objet dans un contexte "monde réel". + </p> + </td> + </tr> + </tbody> </table> -<h2 id="Faisons_bondir_quelques_balles">Faisons bondir quelques balles</h2> - -<p>Dans cet article, nous écrirons une démo classique de "balles bondissantes", pour vous montrer à quel point les objets peuvent être utiles en JavaScript. Nos petites balles bondiront partout sur notre écran et changeront de couleurs lorsqu'elles se toucheront. L'exemple finalisé ressemblera un peu à ceci : </p> +## Faisons bondir quelques balles -<p><img alt="" src="bouncing-balls.png"></p> +Dans cet article, nous écrirons une démo classique de "balles bondissantes", pour vous montrer à quel point les objets peuvent être utiles en JavaScript. Nos petites balles bondiront partout sur notre écran et changeront de couleurs lorsqu'elles se toucheront. L'exemple finalisé ressemblera un peu à ceci : -<ol> -</ol> + -<p>Cet exemple utilise l'<a href="/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">API Canvas </a> pour dessiner les balles sur l'écran, et l'API <a href="/fr/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> pour animer l'ensemble de l'affichage — Nul besoin d'avoir une connaissance préalable de ces APIs, nous expérons qu'une fois cet article terminé, vous aurez envie d'en faire une exploration approfondie. Tout le long du parcours nous utiliserons certains objets formidables et vous montrerons nombre de techniques sympathiques comme des balles bondissantes sur les murs et la vérification de balles qui s'entrechoquent (encore connue sous l'appelation <strong>détection de collision</strong>).</p> +Cet exemple utilise l'[API Canvas ](/fr/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics) pour dessiner les balles sur l'écran, et l'API [requestAnimationFrame](/fr/docs/Web/API/window/requestAnimationFrame) pour animer l'ensemble de l'affichage — Nul besoin d'avoir une connaissance préalable de ces APIs, nous expérons qu'une fois cet article terminé, vous aurez envie d'en faire une exploration approfondie. Tout le long du parcours nous utiliserons certains objets formidables et vous montrerons nombre de techniques sympathiques comme des balles bondissantes sur les murs et la vérification de balles qui s'entrechoquent (encore connue sous l'appelation **détection de collision**). -<p>Pour commencer, faites des copies locales de nos fichiers <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index.html">index.html</a></code>, <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a></code>, et <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main.js">main.js</a></code>. Ces fichiers contiennent respectivement :</p> +Pour commencer, faites des copies locales de nos fichiers [`index.html`](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index.html), [`style.css`](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css), et [`main.js`](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main.js). Ces fichiers contiennent respectivement : -<ol> - <li>Un document HTML très simple contenant un élément {{HTMLElement("h1")}} , un élément {{HTMLElement("canvas")}} pour dessiner nos balles dessus et des élements pour appliquer notre CSS et notre JavaScript à notre HTML ;</li> - <li>Quelques styles très simples qui servent principalement à mettre en forme et placer le <code><h1></code>, et se débarasser de toutes barres de défilement ou de marges autour du pourtour de notre page (afin que cela paraisse plus sympathique et élégant) ;</li> - <li>Un peu de JavaScript qui sert à paramétrer l'élément <code><canvas></code> et fournir les fonctions globalles que nous utiliserons.</li> -</ol> +1. Un document HTML très simple contenant un élément {{HTMLElement("h1")}} , un élément {{HTMLElement("canvas")}} pour dessiner nos balles dessus et des élements pour appliquer notre CSS et notre JavaScript à notre HTML ; +2. Quelques styles très simples qui servent principalement à mettre en forme et placer le `<h1>`, et se débarasser de toutes barres de défilement ou de marges autour du pourtour de notre page (afin que cela paraisse plus sympathique et élégant) ; +3. Un peu de JavaScript qui sert à paramétrer l'élément `<canvas>` et fournir les fonctions globalles que nous utiliserons. -<p>La première partie du script ressemble à ceci :</p> +La première partie du script ressemble à ceci : -<pre class="brush: js">const canvas = document.querySelector('canvas'); +```js +const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const width = canvas.width = window.innerWidth; -const height = canvas.height = window.innerHeight;</pre> +const height = canvas.height = window.innerHeight; +``` -<p>Ce script prend une référence à l'élément <code><canvas></code> et ensuite invoque la méthode <code><a href="/fr/docs/Web/API/HTMLCanvasElement/getContext">getContext()</a></code> sur lui, nous donnant ainsi un contexte sur lequel nous pouvons commencer à dessiner. La variable résultante (<code>ctx</code>) est l'objet qui représente directement la surface du Canvas où nous pouvons dessiner et qui nous permet de dessiner des formes 2D sur ce dernier. </p> +Ce script prend une référence à l'élément `<canvas>` et ensuite invoque la méthode [`getContext()`](/fr/docs/Web/API/HTMLCanvasElement/getContext) sur lui, nous donnant ainsi un contexte sur lequel nous pouvons commencer à dessiner. La variable résultante (`ctx`) est l'objet qui représente directement la surface du Canvas où nous pouvons dessiner et qui nous permet de dessiner des formes 2D sur ce dernier. -<p>Après, nous configurons les variables <code>width</code> (largeur) et <code>height</code>(hauteur), et la largeur et la hauteur de l'élément canvas (représentés par les propriétés <code>canvas.width</code> et <code>canvas.height</code> ) afin qu'elles soient identiques à la fenêtre du navigateur (la surface sur laquelle apparaît la page web— Ceci peut être tiré des propriétés {{domxref("Window.innerWidth")}} et {{domxref("Window.innerHeight")}}).</p> +Après, nous configurons les variables `width` (largeur) et `height`(hauteur), et la largeur et la hauteur de l'élément canvas (représentés par les propriétés `canvas.width` et `canvas.height` ) afin qu'elles soient identiques à la fenêtre du navigateur (la surface sur laquelle apparaît la page web— Ceci peut être tiré des propriétés {{domxref("Window.innerWidth")}} et {{domxref("Window.innerHeight")}}). -<p>Vous verrez qu'ici nous enchaînons les assignations des valeurs des différentes variables ensemble à des fins de rapidité. Ceci est parfaitement autorisé.</p> +Vous verrez qu'ici nous enchaînons les assignations des valeurs des différentes variables ensemble à des fins de rapidité. Ceci est parfaitement autorisé. -<p>Le dernier morceau du script ressemble à ceci :</p> +Le dernier morceau du script ressemble à ceci : -<pre class="brush: js">function random(min, max) { +```js +function random(min, max) { var num = Math.floor(Math.random() * (max - min + 1)) + min; return num; -}</pre> +} +``` -<p>Cette fonction prend deux nombres comme arguments, et renvoie un nombre compris entre les deux. </p> +Cette fonction prend deux nombres comme arguments, et renvoie un nombre compris entre les deux. -<h2 id="Modéliser_une_balle_dans_notre_programme">Modéliser une balle dans notre programme</h2> +## Modéliser une balle dans notre programme -<p>Notre programme met en œuvre beaucoup de balles bondissant partout sur l'écran. Comme nos balles se comporteront toutes de la même façon, cela semble tout à fait sensé de les représenter avec un objet. Commençons donc en ajoutant le constructeur suivant à la fin de notre code.</p> +Notre programme met en œuvre beaucoup de balles bondissant partout sur l'écran. Comme nos balles se comporteront toutes de la même façon, cela semble tout à fait sensé de les représenter avec un objet. Commençons donc en ajoutant le constructeur suivant à la fin de notre code. -<pre class="brush: js">function Ball(x, y, velX, velY, color, size) { +```js +function Ball(x, y, velX, velY, color, size) { this.x = x; this.y = y; this.velX = velX; this.velY = velY; this.color = color; this.size = size; -}</pre> +} +``` -<p>Ici, nous incluons des paramètres qui définissent des propriétés dont chaque balle aura besoin pour fonctionner dans notre programme :</p> +Ici, nous incluons des paramètres qui définissent des propriétés dont chaque balle aura besoin pour fonctionner dans notre programme : -<ul> - <li>Les coordonnées <code>x</code> et <code>y</code> — les coordonnées verticales et horizontales où la balle débutera sur l'écran. Ceci peut se trouver entre 0 (coin à gauche en haut) et la valeur de la hauteur et de la largeur de la fenêtre du navigateur (coin en bas à droite).</li> - <li>Une vitesse horizontale et verticale (<code>velX</code> et <code>velY</code>) — à chaque balle est attribuée une vitesse horizontale et verticale; en termes réels ces valeurs seront régulièrement ajoutéés aux valeurs de la coordonnée <code>x</code>/<code>y</code> quand nous commencerons à animer les balles, afin de les faire bouger d'autant sur chaque vignette (frame).</li> - <li><code>color</code> — chaque balle a une couleur.</li> - <li><code>size</code> — chaque balle a une taille — ce sera son rayon mesuré en pixels.</li> -</ul> +- Les coordonnées `x` et `y` — les coordonnées verticales et horizontales où la balle débutera sur l'écran. Ceci peut se trouver entre 0 (coin à gauche en haut) et la valeur de la hauteur et de la largeur de la fenêtre du navigateur (coin en bas à droite). +- Une vitesse horizontale et verticale (`velX` et `velY`) — à chaque balle est attribuée une vitesse horizontale et verticale; en termes réels ces valeurs seront régulièrement ajoutéés aux valeurs de la coordonnée `x`/`y` quand nous commencerons à animer les balles, afin de les faire bouger d'autant sur chaque vignette (frame). +- `color` — chaque balle a une couleur. +- `size` — chaque balle a une taille — ce sera son rayon mesuré en pixels. -<p>Ceci règle le problème des propriétés mais qu'en est il des méthodes ? Nous voulons maintenant amener nos balles à faire quelque chose dans notre programme.</p> +Ceci règle le problème des propriétés mais qu'en est il des méthodes ? Nous voulons maintenant amener nos balles à faire quelque chose dans notre programme. -<h3 id="Dessiner_la_balle">Dessiner la balle</h3> +### Dessiner la balle -<p>En premier lieu ajoutez la méthode <code>draw()</code> au <code>prototype</code> de <code>Ball()</code> :</p> +En premier lieu ajoutez la méthode `draw()` au `prototype` de `Ball()` : -<pre class="brush: js">Ball.prototype.draw = function() { +```js +Ball.prototype.draw = function() { ctx.beginPath(); ctx.fillStyle = this.color; ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); ctx.fill(); -}</pre> - -<p>En utilisant cette fonction, nous pouvons dire à notre balle de se dessiner sur l'écran en appelant une série de membres du contexte 2D du canvas que nous avons défini plus tôt (<code>ctx</code>). Le contexte est comme le papier et maintenant nous allons demander à notre stylo d'y dessiner quelque chose :</p> - -<ul> - <li>Premièrement, nous utilisons <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> pour spécifier que nous voulons dessiner une forme sur le papier.</li> - <li>Ensuite, nous utilisons <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> pour définir de quelle couleur nous voulons que la forme soit — nous lui attribuons la valeur de la propriété <code>color</code> de notre balle.</li> - <li>Après, nous utilisons la méthode <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/arc">arc()</a></code> pour tracer une forme en arc sur le papier. Ses paramètres sont : - <ul> - <li>Les positions <code>x</code> et <code>y</code> du centre de l'arc — nous specifions donc les propriétés <code>x</code> et <code>y </code>de notre balle.</li> - <li>Le rayon de l'arc — nous specifions la propriété <code>size</code> de notre balle.</li> - <li>Les deux derniers paramètres spécifient l'intervalle de début et de fin en degrés pour dessiner l'arc. Ici nous avons spécifié 0 degrés et <code>2 * PI </code>qui est l'équivalent de 360 degrés en radians (malheureusement vous êtes obligés de spécifier ces valeurs en radians et non en degrés). Cela nous donne un cercle complet. Si vous aviez spécifié seulement <code>1 * PI</code>, vous auriez eu un demi-cercle (180 degrés).</li> - </ul> - </li> - <li>En dernière position nous utilisons la méthode <code><a href="/fr/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> qui est habituellement utilisée pour spécifier que nous souhaitons mettre fin au dessin que nous avons commencé avec <code>beginPath()</code>, et remplir la surface délimitée avec la couleur que nous avions spécifiée plus tôt avec <code>fillStyle</code>.</li> -</ul> - -<p>Vous pouvez déjà commencer à tester votre objet.</p> - -<ol> - <li>Sauvegardez le code et chargez le fichier html dans un navigateur.</li> - <li>Ouvrez la console JavaScript du navigateur et actualisez la page afin que la taille du canvas change et prenne la petite taille restante de la fenêtre lorsque la console est ouverte.</li> - <li>Tapez dans la console ce qui suit afin de créer une nouvelle instance de balle : - <pre class="brush: js">let testBall = new Ball(50, 100, 4, 4, 'blue', 10);</pre> - </li> - <li>Essayez d'appeler ses membres : - <pre class="brush: js">testBall.x -testBall.size -testBall.color -testBall.draw()</pre> - </li> - <li>Lorsque vous entrerez la dernière ligne, vous devriez voir la balle se dessiner quelque part sur votre canvas.</li> -</ol> - -<h3 id="Mettre_à_jour_les_données_de_la_balle">Mettre à jour les données de la balle</h3> - -<p>Nous pouvons dessiner la balle dans n'importe quelle position, mais actuellement pour commencer à la bouger nous aurons besoin d'une sorte de fonction de mise à jour. Insérez donc le code suivant à la fin de votre fichier JavaScript pour ajouter une méthode <code>update()</code> au <code>prototype</code> de <code>Ball()</code>:</p> - -<pre class="brush: js">Ball.prototype.update = function() { - if ((this.x + this.size) >= width) { +} +``` + +En utilisant cette fonction, nous pouvons dire à notre balle de se dessiner sur l'écran en appelant une série de membres du contexte 2D du canvas que nous avons défini plus tôt (`ctx`). Le contexte est comme le papier et maintenant nous allons demander à notre stylo d'y dessiner quelque chose : + +- Premièrement, nous utilisons [`beginPath()`](/fr/docs/Web/API/CanvasRenderingContext2D/beginPath) pour spécifier que nous voulons dessiner une forme sur le papier. +- Ensuite, nous utilisons [`fillStyle`](/fr/docs/Web/API/CanvasRenderingContext2D/fillStyle) pour définir de quelle couleur nous voulons que la forme soit — nous lui attribuons la valeur de la propriété `color` de notre balle. +- Après, nous utilisons la méthode [`arc()`](/fr/docs/Web/API/CanvasRenderingContext2D/arc) pour tracer une forme en arc sur le papier. Ses paramètres sont : + + - Les positions `x` et `y` du centre de l'arc — nous specifions donc les propriétés `x` et `y `de notre balle. + - Le rayon de l'arc — nous specifions la propriété `size` de notre balle. + - Les deux derniers paramètres spécifient l'intervalle de début et de fin en degrés pour dessiner l'arc. Ici nous avons spécifié 0 degrés et `2 * PI `qui est l'équivalent de 360 degrés en radians (malheureusement vous êtes obligés de spécifier ces valeurs en radians et non en degrés). Cela nous donne un cercle complet. Si vous aviez spécifié seulement `1 * PI`, vous auriez eu un demi-cercle (180 degrés). + +- En dernière position nous utilisons la méthode [`fill()`](/fr/docs/Web/API/CanvasRenderingContext2D/fill) qui est habituellement utilisée pour spécifier que nous souhaitons mettre fin au dessin que nous avons commencé avec `beginPath()`, et remplir la surface délimitée avec la couleur que nous avions spécifiée plus tôt avec `fillStyle`. + +Vous pouvez déjà commencer à tester votre objet. + +1. Sauvegardez le code et chargez le fichier html dans un navigateur. +2. Ouvrez la console JavaScript du navigateur et actualisez la page afin que la taille du canvas change et prenne la petite taille restante de la fenêtre lorsque la console est ouverte. +3. Tapez dans la console ce qui suit afin de créer une nouvelle instance de balle : + + ```js + let testBall = new Ball(50, 100, 4, 4, 'blue', 10); + ``` + +4. Essayez d'appeler ses membres : + + ```js + testBall.x + testBall.size + testBall.color + testBall.draw() + ``` + +5. Lorsque vous entrerez la dernière ligne, vous devriez voir la balle se dessiner quelque part sur votre canvas. + +### Mettre à jour les données de la balle + +Nous pouvons dessiner la balle dans n'importe quelle position, mais actuellement pour commencer à la bouger nous aurons besoin d'une sorte de fonction de mise à jour. Insérez donc le code suivant à la fin de votre fichier JavaScript pour ajouter une méthode `update()` au `prototype` de `Ball()`: + +```js +Ball.prototype.update = function() { + if ((this.x + this.size) >= width) { this.velX = -(this.velX); } - if ((this.x - this.size) <= 0) { + if ((this.x - this.size) <= 0) { this.velX = -(this.velX); } - if ((this.y + this.size) >= height) { + if ((this.y + this.size) >= height) { this.velY = -(this.velY); } - if ((this.y - this.size) <= 0) { + if ((this.y - this.size) <= 0) { this.velY = -(this.velY); } this.x += this.velX; this.y += this.velY; -}</pre> +} +``` -<p>Les quatre premières parties de la fonction vérifient si la balle a atteint le rebord du canvas. Si c'est le cas, nous inversons la polarité de la vitesse appropriée pour faire bouger la balle dans le sens opposé. Donc par exemple, si la balle se déplaçait vers le haut (positif <code>velY</code>) alors la vitesse verticale est changée afin qu'elle commence à bouger plutôt vers le bas (negatif <code>velY</code>).</p> +Les quatre premières parties de la fonction vérifient si la balle a atteint le rebord du canvas. Si c'est le cas, nous inversons la polarité de la vitesse appropriée pour faire bouger la balle dans le sens opposé. Donc par exemple, si la balle se déplaçait vers le haut (positif `velY`) alors la vitesse verticale est changée afin qu'elle commence à bouger plutôt vers le bas (negatif `velY`). -<p>Dans les quatre cas nous :</p> +Dans les quatre cas nous : -<ul> - <li>Verifions si la coordonnée <code>x</code> est plus grande que la largeur du canvas (la balle est en train de sortir du côté droit).</li> - <li>Verifions si la coordonnée <code>x</code> est plus petite que 0 (la balle est en train de sortir du côté gauche).</li> - <li>Verifions si la coordonnée <code>y</code> est plus grande que la hauteur du canvas (la balle est en train de sortir par le bas).</li> - <li>Verifions si la coordonnée <code>y</code> est plus petite que 0 (la balle est en train de sortir par le haut).</li> -</ul> +- Verifions si la coordonnée `x` est plus grande que la largeur du canvas (la balle est en train de sortir du côté droit). +- Verifions si la coordonnée `x` est plus petite que 0 (la balle est en train de sortir du côté gauche). +- Verifions si la coordonnée `y` est plus grande que la hauteur du canvas (la balle est en train de sortir par le bas). +- Verifions si la coordonnée `y` est plus petite que 0 (la balle est en train de sortir par le haut). -<p>Dans chaque cas, nous incluons la taille <code>size</code> de la balle dans les calculs parce que les coordonnées <code>x</code>/<code>y</code> sont situées au centre de la balle mais nous voulons que le pourtour de la balle rebondisse sur le rebord — nous ne voulons pas que la balle sorte à moité hors de l'écran avant de commencer à rebondir vers l'arrière.</p> +Dans chaque cas, nous incluons la taille `size` de la balle dans les calculs parce que les coordonnées `x`/`y` sont situées au centre de la balle mais nous voulons que le pourtour de la balle rebondisse sur le rebord — nous ne voulons pas que la balle sorte à moité hors de l'écran avant de commencer à rebondir vers l'arrière. -<p>Les deux dernières lignes ajoutent la valeur <code>velX</code> à la coordonnée <code>x</code> et la valeur <code>velY</code> à la coordonnée <code>y</code> — la balle est en effet mise en mouvement chaque fois que cette méthode est invoquée.</p> +Les deux dernières lignes ajoutent la valeur `velX` à la coordonnée `x` et la valeur `velY` à la coordonnée `y` — la balle est en effet mise en mouvement chaque fois que cette méthode est invoquée. -<p>Cela suffira pour l'instant, passons à l'animation !</p> +Cela suffira pour l'instant, passons à l'animation ! -<h2 id="Animer_la_balle">Animer la balle</h2> +## Animer la balle -<p>Maintenant, rendons cela amusant. Nous allons commencer à ajouter des balles au canvas et à les animer.</p> +Maintenant, rendons cela amusant. Nous allons commencer à ajouter des balles au canvas et à les animer. -<ol> - <li>Tout d'abord, nous avons besoin d'un endroit où stocker toutes nos balles. Le tableau suivant fera ce travail — ajoutez-le au bas de votre code maintenant : +1. Tout d'abord, nous avons besoin d'un endroit où stocker toutes nos balles. Le tableau suivant fera ce travail — ajoutez-le au bas de votre code maintenant : - <pre class="brush: js">let balls = []; -</pre> + ```js + let balls = []; + ``` - <pre>while (balls.length < 25) { - let size = random(10,20); - let ball = new Ball( - // ball position always drawn at least one ball width - // away from the edge of the canvas, to avoid drawing errors - random(0 + size,width - size), - random(0 + size,height - size), - random(-7,7), - random(-7,7), - 'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')', - size - ); + while (balls.length < 25) { + let size = random(10,20); + let ball = new Ball( + // ball position always drawn at least one ball width + // away from the edge of the canvas, to avoid drawing errors + random(0 + size,width - size), + random(0 + size,height - size), + random(-7,7), + random(-7,7), + 'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')', + size + ); - balls.push(ball); -}</pre> - Tous les programmes qui animent les choses impliquent généralement une boucle d'animation, qui sert à mettre à jour les informations dans le programme et à restituer ensuite la vue résultante sur chaque image de l'animation. C'est la base de la plupart des jeux et autres programmes similaires.</li> - <li>Ajoutez ce qui suit au bas de votre code maintenant : - <pre class="brush: js">function loop() { - ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; - ctx.fillRect(0, 0, width, height); + balls.push(ball); + } - for (let i = 0; i < balls.length; i++) { - balls[i].draw(); - balls[i].update(); - } + Tous les programmes qui animent les choses impliquent généralement une boucle d'animation, qui sert à mettre à jour les informations dans le programme et à restituer ensuite la vue résultante sur chaque image de l'animation. C'est la base de la plupart des jeux et autres programmes similaires. + +2. Ajoutez ce qui suit au bas de votre code maintenant : + + ```js + function loop() { + ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; + ctx.fillRect(0, 0, width, height); + + for (let i = 0; i < balls.length; i++) { + balls[i].draw(); + balls[i].update(); + } + + requestAnimationFrame(loop); + } + ``` - requestAnimationFrame(loop); -}</pre> + Notre fonction `loop()` fonctionne comme suit : - <p>Notre fonction <code>loop()</code> fonctionne comme suit :</p> + - On définit la couleur de remplissage du canvas en noir semi-transparent, puis dessine un rectangle de couleur sur toute la largeur et la hauteur du canvas, en utilisant `fillRect()` (les quatre paramètres fournissent une coordonnée de départ et une largeur et une hauteur pour le rectangle dessiné ). Cela sert à masquer le dessin de l'image précédente avant que la suivante ne soit dessinée. Si vous ne faites pas cela, vous verrez juste de longs serpents se faufiler autour de la toile au lieu de balles qui bougent ! La couleur du remplissage est définie sur semi-transparent, `rgba (0,0,0,.25)`, pour permettre aux quelques images précédentes de briller légèrement, produisant les petites traînées derrière les balles lorsqu'elles se déplacent. Si vous avez changé 0.25 à 1, vous ne les verrez plus du tout. Essayez de faire varier ce dernier nombre (entre 0 et 1) pour voir l'effet qu'il a. + - On crée un nouvel objet `Ball()` avec des attributs générées aléatoirement grâce à la fonction `random()`, puis on ajoute l'objet au tableau, mais seulement lorsque le nombre de balles dans le tableau est inférieur à 25. Donc quand on a 25 balles à l'écran, plus aucune balle supplémentaire n'apparaît. Vous pouvez essayer de faire varier le nombre dans `balls.length <25` pour obtenir plus, ou moins de balles à l'écran. En fonction de la puissance de traitement de votre ordinateur / navigateur, spécifier plusieurs milliers de boules peut ralentir l'animation de façon très significative ! + - Le programme boucle à travers tous les objets du tableau sur chacun desquels il exécute la fonction `draw()` et `update()` pour dessiner à l'écran chaque balle et faire les mise à jour de chaque attribut vant le prochain rafraîchissement. + - Exécute à nouveau la fonction à l'aide de la méthode `requestAnimationFrame()` — lorsque cette méthode est exécutée en permanence et a reçu le même nom de fonction, elle exécute cette fonction un nombre défini de fois par seconde pour créer une animation fluide. Cela se fait généralement de manière récursive — ce qui signifie que la fonction s'appelle elle-même à chaque fois qu'elle s'exécute, de sorte qu'elle sera répétée encore et encore. - <ul> - <li>On définit la couleur de remplissage du canvas en noir semi-transparent, puis dessine un rectangle de couleur sur toute la largeur et la hauteur du canvas, en utilisant <code>fillRect()</code> (les quatre paramètres fournissent une coordonnée de départ et une largeur et une hauteur pour le rectangle dessiné ). Cela sert à masquer le dessin de l'image précédente avant que la suivante ne soit dessinée. Si vous ne faites pas cela, vous verrez juste de longs serpents se faufiler autour de la toile au lieu de balles qui bougent ! La couleur du remplissage est définie sur semi-transparent, <code>rgba (0,0,0,.25)</code>, pour permettre aux quelques images précédentes de briller légèrement, produisant les petites traînées derrière les balles lorsqu'elles se déplacent. Si vous avez changé 0.25 à 1, vous ne les verrez plus du tout. Essayez de faire varier ce dernier nombre (entre 0 et 1) pour voir l'effet qu'il a.</li> - <li>On crée un nouvel objet <code>Ball()</code> avec des attributs générées aléatoirement grâce à la fonction <code>random()</code>, puis on ajoute l'objet au tableau, mais seulement lorsque le nombre de balles dans le tableau est inférieur à 25. Donc quand on a 25 balles à l'écran, plus aucune balle supplémentaire n'apparaît. Vous pouvez essayer de faire varier le nombre dans <code>balls.length <25</code> pour obtenir plus, ou moins de balles à l'écran. En fonction de la puissance de traitement de votre ordinateur / navigateur, spécifier plusieurs milliers de boules peut ralentir l'animation de façon très significative !</li> - <li>Le programme boucle à travers tous les objets du tableau sur chacun desquels il exécute la fonction <code>draw()</code> et <code>update()</code> pour dessiner à l'écran chaque balle et faire les mise à jour de chaque attribut vant le prochain rafraîchissement.</li> - <li>Exécute à nouveau la fonction à l'aide de la méthode <code>requestAnimationFrame()</code> — lorsque cette méthode est exécutée en permanence et a reçu le même nom de fonction, elle exécute cette fonction un nombre défini de fois par seconde pour créer une animation fluide. Cela se fait généralement de manière récursive — ce qui signifie que la fonction s'appelle elle-même à chaque fois qu'elle s'exécute, de sorte qu'elle sera répétée encore et encore.</li> - </ul> - </li> - <li>Finallement mais non moins important, ajoutez la ligne suivante au bas de votre code — nous devons appeler la fonction une fois pour démarrer l'animation. - <pre class="brush: js">loop();</pre> - </li> -</ol> +3. Finallement mais non moins important, ajoutez la ligne suivante au bas de votre code — nous devons appeler la fonction une fois pour démarrer l'animation. -<p>Voilà pour les bases — essayez d'enregistrer et de rafraîchir pour tester vos balles bondissantes!</p> + ```js + loop(); + ``` -<h2 id="Ajouter_la_détection_de_collision">Ajouter la détection de collision</h2> +Voilà pour les bases — essayez d'enregistrer et de rafraîchir pour tester vos balles bondissantes! -<p>Maintenant, pour un peu de plaisir, ajoutons une détection de collision à notre programme, afin que nos balles sachent quand elles ont frappé une autre balle.</p> +## Ajouter la détection de collision -<ol> - <li>Tout d'abord, ajoutez la définition de méthode suivante ci-dessous où vous avez défini la méthode <code>update()</code> (c'est-à-dire le bloc <code>Ball.prototype.update</code>). +Maintenant, pour un peu de plaisir, ajoutons une détection de collision à notre programme, afin que nos balles sachent quand elles ont frappé une autre balle. - <pre class="brush: js">Ball.prototype.collisionDetect = function() { - for (let j = 0; j < balls.length; j++) { - if (!(this === balls[j])) { - const dx = this.x - balls[j].x; - const dy = this.y - balls[j].y; - const distance = Math.sqrt(dx * dx + dy * dy); +1. Tout d'abord, ajoutez la définition de méthode suivante ci-dessous où vous avez défini la méthode `update()` (c'est-à-dire le bloc `Ball.prototype.update`). - if (distance < this.size + balls[j].size) { - balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; + ```js + Ball.prototype.collisionDetect = function() { + for (let j = 0; j < balls.length; j++) { + if (!(this === balls[j])) { + const dx = this.x - balls[j].x; + const dy = this.y - balls[j].y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < this.size + balls[j].size) { + balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; + } + } } } - } -}</pre> + ``` + + Cette méthode est un peu complexe, donc ne vous inquiétez pas si vous ne comprenez pas exactement comment cela fonctionne pour le moment. Regardons cela pas-à-pas : - <p>Cette méthode est un peu complexe, donc ne vous inquiétez pas si vous ne comprenez pas exactement comment cela fonctionne pour le moment. Regardons cela pas-à-pas :</p> + - Pour chaque balle _b_, nous devons vérifier chaque autre balle pour voir si elle est entrée en collision avec *b*. Pour ce faire, on inspecte toutes les balles du tableau `balls[]` dans une boucle `for`. + - Immédiatement à l'intérieur de cette boucle `for`, une instruction `if` vérifie si la balle courante *b'* , inspectée dans la boucle, n'est égale à la balle *b. Le code correspondant est :* `b'!== b`_._ En effet, nous ne voulons pas vérifier si une balle _b_ est entrée en collision avec elle-même ! Nous contrôlons donc si la balle actuelle _b_—dont la méthode `collisionDetect()` est invoquée—est distincte de la balle _b'_ inspectée dans la boucle*.* Ainsi le bloc de code venant après l'instruction `if` ne s'exécutera que si les balles _b_ et _b'_ ne sont pas identiques. + - Un algorithme classique permet ensuite de vérifier la superposition de deux disques. Ceci est expliqué plus loin dans [2D collision detection](/fr/docs/Games/Techniques/2D_collision_detection). + - Si une collision est détectée, le code à l'intérieur de l'instruction interne `if` est exécuté. Dans ce cas, nous définissons simplement la propriété `color` des deux cercles à une nouvelle couleur aléatoire. Nous aurions pu faire quelque chose de bien plus complexe, comme faire rebondir les balles de façon réaliste, mais cela aurait été beaucoup plus complexe à mettre en œuvre. Pour de telles simulations de physique, les développeurs ont tendance à utiliser des bibliothèques de jeux ou de physiques telles que [PhysicsJS](http://wellcaffeinated.net/PhysicsJS/), [matter.js](http://brm.io/matter-js/), [Phaser](http://phaser.io/), etc. - <ul> - <li>Pour chaque balle <em>b</em>, nous devons vérifier chaque autre balle pour voir si elle est entrée en collision avec <em>b</em>. Pour ce faire, on inspecte toutes les balles du tableau <code>balls[]</code> dans une boucle <code>for</code>.</li> - <li>Immédiatement à l'intérieur de cette boucle <code>for</code>, une instruction <code>if</code> vérifie si la balle courante <em>b'</em> , inspectée dans la boucle, n'est égale à la balle <em>b. Le code correspondant est : </em><code><em>b</em>'!== <em>b</em></code><em>. </em>En effet, nous ne voulons pas vérifier si une balle <em>b</em> est entrée en collision avec elle-même ! Nous contrôlons donc si la balle actuelle <em>b</em>—dont la méthode <code>collisionDetect()</code> est invoquée—est distincte de la balle <em>b' </em>inspectée dans la boucle<em>. </em>Ainsi le bloc de code venant après l'instruction <code>if</code> ne s'exécutera que si les balles <em>b</em> et <em>b'</em> ne sont pas identiques.</li> - <li>Un algorithme classique permet ensuite de vérifier la superposition de deux disques. Ceci est expliqué plus loin dans <a href="/fr/docs/Games/Techniques/2D_collision_detection">2D collision detection</a>.</li> - <li>Si une collision est détectée, le code à l'intérieur de l'instruction interne <code>if</code> est exécuté. Dans ce cas, nous définissons simplement la propriété <code>color</code> des deux cercles à une nouvelle couleur aléatoire. Nous aurions pu faire quelque chose de bien plus complexe, comme faire rebondir les balles de façon réaliste, mais cela aurait été beaucoup plus complexe à mettre en œuvre. Pour de telles simulations de physique, les développeurs ont tendance à utiliser des bibliothèques de jeux ou de physiques telles que <a href="http://wellcaffeinated.net/PhysicsJS/">PhysicsJS</a>, <a href="http://brm.io/matter-js/">matter.js</a>, <a href="http://phaser.io/">Phaser</a>, etc.</li> - </ul> - </li> - <li>Vous devez également appeler cette méthode dans chaque image de l'animation. Ajouter le code ci-dessous juste après la ligne <code>balls[i].update();</code>: - <pre class="brush: js">balls[i].collisionDetect();</pre> - </li> - <li>Enregistrez et rafraîchissez la démo à nouveau, et vous verrez vos balles changer de couleur quand elles entrent en collision !</li> -</ol> +2. Vous devez également appeler cette méthode dans chaque image de l'animation. Ajouter le code ci-dessous juste après la ligne `balls[i].update();`: -<div class="note"> -<p><strong>Note :</strong> Si vous avez des difficultés à faire fonctionner cet exemple, essayez de comparer votre code JavaScript avec notre <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">version finale</a> (voir également la <a href="http://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html">démo en ligne</a>).</p> -</div> + ```js + balls[i].collisionDetect(); + ``` -<h2 id="Résumé">Résumé</h2> +3. Enregistrez et rafraîchissez la démo à nouveau, et vous verrez vos balles changer de couleur quand elles entrent en collision ! -<p>Nous espérons que vous vous êtes amusé à écrire votre propre exemple de balles aléatoires bondissantes comme dans le monde réel, en utilisant diverses techniques orientées objet et divers objets d'un bout à l'autre du module ! Nous espérons vous avoir offert un aperçu utile de l'utilisation des objets.</p> +> **Note :** Si vous avez des difficultés à faire fonctionner cet exemple, essayez de comparer votre code JavaScript avec notre [version finale](https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js) (voir également la [démo en ligne](http://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html)). -<p>C'est tout pour les articles sur les objets — il ne vous reste plus qu'à tester vos compétences dans l'évaluation sur les objets.</p> +## Résumé -<h2 id="Voir_aussi">Voir aussi</h2> +Nous espérons que vous vous êtes amusé à écrire votre propre exemple de balles aléatoires bondissantes comme dans le monde réel, en utilisant diverses techniques orientées objet et divers objets d'un bout à l'autre du module ! Nous espérons vous avoir offert un aperçu utile de l'utilisation des objets. -<ul> - <li><a href="/fr/docs/Web/API/Canvas_API/Tutorial">Didacticiel sur canvas</a> — un guide pour débutants sur l'utilisation de canvas 2D.</li> - <li><a href="/fr/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></li> - <li><a href="/fr/docs/Games/Techniques/2D_collision_detection">Détection de collision 2D</a> </li> - <li><a href="/fr/docs/Games/Techniques/3D_collision_detection">Détection de collision 3D</a> </li> - <li><a href="/fr/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript">Jeu d'évasion 2D utilisant du JavaScript pu</a> —un excellent tutoriel pour débutant montrant comment construire un jeu en 2D.</li> - <li><a href="/fr/docs/Games/Tutorials/2D_breakout_game_Phaser">Jeu d'évasion 2D utilisant phaser</a> — explique les bases de la construction d'un jeu 2D en utilisant une bibliothèque de jeux JavaScript.</li> -</ul> +C'est tout pour les articles sur les objets — il ne vous reste plus qu'à tester vos compétences dans l'évaluation sur les objets. -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</p> +## Voir aussi +- [Didacticiel sur canvas](/fr/docs/Web/API/Canvas_API/Tutorial) — un guide pour débutants sur l'utilisation de canvas 2D. +- [requestAnimationFrame()](/fr/docs/Web/API/window/requestAnimationFrame) +- [Détection de collision 2D](/fr/docs/Games/Techniques/2D_collision_detection) +- [Détection de collision 3D](/fr/docs/Games/Techniques/3D_collision_detection) +- [Jeu d'évasion 2D utilisant du JavaScript pu](/fr/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript) —un excellent tutoriel pour débutant montrant comment construire un jeu en 2D. +- [Jeu d'évasion 2D utilisant phaser](/fr/docs/Games/Tutorials/2D_breakout_game_Phaser) — explique les bases de la construction d'un jeu 2D en utilisant une bibliothèque de jeux JavaScript. +{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}} -<h2 id="Dans_ce_module">Dans ce module</h2> +## Dans ce module -<ul> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Basics">Les bases de l'objet</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orienté objet pour les débutants</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object_prototypes">Prototypes d'objets</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Inheritance">Héritage en JavaScript</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/JSON">Travailler avec des données JSON</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Object_building_practice">Pratique de construction d'objets</a></li> - <li><a href="/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Ajout de fonctionnalités à notre démo de balles bondissantes</a></li> -</ul> +- [Les bases de l'objet](/fr/docs/Learn/JavaScript/Objects/Basics) +- [JavaScript orienté objet pour les débutants](/fr/docs/Learn/JavaScript/Objects/Object-oriented_JS) +- [Prototypes d'objets](/fr/docs/Learn/JavaScript/Objects/Object_prototypes) +- [Héritage en JavaScript](/fr/docs/Learn/JavaScript/Objects/Inheritance) +- [Travailler avec des données JSON](/fr/docs/Learn/JavaScript/Objects/JSON) +- [Pratique de construction d'objets](/fr/docs/Learn/JavaScript/Objects/Object_building_practice) +- [Ajout de fonctionnalités à notre démo de balles bondissantes](/fr/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features) diff --git a/files/fr/learn/javascript/objects/object_prototypes/index.md b/files/fr/learn/javascript/objects/object_prototypes/index.md index 95663a0f7b..d429450f10 100644 --- a/files/fr/learn/javascript/objects/object_prototypes/index.md +++ b/files/fr/learn/javascript/objects/object_prototypes/index.md @@ -8,187 +8,214 @@ tags: translation_of: Learn/JavaScript/Objects/Object_prototypes original_slug: Learn/JavaScript/Objects/Prototypes_Objet --- -<div>{{LearnSidebar}}</div> +{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}} -<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</div> - -<p>Les prototypes sont un mécanisme au sein de JavaScript qui permettent aux objets JavaScript d'hériter des propriétés d'autres objets. Les prototypes implémentent un héritage différent de celui rencontré dans les langages de programmation objets habituels. Dans cet article, nous allons aborder ces différences, nous allons aussi voir comment la chaîne de prototypage fonctionne. Nous verrons aussi comment les propriétés prototypes peuvent être utilisées afin d'ajouter des méthodes à des constructeurs existants.</p> +Les prototypes sont un mécanisme au sein de JavaScript qui permettent aux objets JavaScript d'hériter des propriétés d'autres objets. Les prototypes implémentent un héritage différent de celui rencontré dans les langages de programmation objets habituels. Dans cet article, nous allons aborder ces différences, nous allons aussi voir comment la chaîne de prototypage fonctionne. Nous verrons aussi comment les propriétés prototypes peuvent être utilisées afin d'ajouter des méthodes à des constructeurs existants. <table class="standard-table"> - <tbody> - <tr> - <th scope="row">Pré-requis :</th> - <td>Une connaissance générale de l'informatique, des notions d'HTML et CSS, une connaissance des bases en JavaScript (voir <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et <a href="/fr/docs/Learn/JavaScript/Building_blocks">Blocs de construction</a>) ainsi que des notions de JavaScript orienté objet (JSOO) (voir <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction aux objets</a>).</td> - </tr> - <tr> - <th scope="row">Objectifs :</th> - <td>Comprendre le concept de prototype en JavaScript, comprendre comment fonctionne une chaîne de prototypage et comment ajouter de nouvelles méthodes aux propriétés d'un prototype.</td> - </tr> - </tbody> + <tbody> + <tr> + <th scope="row">Pré-requis :</th> + <td> + Une connaissance générale de l'informatique, des notions d'HTML et CSS, + une connaissance des bases en JavaScript (voir + <a href="/fr/docs/Learn/JavaScript/First_steps">Premiers pas</a> et + <a href="/fr/docs/Learn/JavaScript/Building_blocks" + >Blocs de construction</a + >) ainsi que des notions de JavaScript orienté objet (JSOO) (voir + <a href="/fr/docs/Learn/JavaScript/Object-oriented/Introduction" + >Introduction aux objets</a + >). + </td> + </tr> + <tr> + <th scope="row">Objectifs :</th> + <td> + Comprendre le concept de prototype en JavaScript, comprendre comment + fonctionne une chaîne de prototypage et comment ajouter de nouvelles + méthodes aux propriétés d'un prototype. + </td> + </tr> + </tbody> </table> -<h2 id="Un_langage_basé_sur_des_prototypes">Un langage basé sur des prototypes ?</h2> +## Un langage basé sur des prototypes ? -<p>JavaScript est souvent décrit comme un langage basé sur les prototypes, chaque objet pouvant avoir un <strong>prototype objet</strong> d'où il hérite des méthodes et des attributs. Un prototype peut lui aussi avoir son prototype objet duquel il héritera des méthodes et des attributs et ainsi de suite. On parle alors de chaîne de prototypage (ou <em>prototype chain<strong> </strong></em>en anglais). Cela permet d'expliquer pourquoi différents objets possèdent des attributs et des méthodes définis à partir d'autres objets.</p> +JavaScript est souvent décrit comme un langage basé sur les prototypes, chaque objet pouvant avoir un **prototype objet** d'où il hérite des méthodes et des attributs. Un prototype peut lui aussi avoir son prototype objet duquel il héritera des méthodes et des attributs et ainsi de suite. On parle alors de chaîne de prototypage (ou \*prototype chain** \***en anglais). Cela permet d'expliquer pourquoi différents objets possèdent des attributs et des méthodes définis à partir d'autres objets. -<p>En réalité, les méthodes et attributs sont définis dans l'attribut <code>prototype</code> , la fonction constructrice de l'objet et non pas dans les instances des objets elles-mêmes.</p> +En réalité, les méthodes et attributs sont définis dans l'attribut `prototype` , la fonction constructrice de l'objet et non pas dans les instances des objets elles-mêmes. -<p>En programmation orientée objet classique, les classes sont définies, puis lorsque des instances sont créées, l'ensemble des attributs et des méthodes sont copiés dans l'instance. En JavaScript en revanche, tout n'est pas copié : on établit un lien entre l'objet instancié et son constructeur (c'est un lien dans la chaîne de prototypage). On détermine alors les méthodes et les attributs en remontant la chaîne.</p> +En programmation orientée objet classique, les classes sont définies, puis lorsque des instances sont créées, l'ensemble des attributs et des méthodes sont copiés dans l'instance. En JavaScript en revanche, tout n'est pas copié : on établit un lien entre l'objet instancié et son constructeur (c'est un lien dans la chaîne de prototypage). On détermine alors les méthodes et les attributs en remontant la chaîne. -<div class="note"> -<p><strong>Note:</strong> Il faut bien comprendre qu'il y a une différence entre la notion de prototype d'un objet (qu'on obtient via <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf">Object.getPrototypeOf(obj)</a></code>, ou via la propriété dépréciée <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code> ) et l' attribut <code>prototype</code>d'une fonction constructrice. La première concerne chaque instance, le dernier existe uniquement sur une fonction constructrice. Cela dit, <code>Object.getPrototypeOf(new Foobar())</code> renvoie au même object que<code>Foobar.prototype</code>.</p> -</div> +> **Note :** Il faut bien comprendre qu'il y a une différence entre la notion de prototype d'un objet (qu'on obtient via [`Object.getPrototypeOf(obj)`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf), ou via la propriété dépréciée [`__proto__`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) ) et l' attribut `prototype`d'une fonction constructrice. La première concerne chaque instance, le dernier existe uniquement sur une fonction constructrice. Cela dit, `Object.getPrototypeOf(new Foobar())` renvoie au même object que`Foobar.prototype`. -<p>Prenons un exemple afin de rendre cela un peu plus clair.</p> +Prenons un exemple afin de rendre cela un peu plus clair. -<h2 id="Comprendre_les_prototypes_objet">Comprendre les prototypes objet</h2> +## Comprendre les prototypes objet -<p>Reprenons notre exemple dans lequel nous avions écrit notre constructeur <code>Personne()</code>. Chargez cet exemple dans votre navigateur, si vous ne l'avez plus, vous pouvez utiliser notre exemple<a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html"> oojs-class-further-exercises.html</a> example (voir aussi le <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">code source</a>).</p> +Reprenons notre exemple dans lequel nous avions écrit notre constructeur `Personne()`. Chargez cet exemple dans votre navigateur, si vous ne l'avez plus, vous pouvez utiliser notre exemple[ oojs-class-further-exercises.html](https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html) example (voir aussi le [code source](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html)). -<p>Dans cet exemple, nous avons défini un constructeur comme suit :</p> +Dans cet exemple, nous avons défini un constructeur comme suit : -<pre class="brush: js">function Personne(prenom, nom, age, genre, interets) { +```js +function Personne(prenom, nom, age, genre, interets) { // property and method definitions -};</pre> +}; +``` + +Nous avons ensuite instancié des objets comme ceci : -<p>Nous avons ensuite instancié des objets comme ceci :</p> +```js +var personne1 = new Personne('Bob', 'Smith', 32, 'homme', ['musique', 'ski']); +``` -<pre class="brush: js">var personne1 = new Personne('Bob', 'Smith', 32, 'homme', ['musique', 'ski']);</pre> +Si vous entrez « `personne1` » dans votre console JavaScript, vous devriez voir que le navigateur essaie de faire de l'auto-complétion avec les attributs de cet objet. -<p>Si vous entrez « <code>personne1</code> » dans votre console JavaScript, vous devriez voir que le navigateur essaie de faire de l'auto-complétion avec les attributs de cet objet.</p> + -<p><img alt="" src="autocomplete_Personne.png"><img alt="" src="autocomplete_Personne.png"></p> +Dans cette liste vous verrez les membres définis au niveau du constructeur de `personne1` qui n'est autre `Personne()`. On y trouve les valeurs suivantes : `nom`, `age`, `genre`, `interets`, `bio`, et `salutation`. On peut voir aussi d'autres membres tels que `watch`, `valueOf` … Ces membres particuliers sont définis au niveau du prototype objet du constructeur `Personne()`, qui est [`Object`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object). On voit ici une mise en œuvre de la chaine de prototypage. -<p>Dans cette liste vous verrez les membres définis au niveau du constructeur de <code>personne1</code> qui n'est autre <code>Personne()</code>. On y trouve les valeurs suivantes : <code>nom</code>, <code>age</code>, <code>genre</code>, <code>interets</code>, <code>bio</code>, et <code>salutation</code>. On peut voir aussi d'autres membres tels que <code>watch</code>, <code>valueOf</code> … Ces membres particuliers sont définis au niveau du prototype objet du constructeur <code>Personne()</code>, qui est <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code>. On voit ici une mise en œuvre de la chaine de prototypage.</p> + -<p><img alt="" src="prototype_chaine.PNG"></p> +Que peut-il bien se passer lorsque l'on tente d'appeler une méthode définie pour `Object` en l'appliquant à `Personne`1 ? Par exemple : -<p>Que peut-il bien se passer lorsque l'on tente d'appeler une méthode définie pour <code>Object</code> en l'appliquant à <code>Personne</code>1 ? Par exemple :</p> +```js +personne1.valueOf() +``` -<pre class="brush: js">personne1.valueOf()</pre> +Cette méthode renvoie simplement la valeur de l'objet pour lequel elle est appelée. Vous pouvez essayer dans votre console ! Lorsque l'on effectue cet appel, il se produit les choses suivantes : -<p>Cette méthode renvoie simplement la valeur de l'objet pour lequel elle est appelée. Vous pouvez essayer dans votre console ! Lorsque l'on effectue cet appel, il se produit les choses suivantes :</p> +- Le navigateur tente de déterminer si l'objet `personne1` implémente une méthode `valueOf().` +- Aucune n'est présente, le navigateur vérifie donc si le prototype objet de `personne1` (`Personne`) contient cette méthode. +- Pas de `valueOf()` non plus, donc le navigateur regarde si le prototype objet du constructeur `Personne()` (`Object`) possède cette méthode. Il y en a une, donc il l'appelle et tout va bien ! -<ul> - <li>Le navigateur tente de déterminer si l'objet <code>personne1</code> implémente une méthode <code>valueOf().</code></li> - <li>Aucune n'est présente, le navigateur vérifie donc si le prototype objet de <code>personne1</code> (<code>Personne</code>) contient cette méthode.</li> - <li>Pas de <code>valueOf()</code> non plus, donc le navigateur regarde si le prototype objet du constructeur <code>Personne()</code> (<code>Object</code>) possède cette méthode. Il y en a une, donc il l'appelle et tout va bien !</li> -</ul> +> **Note :** Encore une fois, il est important d'insister sur le fait que les méthodes et attributs ne sont **pas** copiés d'un objet à un autre, mais qu'on y accède à chaque fois en remontant la chaine de prototypage. -<div class="note"> -<p><strong>Note :</strong> Encore une fois, il est important d'insister sur le fait que les méthodes et attributs ne sont <strong>pas</strong> copiés d'un objet à un autre, mais qu'on y accède à chaque fois en remontant la chaine de prototypage.</p> -</div> +> **Note :** Il n'existe pas de façon officielle d'accéder directement au prototype d'un objet donné. Les « liens » entre les éléments de la chaine sont définis au sein d'une propriété interne appelée `[[prototype]]` définie dans la spécification de JavaScript. (voir [ECMAScript](fr/docs/Web/JavaScript/Language_Resources)). Néanmoins, la plupart des navigateurs modernes implémentent l'attribut [`__proto__`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) (deux tirets soulignés ou _underscore_ de chaque côté) qui contient le prototype objet d'un objet. Vous pouvez tenter `personne1.__proto__` et `personne1.__proto__.__proto__` pour voir à quoi ressemble une chaine de prototypage dans la console ! -<div class="note"> -<p><strong>Note :</strong> Il n'existe pas de façon officielle d'accéder directement au prototype d'un objet donné. Les « liens » entre les éléments de la chaine sont définis au sein d'une propriété interne appelée <code>[[prototype]]</code> définie dans la spécification de JavaScript. (voir <a href="fr/docs/Web/JavaScript/Language_Resources">ECMAScript</a>). Néanmoins, la plupart des navigateurs modernes implémentent l'attribut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code> (deux tirets soulignés ou <em>underscore</em> de chaque côté) qui contient le prototype objet d'un objet. Vous pouvez tenter <code>personne1.__proto__</code> et <code>personne1.__proto__.__proto__</code> pour voir à quoi ressemble une chaine de prototypage dans la console !</p> -</div> +## L'attribut prototype : là où l'on définit les éléments héritables -<h2 id="Lattribut_prototype_là_où_lon_définit_les_éléments_héritables">L'attribut prototype : là où l'on définit les éléments héritables</h2> +Mais alors, où définissons-nous les attributs et méthodes qui seront hérités au long de la chaîne de prototypage ? En effet, s'il on regarde à la page de documentation [`Object`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object) on peut voir un large éventail d'attributs et de méthodes qui sont définis, une liste bien plus longue que celle disponible pour notre objet `Personne1`. Pourquoi `Personne1` hérite de certains de ces éléments mais pas de tous ? -<p>Mais alors, où définissons-nous les attributs et méthodes qui seront hérités au long de la chaîne de prototypage ? En effet, s'il on regarde à la page de documentation <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code> on peut voir un large éventail d'attributs et de méthodes qui sont définis, une liste bien plus longue que celle disponible pour notre objet <code>Personne1</code>. Pourquoi <code>Personne1</code> hérite de certains de ces éléments mais pas de tous ?</p> +Cela vient du fait que les éléments hérités sont ceux définis au niveau de l'attribut `prototype` d'`Object` (on peut voir cet attribut comme un sous espace de noms). Ainsi, les éléments listés sont ceux sous `Object.prototype.` et pas ceux situés juste sous `Object.` La valeur de l'attribut `prototype` est un objet qui rassemble les attributs et méthodes que l'on souhaite appliquer aux objets tout au long de la chaine de prototypage. -<p>Cela vient du fait que les éléments hérités sont ceux définis au niveau de l'attribut <code>prototype</code> d'<code>Object</code> (on peut voir cet attribut comme un sous espace de noms). Ainsi, les éléments listés sont ceux sous <code>Object.prototype.</code> et pas ceux situés juste sous <code>Object.</code> La valeur de l'attribut <code>prototype</code> est un objet qui rassemble les attributs et méthodes que l'on souhaite appliquer aux objets tout au long de la chaine de prototypage.</p> +Ainsi [`Object.prototype.watch()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/watch), [`Object.prototype.valueOf()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) … sont disponibles pour n'importe quel objet qui hérite de `Object.prototype` ce qui inclus les nouvelles instances créées à partir du constructeur `Personne()`. -<p>Ainsi <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/watch">Object.prototype.watch()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf">Object.prototype.valueOf()</a></code> … sont disponibles pour n'importe quel objet qui hérite de <code>Object.prototype</code> ce qui inclus les nouvelles instances créées à partir du constructeur <code>Personne()</code>.</p> +[`Object.is()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/is), [`Object.keys()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), ainsi que d'autres membres non définis dans `prototype` ne sont pas hérités par les instances d'objet ou les objets qui héritent de `Object.prototype`. Ces méthodes et attributs sont disponibles uniquement pour le constructeur `Object()`. -<p><code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/is">Object.is()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>, ainsi que d'autres membres non définis dans <code>prototype</code> ne sont pas hérités par les instances d'objet ou les objets qui héritent de <code>Object.prototype</code>. Ces méthodes et attributs sont disponibles uniquement pour le constructeur <code>Object()</code>.</p> +> **Note :** Ça paraît bizarre, d'avoir une méthode définie au sein d'un constructeur qui est lui même une fonction non ? Et bien, une fonction est aussi un type d'objet — vous pouvez jeter un œil à la documentation du constructeur [`Function()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Function) si vous ne nous croyez pas. -<div class="note"> -<p><strong>Note :</strong> Ça paraît bizarre, d'avoir une méthode définie au sein d'un constructeur qui est lui même une fonction non ? Et bien, une fonction est aussi un type d'objet — vous pouvez jeter un œil à la documentation du constructeur <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Function">Function()</a></code> si vous ne nous croyez pas.</p> -</div> +1. Vous pouvez vérifier les attributs du prototype en reprenant l'exemple précédent et en entrant le code suivant dans la console JavaScript : -<ol> - <li>Vous pouvez vérifier les attributs du prototype en reprenant l'exemple précédent et en entrant le code suivant dans la console JavaScript : - <pre class="brush: js">Personne.prototype</pre> - </li> - <li>Il n'y a pas grand chose renvoyé par le navigateur. En même temps, nous n'avons rien défini dans l'attribut prototype de notre constructeur, et par défaut l'attribut prototype d'un constructeur est toujours vide. Voyons ce que renvoie le code suivant : - <pre class="brush: js">Object.prototype</pre> - </li> -</ol> + ```js + Personne.prototype + ``` -<p>On observe que plusieurs méthodes sont définies au niveau de l'attribut <code>prototype</code> d'<code>Object</code>, qui seront alors disponibles pour les objets qui héritent d'<code>Object</code>, comme nous l'avons vu plus haut.</p> +2. Il n'y a pas grand chose renvoyé par le navigateur. En même temps, nous n'avons rien défini dans l'attribut prototype de notre constructeur, et par défaut l'attribut prototype d'un constructeur est toujours vide. Voyons ce que renvoie le code suivant : -<p>Vous verrez qu'il existe plein d'exemples de chaine de prototypage dans JavaScript. Vous pouvez essayer de trouver les méthodes et les attributs définis dans les attributs <code>prototype</code> des objets globeaux comme <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Date">Date</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Number">Number</a></code>, et <code> <a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code>. Chacun de ces objets possède des éléments au sein de leur attribut prototype. Dès lors que l'on crée une chaine de caractères, comme celle-ci :</p> + ```js + Object.prototype + ``` -<pre class="brush: js">var maChaine = 'Ceci est ma chaine de caracteres.';</pre> +On observe que plusieurs méthodes sont définies au niveau de l'attribut `prototype` d'`Object`, qui seront alors disponibles pour les objets qui héritent d'`Object`, comme nous l'avons vu plus haut. -<p><code>maChaine </code>possède aussitôt plusieurs méthodes utiles pour manipuler les chaines de caractères telles que <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/split">split()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf">indexOf()</a></code>, <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a></code>…</p> +Vous verrez qu'il existe plein d'exemples de chaine de prototypage dans JavaScript. Vous pouvez essayer de trouver les méthodes et les attributs définis dans les attributs `prototype` des objets globeaux comme [`String`](/fr/docs/Web/JavaScript/Reference/Global_Objects/String), [`Date`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Date), [`Number`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Number), et ` Array`. Chacun de ces objets possède des éléments au sein de leur attribut prototype. Dès lors que l'on crée une chaine de caractères, comme celle-ci : -<div class="warning"> -<p><strong>Attention :</strong> L'attribut <code>prototype</code> est un des éléments JavaScript qui peut le plus prêter à confusion. On pourrait penser qu'il s'agit du prototype objet de l'objet courant mais ça ne l'est pas (on peut y accéder via <code>__proto__</code>). L'attribut <code>prototype </code>est un attribut qui contient un objet où l'on définit les éléments dont on va pouvoir hériter.</p> -</div> +```js +var maChaine = 'Ceci est ma chaine de caracteres.'; +``` -<h2 id="Revenons_sur_create">Revenons sur create()</h2> +`maChaine `possède aussitôt plusieurs méthodes utiles pour manipuler les chaines de caractères telles que [`split()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/String/split), [`indexOf()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf), [`replace()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/String/replace)… -<p>Nous avons vu précedemment que la méthode <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></code> pouvait être utilisée pour instancier des objets.</p> +> **Attention :** L'attribut `prototype` est un des éléments JavaScript qui peut le plus prêter à confusion. On pourrait penser qu'il s'agit du prototype objet de l'objet courant mais ça ne l'est pas (on peut y accéder via `__proto__`). L'attribut `prototype `est un attribut qui contient un objet où l'on définit les éléments dont on va pouvoir hériter. -<ol> - <li>Par exemple, vous pouvez essayer le code suivant dans la console JavaScript : - <pre class="brush: js">var personne2 = Object.create(personne1);</pre> - </li> - <li>En réalité <code>create()</code> se contente de créer un nouvel objet à partir d'un prototype spécifique. Dans cet exemple, <code>personne2</code> est créé à partir de <code>personne1</code> qui agit en tant que prototype. Vous pouvez le vérifier via : - <pre class="brush: js">person2.__proto__</pre> - </li> -</ol> +## Revenons sur create() -<p>Cela renverra l'objet <code>personne1</code>.</p> +Nous avons vu précedemment que la méthode [`Object.create()`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/create) pouvait être utilisée pour instancier des objets. -<h2 id="Lattribut_constructor">L'attribut <em>constructor</em></h2> +1. Par exemple, vous pouvez essayer le code suivant dans la console JavaScript : -<p>Chaque fonction possède un attribut prototype dont la valeur est un objet contenant un attribut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code>. L'attribut <code>constructor</code> renvoie vers la méthode constructrice utilisée. Nous allons le voir dans la section suivante, les attributs définis dans l'attribut <code>Personne.prototype</code> deviennent disponibles pour toutes les instances créées à partir du constructeur <code>Personne()</code>. De cette manière, l'attribut <code>constructor</code> est aussi disponible au sein de <code>personne1</code> et <code>personne2</code>.</p> + ```js + var personne2 = Object.create(personne1); + ``` -<ol> - <li>Par exemple, vous pouvez tester le code suivant : - <pre class="brush: js">personne1.constructor -personne2.constructor</pre> +2. En réalité `create()` se contente de créer un nouvel objet à partir d'un prototype spécifique. Dans cet exemple, `personne2` est créé à partir de `personne1` qui agit en tant que prototype. Vous pouvez le vérifier via : - <p>Chaque commande devrait renvoyer le constructeur <code>Personne()</code> étant donné qu'il a permis d'instancier ces objets.</p> + ```js + person2.__proto__ + ``` - <p>Une astuce qui peut s'avérer utile est d'ajouter des parenthèses à la fin de l'attribut <code>constructor</code> pour le transformer en méthode. Après tout, le constructeur est une fonction que l'on peut appeler si besoin. Il faut juste utiliser le mot-clé <code>new</code> pour signifier que l'on souhaite construire un objet.</p> - </li> - <li>Par exemple : - <pre class="brush: js">var personne3 = new personne1.constructor('Karen', 'Stephenson', 26, 'femme', ['jouer de la batterie', 'escalade']);</pre> - </li> - <li>Vous pouvez désormais essayer d'accéder aux propriétés de personne3 : - <pre class="brush: js">personne3.prenom -personne3.age -personne3.bio()</pre> - </li> -</ol> +Cela renverra l'objet `personne1`. -<p>Ça fonctionne bien. A priori, ce n'est pas la manière la plus simple de créer un objet et vous n'aurez pas à l'utiliser souvent. En revanche, ça peut vous débloquer quand vous devez créer une nouvelle instance et que vous ne disposez pas facilement du constructeur d'origine.</p> +## L'attribut _constructor_ -<p>L'attribut <code><a href="/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code> possède d'autres intérêts. Par exemple, si vous disposez du nom d'une instance objet vous pouvez utiliser le code suivant pour renvoyer le nom de son constructeur :</p> +Chaque fonction possède un attribut prototype dont la valeur est un objet contenant un attribut [`constructor`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor). L'attribut `constructor` renvoie vers la méthode constructrice utilisée. Nous allons le voir dans la section suivante, les attributs définis dans l'attribut `Personne.prototype` deviennent disponibles pour toutes les instances créées à partir du constructeur `Personne()`. De cette manière, l'attribut `constructor` est aussi disponible au sein de `personne1` et `personne2`. -<pre class="brush: js">instanceName.constructor.name</pre> +1. Par exemple, vous pouvez tester le code suivant : -<p>Vous pouvez essayer :</p> + ```js + personne1.constructor + personne2.constructor + ``` -<pre class="brush: js">personne1.constructor.name</pre> + Chaque commande devrait renvoyer le constructeur `Personne()` étant donné qu'il a permis d'instancier ces objets. -<h2 id="Modifions_les_prototypes">Modifions les prototypes</h2> + Une astuce qui peut s'avérer utile est d'ajouter des parenthèses à la fin de l'attribut `constructor` pour le transformer en méthode. Après tout, le constructeur est une fonction que l'on peut appeler si besoin. Il faut juste utiliser le mot-clé `new` pour signifier que l'on souhaite construire un objet. -<p>Voyons au travers d'un exemple comment modifier l'attribut <code>prototype</code> d'un constructeur (les méthodes ajoutées au prototype seront alors disponibles pour toutes les instances créées à partir du constructeur).</p> +2. Par exemple : -<ol> - <li>Revenons à notre exemple <a href="https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">oojs-class-further-exercises.html</a> et faisons une copie local du <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">code source</a>. En dessous du JavaScript existant, vous pouvez ajouter le code suivant, ce qui aura pour effet d'ajouter une nouvelle méthode à l'attribut <code>prototype</code> du constructeur : + ```js + var personne3 = new personne1.constructor('Karen', 'Stephenson', 26, 'femme', ['jouer de la batterie', 'escalade']); + ``` - <pre class="brush: js">Personne.prototype.aurevoir = function() { - alert(this.nom.prenom + ' est sorti. Au revoir !'); -}</pre> - </li> - <li>Enregistrez vos modifications et chargez la page dans votre navigateur. Vous pouvez ensuite entrer le code suivant dans la console : - <pre class="brush: js">personne1.aurevoir();</pre> - </li> -</ol> +3. Vous pouvez désormais essayer d'accéder aux propriétés de personne3 : + + ```js + personne3.prenom + personne3.age + personne3.bio() + ``` + +Ça fonctionne bien. A priori, ce n'est pas la manière la plus simple de créer un objet et vous n'aurez pas à l'utiliser souvent. En revanche, ça peut vous débloquer quand vous devez créer une nouvelle instance et que vous ne disposez pas facilement du constructeur d'origine. + +L'attribut [`constructor`](/fr/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) possède d'autres intérêts. Par exemple, si vous disposez du nom d'une instance objet vous pouvez utiliser le code suivant pour renvoyer le nom de son constructeur : + +```js +instanceName.constructor.name +``` + +Vous pouvez essayer : + +```js +personne1.constructor.name +``` + +## Modifions les prototypes + +Voyons au travers d'un exemple comment modifier l'attribut `prototype` d'un constructeur (les méthodes ajoutées au prototype seront alors disponibles pour toutes les instances créées à partir du constructeur). + +1. Revenons à notre exemple [oojs-class-further-exercises.html](https://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html) et faisons une copie local du [code source](https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html). En dessous du JavaScript existant, vous pouvez ajouter le code suivant, ce qui aura pour effet d'ajouter une nouvelle méthode à l'attribut `prototype` du constructeur : + + ```js + Personne.prototype.aurevoir = function() { + alert(this.nom.prenom + ' est sorti. Au revoir !'); + } + ``` + +2. Enregistrez vos modifications et chargez la page dans votre navigateur. Vous pouvez ensuite entrer le code suivant dans la console : + + ```js + personne1.aurevoir(); + ``` -<p>Vous devriez voir une fenêtre s'afficher avec un message contenant le nom de la personne. Cette fonctionalité est utile, mais là où ça devient plus intéressant c'est que la chaine de prototypage a été mis à jour dynamiquement, rendant automatiquement cette méthode disponible à l'ensemble des instances existantes.</p> +Vous devriez voir une fenêtre s'afficher avec un message contenant le nom de la personne. Cette fonctionalité est utile, mais là où ça devient plus intéressant c'est que la chaine de prototypage a été mis à jour dynamiquement, rendant automatiquement cette méthode disponible à l'ensemble des instances existantes. -<p>Revoyons en détail ce qui s'est passé : tout d'abord, nous avons défini le constructeur. Ensuite, nous avons instancié un objet à partir du constructeur. Enfin, nous avons ajouté une nouvelle méthode au prototype du construceur :</p> +Revoyons en détail ce qui s'est passé : tout d'abord, nous avons défini le constructeur. Ensuite, nous avons instancié un objet à partir du constructeur. Enfin, nous avons ajouté une nouvelle méthode au prototype du construceur : -<pre class="brush: js">function Personne(prenom, nom, age, genre, interets) { +```js +function Personne(prenom, nom, age, genre, interets) { // définition des attrbuts et des méthodes @@ -198,27 +225,31 @@ var personne1 = new Personne('Tammi', 'Smith', 32, 'neutre', ['musique', 'ski', Personne.prototype.aurevoir= function() { alert(this.nom.prenom + ' est sorti. Au revoir !'); -}</pre> +} +``` -<p>Même si nous l'avons déclaré après, la méthode <code>aurevoir()</code> est disponible pour l'instance <code>personne1</code>. Son existence a mis à jour dynamiquement les méthodes de l'instance. Cela démontre ce que nous expliquions plus haut au sujet de la chaine de prototypage : le navigateur la parcourt de manière ascendante. Ainsi, il est possible de trouver directement les méthodes qui n'ont pas été définies au niveau de l'instance, plutôt que de les recopier au sein de l'instance. Cela nous permet de bénéficier d'un système extensible de manière simple et élégante.</p> +Même si nous l'avons déclaré après, la méthode `aurevoir()` est disponible pour l'instance `personne1`. Son existence a mis à jour dynamiquement les méthodes de l'instance. Cela démontre ce que nous expliquions plus haut au sujet de la chaine de prototypage : le navigateur la parcourt de manière ascendante. Ainsi, il est possible de trouver directement les méthodes qui n'ont pas été définies au niveau de l'instance, plutôt que de les recopier au sein de l'instance. Cela nous permet de bénéficier d'un système extensible de manière simple et élégante. -<div class="note"> -<p><strong>Note :</strong> Si vous avez du mal à faire fonctionner cet exemple, vous pouvez jeter un œil au notre (<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-prototype.html">oojs-class-prototype.html</a>, voir la <a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-prototype.html">démo</a>)</p> -</div> +> **Note :** Si vous avez du mal à faire fonctionner cet exemple, vous pouvez jeter un œil au notre ([oojs-class-prototype.html](https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-prototype.html), voir la [démo](https://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-prototype.html)) -<p>Vous verrez peu d'attributs définis au sein de l'attribut <code>prototype</code>, pour la simple et bonne raison que c'est assez peu pratique. Vous pourriez avoir :</p> +Vous verrez peu d'attributs définis au sein de l'attribut `prototype`, pour la simple et bonne raison que c'est assez peu pratique. Vous pourriez avoir : -<pre class="brush: js">Personne.prototype.nomComplet = 'Bob Smith';</pre> +```js +Personne.prototype.nomComplet = 'Bob Smith'; +``` -<p>Mais ce n'est pas très pratique, étant donné qu'une personne ne sera peut-être pas appelée de cette manière. Il est plus cohérent de construire le nom entier en combinant le nom et le prénom :</p> +Mais ce n'est pas très pratique, étant donné qu'une personne ne sera peut-être pas appelée de cette manière. Il est plus cohérent de construire le nom entier en combinant le nom et le prénom : -<pre class="brush: js">Personne.prototype.nomComplet = this.nom.prenom + ' ' + this.nom.nom;</pre> +```js +Personne.prototype.nomComplet = this.nom.prenom + ' ' + this.nom.nom; +``` -<p>Ça ne fonctionnera toujours pas. En effet, <code>this</code> aura une portée globale et ne sera pas dans le contexte de la fonction. En appelant cet attribut, nous aurions alors <code>undefined undefined</code>. Dans les exemples précédents sur le prototype, nous arrivions à obtenir quelque chose de fonctionnel puisque nous étions au sein d'une méthode, qui sera utilisée par l'instance. Il est donc possible de définir des attributs invariables au niveau du prototype mais de manière générale, il est préférable de les définir au sein du constructeur.</p> +Ça ne fonctionnera toujours pas. En effet, `this` aura une portée globale et ne sera pas dans le contexte de la fonction. En appelant cet attribut, nous aurions alors `undefined undefined`. Dans les exemples précédents sur le prototype, nous arrivions à obtenir quelque chose de fonctionnel puisque nous étions au sein d'une méthode, qui sera utilisée par l'instance. Il est donc possible de définir des attributs invariables au niveau du prototype mais de manière générale, il est préférable de les définir au sein du constructeur. -<p>En fait, on retrouve généralement la chose suivante : les attributs sont définis dans le constructeur, tandis que les méthodes sont définies au niveau du prototype. Cela rend le code plus simple à lire puisque les attributs sont groupés et les méthodes structurées en blocs distincts. Par exempe :</p> +En fait, on retrouve généralement la chose suivante : les attributs sont définis dans le constructeur, tandis que les méthodes sont définies au niveau du prototype. Cela rend le code plus simple à lire puisque les attributs sont groupés et les méthodes structurées en blocs distincts. Par exempe : -<pre class="brush: js">// Constructeur avec définition des attributs +```js +// Constructeur avec définition des attributs function Test(a, b, c, d) { // définition des attributs @@ -232,14 +263,15 @@ Test.prototype.x = function() { ... } Test.prototype.y = function() { ... } -// etc...</pre> +// etc... +``` -<p>Ce type d'implémentation peut être observée dans l'appli <a href="https://github.com/zalun/school-plan-app/blob/master/stage9/js/index.js">plan d'école</a> de Piotr Zalewa par exemple.</p> +Ce type d'implémentation peut être observée dans l'appli [plan d'école](https://github.com/zalun/school-plan-app/blob/master/stage9/js/index.js) de Piotr Zalewa par exemple. -<h2 id="Résumé">Résumé</h2> +## Résumé -<p>Cet article a traité des prototypes objet en JavaScript, en incluant la chaine de prototypage qui permet aux objets d'hériter des propriétés d'un autre objet. Nous avons aussi vu l'attribut prototype et comment nous pouvons l'utiliser pour ajouter des méthodes au constructeur.</p> +Cet article a traité des prototypes objet en JavaScript, en incluant la chaine de prototypage qui permet aux objets d'hériter des propriétés d'un autre objet. Nous avons aussi vu l'attribut prototype et comment nous pouvons l'utiliser pour ajouter des méthodes au constructeur. -<p>Dans le prochain article, nous verrons comment appliquer l'héritage entre deux de nos propres objets.</p> +Dans le prochain article, nous verrons comment appliquer l'héritage entre deux de nos propres objets. -<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</p> +{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}} |