Introduction au Javascript
Introduction
Le Javascript est un langage qui rend les pages web plus interactives. Un peu comme le CSS, le Javascript peut s’écrire dans une balise <script> dans le HTML, mais il est préférable de l’écrire dans un fichier à part.
Dans un fichier HTML :
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="script.js" defer></script>
<title>Document</title>
</head>
<body>
<h1>Découverte du Javascript</h1>
</body>
</html>
<script>: du Javascriptsrc="script.js": récupère le contenu du fichierscript.jsdefer: exécute le script après le chargement duHTML
Et dans un fichier script.js :
alert("Bonjour !");
Ouvrez cette page sur un navigateur, vous devriez voir une alerte “Bonjour !”.
Lien entre HTML et Javascript
Les bases
Depuis du Javascript, il est possible de récupérer une balise du HTML à partir de son identifiant (id). Pour ce faire on utilise la fonction :
const div = document.getElementById("my-div");
La fonction va chercher dans le HTML une balise avec l’attribut id="my-div" et l’enregistrer dans notre constante div. Il s’agit d’un objet, avec des champs à l’intérieur, il est par exemple possible de récupérer le contenu HTML dans la <div> comme ceci :
const html = div.innerHTML;
console.log(html);
Si la <div> contient quelque chose, il sera affiché dans la console.
Exemple de HTML pour tester :
<div id="my-div">
<p>Hello world!</p>
</div>
La console devrait vous afficher <p>Hello world!</p>.
On va mettre ça dans une fonction pour éviter de réécrire plusieurs fois la même chose plus tard. L’objectif est d’avoir juste besoin de lui donner l’identifiant, et la fonction s’occupe de nous renvoyer le innerHTML de la balise concernée :
function getHtmlOf(id) {
const element = document.getElementById(id);
const html = element.innerHTML;
return html;
}
const html = getHtmlOf("my-div");
console.log(html);
Essayer de mettre un identifiant qui n’existe pas, et vous verrez que le Javascript plante. Car, si aucune balise n’est trouvée, notre element vaut null et l’erreur aura lieu quand on essaye de regarder un champ innerHTML dans null.
Il faut donc ajouter une sécurité, si jamais on ne trouve pas de balise, on affiche un message d’erreur et on renvoie null :
function getHtmlOf(id) {
const element = document.getElementById(id);
// si element est null
if (element === null) {
// on affiche une alerte
alert(`Aucune balise avec l'attribut : id="${id}"`);
// on renvoie null
return null;
}
const html = element.innerHTML;
return html;
}
Quand une fonction atteint un return, elle ne fait plus rien après, elle s’arrête directement. C’est pourquoi le return null; à la fin de la condition empêche l’exécution des lignes qui suivent.
Les <input>
Maintenant, notre balise ne sera pas n’importe quelle balise mais un <input>, car il a un attribut intéressant : value, c’est littéralement ce que vous écrivez dans l’<input> qui est contenu dans cet attribut.
Voici comment on peut le récupérer :
function getValueOf(id) {
const input = document.getElementById(id);
if (input === null) {
alert(`Aucun <input> avec l'attribut : id="${id}"`);
return null;
}
return input.value;
}
Mais il ya un problème, si on appelle cette fonction au chargement de la page, l’<input> sera vide, il nous faut un moyen pour pouvoir appeler la fonction quand on en a besoin. Et pour ça, on a les boutons, avec un attribut qui permet d’exécuter du code quand on clique dessus, l’attribut onclick. Exemple :
<button onclick="console.log('Hello world!')">Clique moi</button>
En cliquant sur ce bouton, vous devriez voir apparaître dans la console des Hello world!.
On utilise console.log() dans le onclick, mais on peut très bien utiliser une fonction déclarée dans notre script.js (tant que le fichier est chargé), on peut donc ajouter dans notre script.js une fonction qui récupère la valeur et l’affiche au lieu de le faire au chargement du fichier :
function displayValue() {
const value = getValueOf("my-input");
console.log(value);
}
Et dans notre HTML :
<input id="my-input" />
<button onclick="displayValue()">Afficher la valeur dans la console</button>
Qu’est-ce qui se passe quand on on clique sur le bouton :
- on appelle notre fonction
displayValue() - qui elle-même appelle
getValueOf() - qui elle-même appelle
document.getElementById() - qui nous renvoie l’élément
- on vérifier qu’il n’est pas
null - puis on renvoie l’attribut
valuede cet élément displayValue()récupère le résultat- puis l’affiche dans la console avec le
console.log()
Mettre à jour du HTML
On va maintenant voir un peu plus ce qu’on peut faire avec l’attribut innerHTML, ajouter cette balise dans votre HTML :
<ul id="list"></ul>
Et dans votre Javascript :
function insertIn(id, html) {
const element = document.getElementById(id);
if (!element) {
alert(`Aucune balise avec l'attribut id="${id}"`);
return;
}
element.innerHTML += html;
}
Cette fonction permet d’insérer de l’HTML dans une balise déjà existante. On a vu que innerHTML contenait l’HTML à l’intérieur de la balise :
innerHTML = html;écrase l’ancien contenu et le remplace parhtmlinnerHTML += html;garde l’ancien contenu et y ajoutehtmlà la suite
On va remplacer notre fonction displayValue() par une fonction addToList() qui :
- récupérera la valeur de l’
input(commedisplayValue()) - créera du HTML à partir de la valeur récupérée
- puis ajoutera ce HTML à notre liste
Voici la fonction :
function addToList() {
const value = getValueOf("my-input");
const html = `<li>${value}</li>`;
insertIn("list", html);
}
Il vous suffit juste de changer l’attribut onclick du bouton pour que lorsque l’on clique, ça appelle la fonction addToList().
Exercice - Miroir
Écrivez dans votre HTML un élément <p> et <input>, écrivez dans le JS le code nécessaire à ce que le contenu de l’<input> s’inscrive automatiquement dans le <p>.
Il existe un attribut très similaire à onclick, c’est oninput, au lieu de s’activer lorsque l’on clique, il s’active dès lors qu’il a un changement, dans un <input>, oninput s’active à chaque lettre tapée.
l’objectif de cette exercice est :
- d’avoir un
<input>et un<p> - tout ce que j’écris dans l’
<input>est automatiquement écrit dans le<p> <input>et<p>doivent donc constamment avoir le même texte à l’intérieur
Le localStorage
Le localStorage est une zone de stockage dans le navigateur. Elle est persistante, si on sauvegarde une valeur dedans, la valeur restera sauvegardée même si :
- on rafraîchie l’onglet
- on ferme l’onglet
- on ferme le navigateur
- on éteint l’ordinateur
Voici un set de fonctions utilitaires pour vous faciliter l’utilisation de ce localStorage :
function save(key, value) {
const stringifiedValue = JSON.stringify(value);
localStorage.setItem(key, stringifiedValue);
}
function get(key) {
const stringifiedValue = localStorage.getItem(key);
const value = JSON.parse(stringifiedValue);
return value;
}
function remove(key) {
localStorage.removeItem(key);
}
Exercice - Sauvegarde
Reprenez votre code de l’exercice miroir, ajouter un bouton pour sauvegarder le contenu de l’<input>. On doit pouvoir fermer l’onglet et le rouvrir, et réécrire l’ancien contenu dans l’<input>.
Les tableaux
Un tableau en Javascript, c’est plusieurs éléments réunis ensemble. Voici un exemple avec un tableau de chaînes de caractères qu’on affiche ensuite dans la console :
// déclaration d'un tableau
const arr = ["bonjour", "tout", "le"];
// on ajoute un élément à la fin du tableau
arr.push("monde");
// arr vaut maintenant : ["bonjour", "tout", "le", "monde"];
// une boucle qui va se balader dans tout le tableau
for (const word of arr) {
// word est une variable qui contiendra chacun des éléments du tableau 1 par 1
console.log(word);
}
Exercice - La liste de courses
Proposez une interface permettant d’avoir une liste de courses, on doit pouvoir :
- remplir un champ et cliquer sur un bouton “Ajouter”
- voir notre liste se mettre à jour dès lors qu’on clique sur le bouton
- fermer l’onglet et l’ouvrir à nouveau et toujours avoir notre liste de courses
API
Les APIs (Application Programming Interface) permettent à des applications de demander un service ou des données à une autre application, sans avoir besoin de connaître son fonctionnement interne.
Analogie
Au restaurant, j’ai :
- le menu qui me permet de savoir ce que je peux commander
- un serveur, à qui je peux demander ce que je veux commander
Je n’ai pas besoin de savoir comment fonctionne le restaurant, je regarde juste la carte, je demande au serveur puis je reçois mon plat.
Une API, c’est le même principe, vous aurez :
- une documentation (le menu) expliquant les différents endpoints (les plats) que vous pouvez utiliser (commander)
- un serveur (cette fois ci au sens informatique), auquel je peux appeler via ces endpoints (commander les plats)
Je n’ai toujours pas besoin de savoir comment ça fonctionne derrière, je reçois juste la donnée, et j’en fais ce que je veux après.
Voici un exemple avec une API sur les pokemons, essayez là ! Par exemple, coller dans l’URL de votre navigateur https://pokeapi.co/api/v2/pokemon/pikachu (et activez le pretty-print si votre navigateur le propose).
L’asynchrone et appel d’API
En Javascript, certaines fonctions peuvent être lentes, par exemple, la fonction fetch() est utilisée pour faire des appels à une API (exemple : fetch("https://pokeapi.co/api/v2/pokemon/pikachu")), mais la réponse, même si très rapide, n’est pas instantanée.
Il faut donc dire au programme d’attendre la réponse avec le mot-clé await. Ce mot-clé ne peut être utilisé que dans des fonctions asynchrones (async function ...).
Ce qui est important à retenir, c’est que pour utiliser la fonction call(), vous devez être dans une fonction asynchrone (async function ...) et utiliser le mot-clé await devant l’appel à call() :
async function call(url) {
const response = await fetch(url);
const data = await response.json();
return data;
}
async function test() {
const pikachu = await call("https://pokeapi.co/api/v2/pokemon/pikachu");
console.log(pikachu);
}
test();
Tableau de pokémons
On peut récupérer une liste de pokémons comme ceci :
async function test() {
const response = await call("https://pokeapi.co/api/v2/pokemon");
const pokemons = response.results;
console.log(pokemons);
}
Pokeapi nous renvoie un objet contenant les champs :
next: une URL à utiliser pour avoir la page suivante (nulls’il n’y en a pas)previous: une URL à utiliser pour avoir la page précédente (nulls’il n’y en a pas)results: la liste des pokémons de la page actuelle (son et une URL pour avoir plus d’informations)
Exemple de cet objet :
{
"count": 1350,
"next": "https://pokeapi.co/api/v2/pokemon?offset=2&limit=2",
"previous": null,
"results": [
{
"name": "bulbasaur",
"url": "https://pokeapi.co/api/v2/pokemon/1/"
},
{
"name": "ivysaur",
"url": "https://pokeapi.co/api/v2/pokemon/2/"
}
}
Toutes Les APIs ne renvoient pas forcément ça, Pokeapi nous simplifie la vie.
On peut alors afficher une liste avec les noms des pokémons de la page actuelle :
for (const pokemon of pokemons) {
const li = `<li>${pokemon.name}</li>`;
list.innerHTML += li;
}