Outils pour utilisateurs

Outils du site


nsi:premiere:javascript

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
nsi:premiere:javascript [2021/12/02 15:50] goupillwikinsi:premiere:javascript [2025/01/09 18:13] (Version actuelle) – [Exemple] yadam
Ligne 7: Ligne 7:
 JS permet de capter ces événements et de déclencher un programme. Un clic de souris capté par JS permettra d'ajouter un élément, dérouler un menu, changer une couleur, valider une saisie, envoyer un message vers le serveur... JS permet de capter ces événements et de déclencher un programme. Un clic de souris capté par JS permettra d'ajouter un élément, dérouler un menu, changer une couleur, valider une saisie, envoyer un message vers le serveur...
  
-Pour l'ensemble de ce cours, vous aurez besoin des fichiers contenus dans <wrap todo>fichier zip</wrap>. Décompressez cette archive dans un dossier local.+Pour l'ensemble de ce cours, vous aurez besoin des fichiers contenus dans {{ :nsi:premiere:web:js.zip |}}. Décompressez cette archive dans un dossier local.
  
 ===== Premier événement ===== ===== Premier événement =====
Ligne 15: Ligne 15:
 <code html linenums> <code html linenums>
 <!DOCTYPE html> <!DOCTYPE html>
-<html>+<html>  <!-- page_1.html -->
   <head>   <head>
     <meta charset="utf-8">     <meta charset="utf-8">
Ligne 49: Ligne 49:
 <!DOCTYPE html> <!DOCTYPE html>
 <html> <html>
-  <head>+  <head>  <!-- page_2.html -->
     <meta charset="utf-8">     <meta charset="utf-8">
     <title>page 2</title>     <title>page 2</title>
Ligne 87: Ligne 87:
 <code html linenums> <code html linenums>
 <!DOCTYPE html> <!DOCTYPE html>
-<html>+<html>  <!-- page_3.html -->
   <head>   <head>
     <meta charset="utf-8">     <meta charset="utf-8">
Ligne 96: Ligne 96:
         function addMessage(message){         function addMessage(message){
           nombreClicks++;           nombreClicks++;
-          divMessages = document.getElementById("divMessages"); +          let divMessages = document.getElementById("divMessages"); 
-          nouvelleLigne = nombreClicks+" : "+message; +          let nouvelleLigne = nombreClicks+" : " + message; 
-          nodeText = document.createTextNode(nouvelleLigne); +          let nodeText = document.createTextNode(nouvelleLigne); 
-          nodeParagraph = document.createElement("p");+          let nodeParagraph = document.createElement("p");
           nodeParagraph.appendChild(nodeText);           nodeParagraph.appendChild(nodeText);
           divMessages.appendChild(nodeParagraph);           divMessages.appendChild(nodeParagraph);
Ligne 112: Ligne 112:
     <div class="carre bleu" onclick="addMessage('clic sur bleu');"></div>     <div class="carre bleu" onclick="addMessage('clic sur bleu');"></div>
   </body>   </body>
 +  <div id="divMessages"></div>
 </html> </html>
 </code> </code>
Ligne 127: Ligne 128:
 <code html linenums> <code html linenums>
 <!DOCTYPE html> <!DOCTYPE html>
-<html>+<html>  <!-- page_4.html -->
   <head>   <head>
     <meta charset="utf-8">     <meta charset="utf-8">
Ligne 151: Ligne 152:
 // Fichier script mis à part // Fichier script mis à part
 function addMessage(message){ function addMessage(message){
-  nodeMessages = document.getElementById("listeMessages"); +  let nodeMessages = document.getElementById("listeMessages"); 
-  nouvelleLigne = message; +  let nouvelleLigne = message; 
-  nodeText = document.createTextNode(nouvelleLigne); +  let nodeText = document.createTextNode(nouvelleLigne); 
-  nodeLi = document.createElement("li");+  let nodeLi = document.createElement("li");
   nodeLi.appendChild(nodeText);   nodeLi.appendChild(nodeText);
   nodeMessages.appendChild(nodeLi);   nodeMessages.appendChild(nodeLi);
Ligne 179: Ligne 180:
 <code html linenums> <code html linenums>
 <!DOCTYPE html> <!DOCTYPE html>
-<html>+<html>  <!-- page_5.html -->
   <head>   <head>
     <meta charset="utf-8">     <meta charset="utf-8">
Ligne 199: Ligne 200:
 </code> </code>
  
 +Le html ne contient plus aucun code JS. Tout le JS est dans le fichier ''script_5.js''.
 +
 +<code javascript linenums>
 +// script_5.js
 +// Fichier script mis à part
 +function addMessage(message){
 +  let nodeMessages = document.getElementById("listeMessages");
 +  let nouvelleLigne = message;
 +  let nodeText = document.createTextNode(nouvelleLigne);
 +  let nodeLi = document.createElement("li");
 +  nodeLi.appendChild(nodeText);
 +  nodeMessages.appendChild(nodeLi);
 +}
 +
 +document.getElementById("bouton_rouge").addEventListener(
 +  "click",
 +  function(){ addMessage("clic sur rouge"); });
 +document.getElementById("bouton_bleu").addEventListener(
 +  "click",
 +  function(){ addMessage("clic sur bleu"); });
 +document.getElementById("bouton_vert").addEventListener(
 +  "click",
 +  function(){ addMessage("clic sur vert"); });
 +</code>
 +
 +Remarquez en particulier les lignes 12-20 : En ligne 12-14 par exemple, on accède à l'élément d'id ''%%""bouton_rouge""%%''. Cet élément est bien présent dans le fichier html, en ligne 11. On demande ce nœud d'**écouter l'événement** clic de souris -- //addEventListener//. On comprend que dès lors, un clic de souris sur cet élément déclenchera une fonction.
 +
 +<WRAP box>**À faire :** ouvrez ''page_5.html'' dans un navigateur. Constatez que cela ne fonctionne pas -- pensez à observer la console.</WRAP>
 +
 +Voici où est le problème : Le script ''script_5.js'' est déclaré en début de page html. Il est chargé dès le début alors que le contenu ''%%<body>%%'' n'es pas encore chargé dans le navigateur. Le nœud d'id ''%%""bouton_rouge""%%'' n'existe pas encore dans le DOM.
 +
 +La solution est de déclarer le script à la fin de ''%%<body>%%'' et pas dans ''%%<head>%%''.
 +
 +<WRAP box>**À faire :** faites-le et constatez que maintenant, ça fonctionne.</WRAP>
 +
 +===== D'autres événements =====
 +
 +Il y a d'autres événements que //click// !
 +
 +  * ''load'' : quand l'élément est chargé.\\ On l'associe souvent à ''%%<body>%%'', permet d'attendre que la page est bien chargée.
 +  * ''click'' : déjà vu, c'est le clic souris.
 +  * ''dblclick'' : double clic.
 +  * ''mouseover'' : quand la souris passe au-dessus.
 +  * ''mouseout'' : quand la souris arrête d'être au-dessus.
 +  * ''keypress'' : quand on appuie sur une touche pour entrer un caractère. Utile dans un champ de saisie.
 +  * ''input'' : quand le contenu d'un champ de saisie texte est modifié, à chaque entrée de caractère.
 +  * ''change'' : quand le contenu d'un champ de saisie est modifié et ce changement est validé (un peu différent du précédent)
 +  * ''focus'' : quand l'élément gagne le //focus//. Dans une page où on trouve plusieurs zones de saisie, celle dans laquelle on est en train d'écrire est celle qui a le focus.
 +  * ''blur'' : perte du focus.
 +  * ''submit'' : dans le cas d'un formulaire (ensemble de champ de saisie avec un bouton "soumettre" ou "Envoyer" ou "ok" ou...) quand le formulaire est validé et peut-être envoyé.
 +
 +<WRAP tip>Il y a beaucoup d'événements, inutile de les connaître par cœur... Internet est plein de références permettant de trouver tout ce que l'on a besoin de savoir. Par exemple [[https://developer.mozilla.org/fr/|MDN web docs]].</WRAP>
 +
 +==== Exemple ====
 +
 +<code html linenums>
 +<!DOCTYPE html>
 +<html>  <!-- page_6.html -->
 +  <head>
 +    <meta charset="utf-8">
 +    <title>page 6</title>
 +    <link rel="stylesheet" type="text/css" href="styles.css">
 +  </head>
 +  <body>
 +    <h2>Démonstration</h2>
 +    <input type="text" id="champ_saisie">
 +
 +    <div class="messages"><b>Zone pour la réponse</b>
 +        <div id="zone_de_reponse"></div>
 +    </div>
 +    <script type="text/javascript" src="script_6.js"></script>
 +  </body>
 +</html>
 +</code>
 +
 +Dans ce code, ligne 10, on a défini :
 +<code html linenums:10>
 +<input type="text" id="champ_saisie">
 +</code>
 +
 +Ce champ de saisie est lié, dans le script ''script_6.js'' en ligne 3, à l'événement ''input''.
 +
 +<code javascript linenums>
 +// script_6.js
 +let villes = ["Paris", "Marseille", "Lyon", ... ]; // j'abrège...
 +
 +document.getElementById("champ_saisie").addEventListener("input", saisieInput)
 +
 +// Il y a une suite dans script_6.js
 +</code>
 +
 +<WRAP box>**À faire :** on aimerait que quand il n'y a aucun résultat apparaisse un message comme //Aucun résultat//. Faites la modification dans ''script_6.js''.</WRAP>
 +
 +===== event =====
 +
 +Quand l'événement appelle la fonction, il lui transmet automatiquement un argument. On peut l'appeler ''e''. Il contient un objet représentant l'événement lui même.
 +
 +Par exemple, dans ''page_7.html'',
 +
 +<code html linenums:9>
 +<h2>event</h2>
 +<input type="button" id="bouton_event1" value="Cliquez-moi !">
 +<input type="button" id="bouton_event2" value="Cliquez-moi !">
 +</code>
 +
 +Associé à, dans ''script_7.js''
 +<code javascript linenums:1>
 +// script_7.js
 +function clickButton(e){
 +    console.log(e);
 +}
 +
 +document.getElementById("bouton_event1").addEventListener("click", clickButton );
 +document.getElementById("bouton_event2").addEventListener("click", clickButton );
 +</code>
 +
 +<WRAP box>**À faire :** ouvrez ''page_7.html'' dans un navigateur, ouvrez la console et cliquez sur l'un des boutons de la section //event//. Observez ce qui s'affiche en console.</WRAP>
 +
 +<WRAP tip>L'objet ''event'' qui apparaît en console a beaucoup d'attributs. Ils renseignent sur la nature de l'événement. Par exemple, l'attribut ''target'' nous indique quel nœud du DOM est la cible de cet événement. Ici, deux boutons sont attachés au même événement. L'attribut ''target'' nous permet de savoir lequel a été cliqué.</WRAP>
 +
 +<WRAP box>**À faire :** modifiez la fonction ''clickButton'' dans ''script_7.js'' pour que le texte du bouton cliqué change, passant de ''%%"Cliquez-moi !"%%'' à ''%%"Cliquez-moi ! (1)"%%'' au premier clic, puis ''%%"Cliquez-moi ! (2)"%%'' et ainsi de suite.</WRAP>
 +
 +===== this =====
 +
 +Le mot clé ''this'' désigne celui qui appelle la fonction. On retrouve ce mot clé dans les différents langages sous différentes formes. En Python, on utilise plutôt ''self''.
 +
 +<code html linenums:9>
 +<h2>this</h2> <!-- page_8.html -->
 +<input type="button" id="bouton_this_gauche" value="Je suis le bouton de gauche">
 +<input type="button" id="bouton_this_droite" value="Je suis le bouton de droite">
 +</code>
 +
 +<code javascript linenums:1>
 +// script_8.js
 +function quiSuisJe(e){
 +    console.log(this.value);
 +}
 +
 +document.getElementById("bouton_this_gauche").addEventListener("click", quiSuisJe );
 +document.getElementById("bouton_this_droite").addEventListener("click", quiSuisJe );
 +</code>
 +
 +Dans ce code, le même événement peut être appelé depuis deux boutons -- //problème semblable au précédent//. À l'intérieur de la fonction, le mot clé ''this'' désigne le contexte de l'événement. Quand on appuie sur ''%%bouton_this_gauche%%'', le contexte est ''%%bouton_this_gauche%%''.
 +
 +<WRAP box>**À faire :** testez en visualisant la console.
 +Modifiez en ajoutant après les boutons une balise ''%%<img>%%'' et modifiez la fonction ''quiSuisJe'' pour que le bouton de gauche provoque l'affichage de ''pikachu.jpeg'' dans la balise ''%%<img>%%'' et le bouton droit provoque l'affichage de ''salamèche.jpeg''. //Les fichiers images sont dans l'archive fournie.//</WRAP>
 +
 +===== Détourner les balises =====
 +
 +Quand on conçoit une page dynamique, on n'a pas vraiment besoin de recharger une page web comme cela se faisait dans le passé. Le clic sur un lien n'a pas besoin de demander au serveur une nouvelle page html. Au contraire, le lien hypertexte ''%%<a>%%'' déclenche un événement et c'est le script qui se charge de construire la nouvelle page. Le lien est alors détourné de sa fonction première qui est de demander au serveur de fournir une nouvelle page.
 +
 +Pour une bonne conception, on utilise tout de même la balise ''%%<a>%%'' :
 +  * on peut parcourir les liens avec le clavier (touche TAB),\\ //c'est une fonctionnalité des navigateurs//
 +  * les outils d'accessibilité (//déficience visuelle par ex.//) détectent les liens.
 +
 +Donc on veut utiliser une balise ''%%<a>%%'' même si on ne veut pas qu'elle fonctionne comme une balise ''%%<a>%%'' normal... Voyons un exemple.
 +
 +<code html linenums:9>
 +<h2>Détourner les balises</h2> <!-- page_9.html -->
 +<a href="fausse_page.html" id="faux_lien">Mon faux lien</a>
 +</code>
 +
 +<code javascript linenums>
 +// script_9.js
 +function click_faux_lien(e){
 +    alert('au lieu d\'un lien vous avez une popup !');
 +    e.preventDefault();
 +}
 +
 +document.getElementById("faux_lien").addEventListener("click", click_faux_lien );
 +</code>
 +
 +Dans ce script, la balise ''%%<a>%%'' est liée à un événement qui provoque l'affichage d'un popup avec ''alert''. En ligne 4, ''e.preventDefault()'' commande de ne pas faire ce qui devrait se faire normalement dans ce cas. Cela revient à demander que la balise ''%%<a>%%'' ne demande pas le chargement de la page ''%%"fausse_page.html"%%'' qui d'ailleurs n'existe pas.
 +
 +===== Bibliothèques, exemple de jQuery =====
 +
 +Les fonctions de JS et surtout celles qui permettent d'accéder au éléments du DOM sont assez limitées. Elles se développent mais pas toujours suffisamment. De plus, on doit faire avec les différences entre //Firefox//, //Chrome//, //Edge//, //Safari//...
 +
 +Le plus souvent on préfère utiliser une bibliothèque qui ajoute des fonctionnalités. La plus populaire (de loin) est [[https://jquery.com/|jQuery]]. J'ai ajouté ''jQuery.3.4.1'' à ''page_10.html''. Le fichier **minifié** -- //c'est une façon spéciale de compresser les fichiers JS// -- ne pèse même pas 100 ko. Ce n'est rien au regard de tout ce qu'apporte jQuery. Par exemple, dans un site web, s'il y a un beau menu déroulant, vous pouvez être certains que jQuery est utilisé.
 +
 +Pour illustrer l'utilisation de jQuery, dans ''page_10.html'',
 +
 +<code html linenums:10>
 +<h2>Des bibliothèques</h2> <!-- page_10.html -->
 +<div class="carre rouge"></div>
 +<div class="carre vert"></div>
 +<div class="carre bleu"></div>
 +<div class="carre rouge"></div>
 +<div class="carre vert"></div>
 +<div class="carre bleu"></div>
 +<div class="carre rouge"></div>
 +<div class="carre vert"></div>
 +<div class="carre bleu"></div>
 +<div class="carre rouge"></div>
 +<div class="carre vert"></div>
 +<div class="carre bleu"></div>
 +</code>
 +
 +Je veux que chaque carré soit cliquable, c'est à dire que chaque carré soit lié à un événement. Vais-je devoir doré chaque ''%%<div>%%'' d'un id pour les atteindre depuis le script ''script_10.js'' ? Ce serait fastidieux, on préférerait éviter...
 +
 +<code javascript linenums>
 +// script_10.js
 +function bouton_couleur(e){
 +    let $item = $(e.target);
 +    if ($item.hasClass("rouge")) {
 +        alert("Ce bouton est rouge");
 +    } else if ($item.hasClass("vert")) {
 +        alert("Ce bouton est vert");
 +    } else {
 +        alert("Ce bouton est bleu");
 +    }
 +}
 +
 +$(".carre").click(bouton_couleur)
 +</code>
 +
 +Ci-dessus, en ligne 13, ''$'' est un raccourci pour désigner ''jQuery''.
 +
 +Le code ''%%$(".carre")%%'' permet d'atteindre directement tous les nœuds de la page qui possèdent la classe ''carre''. Ainsi on atteint tous les ''%%<div>%%''. Ensuite, on associe à tous ces nœuds l'événement ''click'' qui déclenche la fonction ''bouton_couleur''.
 +
 +En ligne 3, on veut récupérer la cible du clic avec ''e.target''. Mais ''e.target'' désigne un nœud ordinaire. En notant ''$(e.target)'' on obtient une version augmentée par jQuery qui nous donne accès à des fonctionnalités supplémentaires.
  
 +Vous comprenez que de tels outils font gagner en **productivité**, c'est à dire qu'une simple ligne de code permet de faire beaucoup.
  
 +<WRAP box>**À faire :** n'oubliez pas de tester.</WRAP>
nsi/premiere/javascript.1638456616.txt.gz · Dernière modification : de goupillwiki