TCH056 - Programmation Web

TCH056 - Programmation Web

<Chapitre 04> Javascript



Anis Boubaker, Ph.D.
Prof. Enseignant en informatique

Plan du chapitre

  • Historique
  • Motivation
  • Normes
  • Syntaxe de base
  • Comment inclure du Javascript?

Genèse du langage

Créé en 10 jours par Brendan Eich, un employé de Netscape.

JavaScript (JS) had to “look like Java” only less so, be Java’s dumb kid brother or boy-hostage sidekick. Plus, I had to be done in ten days or something worse than JS would have happened

Historique

Faites défiler la ligne du temps avec la flèche. Rechargez la page si la ligne du temps ne s'affiche pas.
1996 - Version 1.0
Intégrée dans Netscape 2
1997 - Première norme (ECMA)
ECMAScript1 (ES1)
IE4 est le premier navigateur à l'implémenter
1998 - Javascript 1.3
Netscape continue le développement indépendant de Javascript pour son navigateur
1999
ECMAScript 3 (ES3)
2000 - Firefox et Javascript 1.5
La fondation Mozilla effectue une refonte de Netscape: le navigateur Firefox qui inclut JS 1.5
2008-2009 - ES5
Abandon de ES4 et sortie de ES5
2015 - ES6
Sortie de ES6 qui comporte l'essentiel des améliorations modernes du langage
2018
Support de ES6 dans tous les navigateurs modernes (sauf IE11)
Aujourd'hui
Chaque année une version de ECMAScript est publiée (ES 20xx) rendant l'évolution du langage plus agile.

Motivation

  • HTML nous a permis de définir le contenu
  • CSS nous a permis de définir l'apparence des pages
  • Javascript nous permettra d'ajouter des aspects dynamiques à nos pages. Ex.:
    • Réagir aux actions de l'usager
    • Charger du contenu dynamiquement
    • Animations
    • ...

Environnements

Le seul langage de programmation qui s'exécute dans un navigateur! mais aussi...

Côté serveur

Applications de bureau

Un langage populaire

Sondage StackOverflow 2022, mené auprès des développeurs

Une syntaxe connue...

Philosophie

Tout est objet

  • Les types primitifs
  • Les fonctions
  • Le code!

Non-typé

  • Typage dynamique (Duck typing)
  • Le type est mutable

Prototypal

  • Langage orienté-objet
  • Différent des langages OO traditionnels

Événementiel

  • Cycle d'exécution non bloquant basé sur les événement
  • Modèle asynchrone

Javascript: Où dans une page Web?

Comme attribut (très mauvais!)


								

...

Cliquez ici!

Balise script (éviter)


								

...

<script type="text/javascript"> alert("Bonjour le monde!"); </script>

Dans un fichier externe (Mieux!)


								
							

Dans un fichier externe comme module (Parfait!)


								
							

Les attributs `defer` et `async`

  • `defer`: Charger le script en parallèle, l'exécuter après le chargement de la page
    
    								
    							
  • `async`: Charger le script en parallèle, l'exécuter dès qu'il est disponible
    
    								
    							
  • `async` et `defer`: Le script et chargé et exécuté immédiatement, bloquant le chargement de la page
    
    								
    							

Plan du chapitre

  • Variables et types de données
  • Objets et tableaux
  • Chaines de caractères
  • Fonctions

Préambule

  • On ne reviendra pas sur la syntaxe évidente (structures conditionnelles et itératives) - c.f. INF155/INF111
  • Pas de conception OO (classes, prototypes, etc.) mais nous utiliserons des objets existants et leurs propriétés/méthodes
  • Certains concepts avancés ne seront pas abordés (ex.: fermetures, promesses, async)

Les variables

Le mot clé let permet de déclarer une variable.

Les variables sont typées dynamiquement.
La fonction typeof permet de déterminer le type inféré:

Le mot clé var

On peut aussi déclarer des variables avec le mot clé var:

  • Ce mot clé existe encore par compatibilité ascendante
  • Il a un fonctionnement particulier (problématique pour le périmètre et l'élévation -- hoisting -- des variable)
  • Utilisation à proscrire depuis ES6!

Les constantes 1/2

On déclare une constante avec le mot clé const:


Il est possible de modifier les propriétés d'un objet, même si c'est const!

Les constantes 2/2

  • Il est conseillé de toujours commencer par déclarer les variables de type objet comme constantes
  • Au besoin, changer la déclaration par un let.

Les types primitifs

Type Exemples de valeurs
Number 42, 3.24, Infinity, -Infinity, NaN (Not a Number)
BigInt 9007199254740991n
Boolean true, false
String "Hello, world!", 'TCH056'
Undefined Variable non définie (voir plus loin)
null null= absence intentionnelle de valeur d'objet

Booléens et vérité

En Javascript, le type boolean existe et peut prendre la valeur true ou false

MAIS... Toute valeur "véridique" (truthy) sera considérée comme vraie et une valeur "non-véridique" (falsy) sera considérée comme fausse

Valeur véridique

  • Toute valeur n'étant pas false, 0, -0, "", null, undefined et NaN.
  • Ou encore: toute valeur qui n'est pas true lorsque convertie en Booléen avec Boolean()

null et undefined??

  • undefined est un type associé aux variables inexistantes et aux variables qui n'ont pas reçu de valeur.
  • null est un objet qu'on affecte à une variable pour indiquer qu'elle a une valeur nulle.

Undefined c'est aussi...

  • La valeur de propriétés inexistantes dans un objet
  • La valeur de retour d'une fonction qui ne retourne rien (de type void)

Conversion explicite de types

Les fonctions Boolean(), Number() et String() permettent de convertir entre type de données (type casting):

Conversion implicite de types

  • Javascript étant un langage typé dynamiquement, des conversion ont lieu automatiquement dès qu'on effectue des opérations entre données de type différents.
  • La logique de conversion n'est pas toujours intuitive...

Opérations Booléennes

  • Le résultat d'une opération Booléenne (ex.: &&, ||) n'est pas obligatoirement une valeur Booléenne.

Expression Résultat
a && b b si Boolean(a) est true, sinon a.
a || b a si Boolean(a) est true, sinon b.

Opérateur de comparaison ==

  • Comme en C et en Java, on compare des valeurs avec l'opérateur `==`
  • Cependant, cet opérateur tentera de convertir les valeurs comparées si elles ne sont pas de même Type

Opérateur de comparaison ===

  • L'opérateur `===` donnera une valeur vraie si les deux valeurs sont égales ET de même type
  • Il est toujours conseillé d'utilise === pour tester l'égalité, sauf exception où le comportement du `==` est souhaitable.

Plan du chapitre

  • Variables et types de données
  • Objets et tableaux
  • Chaines de caractères
  • Fonctions

Définition d'un objet

Un objet est un ensemble de propriétés de type clé-valeur. On peut définir un objet à l'aide d'un littéral en notation JSON { ... }

On accède aux propriétés d'un objet à l'aide de la notation xxx.yyy:

Tableaux

En JS, un tableau est une structure pouvant contenir plusieurs éléments pas forcément du même type

Tableaux - Méthodes et attributs utiles

Modification d'un objet

  • Les objets en JS n'ont pas de structure pré-établie* (i.e. pas de classes, comme en Java)
  • Il est possible d'ajouter/supprimer des propriété à tout moment

Modification d'un objet (2)

  • On peut accéder aux propriétés d'un objet comme un tableau associatif:

Objets et tableaux

Plan du chapitre

  • Variables et types de données
  • Objets et tableaux
  • Chaines de caractères
  • Fonctions

Chaines de caractères

  • Le type chaine de caractères (string) est un type de base en JS
  • Syntaxe:

Caractères dans une chaine

  • On accède aux caractères par indice, avec la notation tableau ou la méthode at
  • Une chaine de caractères est immutable

Chaines : Méthodes utiles

Plusieurs méthodes sont disponibles pour manipuler les chaines de caractères

toLowerCase toUpperCase indexOf
lastIndexOf includes startsWith
endsWith slice substring
substr localeCompare

Plan du chapitre

  • Variables et types de données
  • Objets et tableaux
  • Chaines de caractères
  • Fonctions

Fonctions

Plusieurs façon d'en déclarer:

Appel d'une fonction

  • Syntaxe semblable aux autres langages de la famille C: il suffit de spécifier le nom de la fonction, suivi des paramètres effectifs entre parenthèse.
  • Si la fonction est un attribut d'un objet, on l'invoque en utilisant la notation "point"

Paramètres d'une fonction

  • Aucune règle sur les paramètres: les types sont dynamiquement typés et le nombre de paramètres peut varier du nombre de paramètres défini
  • Si un paramètre est omis lors de l'appel, alors sa valeur sera undefined

Valeurs de paramètres par défaut

  • Pour éviter qu'un paramètre omis lors de l'appel ait la valeur undefined, il est possible de donner des valeur par défaut aux paramètres:

Valeur de retour

  • Une fonction ne peut retourner plus d'une valeur
  • La valeur retournée peut être un type simple (number, string), un objet (ex.: array, ou objet personnalisé), et même une fonction (voir plus loin)
  • Une fonction qui ne retourne aucune valeur retournera la valeur undefined

Fonctions variadiques

  • On appelle une fonction variadique une fonction dont le nombre total de paramètres n'est pas défini d'avance
  • En JS, toute fonction peut recevoir plus d'arguments que spécifié, il suffit alors d'accéder aux autres paramètres à l'aide du tableau arguments

Fonctions variadiques

  • ES6 a introduit une nouvelle syntaxe pour définir des fonctions variadiques en utilisant la notation ellipse (...)
  • Il est préférable d'utiliser cette syntaxe car elle améliore la maintenabilité du code.

Fonctions = Données

En JS, une fonction est une donnée qu'on peut affecter...

Fonctions = Données

On peut même retourner une fonction...

Fonctions = Données

Et passer une fonction en paramètre...

Fonctions d'ordre supérieur

  • On appelle fonction d'ordre supérieur une fonction qui reçoit une autre fonction en argument, ou qui retourne une fonction.
  • Les fonctions d'ordre supérieur sont un mécanisme puissant qui offre des flexibilités et des applications intéressantes.
  • Spécifiquement, les fonctions itératives sur les tableaux suivantes (à connaître):
    Map Reduce Filter forEach

Plan du chapitre

  • Rappel: Document HTML = Arbre
  • API de parcours du DOM/BOM
  • Modification dynamique du DOM

Rappel: Arborescence HTML

DOM: Document Object Model

  • Le DOM est une une structure hiérarchique qui représente le contenu d'une page sous forme d'une arborescence
  • L'arbre peut-être manipulé avec du code Javascript: tout changement au DOM se reflète de façon dynamique sur le rendu de la page (à l'écran)
  • La manipulation se fait à travers une API commune à tous les navigateurs
  • Le DOM est une entité qui évolue constamment dans les pages/application WEB modernes

API du DOM

Ensemble de fonctions disponibles pour:

  • Localiser des éléments de la page
  • Modifier des éléments identifiés (contenu, ajout d'enfants, suppression)
  • Accéder et agir sur les différentes propriétés des éléments

Il existe plusieurs DOM (HTML, SVG, XML), mais ils partagent tous la même API normalisée par le W3C.

Construction du DOM depuis le HTML

Méta-modèle du DOM

DOMMetaModel

Types d'éléments du DOM

Plan du chapitre

  • Rappel: Document HTML = Arbre
  • API de parcours du DOM/BOM
  • Modification dynamique du DOM

Sélection d'éléments

Quatre approches/méthodes de sélection (démontrées en classe)

Sélection par Identifiant


						const conteneur = document.getElementById('conteneur');
					

Sélection par Classe


						const hots = document.getElementsByClassName('hot');
						//NOTE: `hots` est un tableau!!
					

Sélection par Type


						const paragraphes = document.getElementsByTagName('p');
						//NOTE: paragraphes est un tableau!!
					

Sélection par Sélecteur 1/2


						const lesHot = document.querySelector('#conteneur p.hot');
						//NOTE: Un seul élément est sélectionné (le premier 
						// qui est satisfaisant)
					

Sélection par Sélecteur 2/2


						const lesHot = document.querySelectorAll('#conteneur p.hot');
						//NOTE: Tous les éléments satisfaisants au sélecteur seront
						// retournés (dans un tableau)
					

Sélection en sous-arbre

  • Les méthodes `getElementsByClassName`, `getElementsByTagName` et `querySelector` sont implémentées dans `Element` (sont disponibles pour tout objet de type Element)
  • Utiliser ces fonctions sur un élément en particulier (pas document) exécutera la requête comme si l’élément était la racine de l'arbre.
  • Les éléments retournés seront seulement ceux qui sont descendants de l'élément.

						const conteneur = document.getElementById('conteneur');
						const paragraphes = conteneur.getElementsByTagName('p');
						//NOTE: Seuls les paragraphes descendants du div#conteneur 
						//seront sélectionnées!
					

Parcours du DOM

  • Une fois un élément sélectionné, il est souvent désirable de parcourir l'ensemble des éléments qui lui sont liés de façon hiérarchique.
  • Plusieurs propriétés de chaque élément permettent d'accéder - de proche en proche - aux enfants, frères et parents, de l'élément :

Noeud parent


						const lien = document.querySelector('div p a');
						const leSpan = lien.parentNode;
					

Noeuds Enfants


						const conteneur = document.querySelector('div#conteneur');
						const enfants = conteneur.childNodes;
						//Contient les noeuds p.para.hot, p#texte et div.hot
					

Premier et dernier enfants


						const conteneur = document.querySelector('div#conteneur');
						const premier = conteneur.firstChild; //p.para.hot
						const dernier = conteneur.lastChild; //div.hot
					

Frères précédent et suivant


						const conteneur = document.querySelector('p#texte');
						const premier = conteneur.previousSibling; //p.para.hot
						const dernier = conteneur.nextSibling; //div.hot
					

Contenu d'un élément

Trois méthodes pour lire le contenu d'un élément (et pour le modifier!)

>> Démonstration

Plan du chapitre

  • Rappel: Document HTML = Arbre
  • API de parcours du DOM/BOM
  • Modification dynamique du DOM

Création d'un nouvel élément

  • La méthode document.createElement permet de créer un élément du type spécifié.
    
    								//Création d'un nouveau paragraphe
    								const nouveauParagraphe = document.createElement("p");
    								//Définition du contenu du paragraphe
    								nouveauParagraphe.textContent = 
    									"Ceci est le contenu du nouveau paragraphe";
    							
  • Le nouvel élément n'est pas ajouté à la page, il faut le lier à l'arbre du DOM

Ajout d'éléments dans le DOM

>> Démonstration

Suppression d'éléments

  • On utilise la méthode elt.remove() pour supprimer un élément de l'arbre.
    
    								const elt = document.querySelector("#mon_element");
    								elt.remove(); //L'élément disparaît de l'écran
    							
  • Si on dispose du parent, on peut utiliser la méthode parent.removeChild(elt), qui retourne l'élément supprimé (pour l'ajouter ailleurs éventuellement)
    
    								const conteneur = document.querySelector("#conteneur");
    								//On supprime le 3e enfant de conteneur
    								const supprime = 
    									conteneur.removeChild( conteneur.childNode[2] );
    							

Attributs HTML - Ajout/Modification

Deux façons pour modifier les attributs d'un élément:

  1. Directement en utilisant la notation point (.):
    
    								const a = document.createElement('a');
    								a.href = "https://www.etsmtl.ca";
    								a.target = "_blank";
    								let valeur = a.target;
    							
  • L'approche la plus simple
  • Certains attributs s'appelle différemment en JS qu'en HTML (ex.: className)
  • Certains attributs spéciaux ne fonctionnent pas (ex.: data-extra-info)

Attributs HTML - Ajout/Modification

Deux façons pour modifier les attributs d'un élément:

  1. Directement en utilisant la notation point (.)
  2. En utilisant la méthode setAttribute:
    
    								const a = document.createElement('a');
    								a.setAttribute('href', "https://www.etsmtl.ca");
    								a.setAttribute('target', "_blank");
    							
  • Plus homogène: fonctionne toujours de la même façon quelque soit l'attribut
  • Ne respecte pas la casse (case insensitive) contrairement à la notation (.)
  • Méthode getAttribute pour la lecture

Attributs HTML - Suppression

  • En utilisant la méthode removeAttribute:
    
    								const para = document.createElement('p');
    								para.id="un-identifiant";
    								para.removeAttribute('id');
    							
  • Définir la valeur à null ne supprime pas un attribut.

Modification du style 1/3

Propriété className

  • Modifie l'attribut class de l'élément
    
    								const para = document.createElement('p');
    								//Définit les classes 'important' et 'citation' au 
    								//nouvel élément créé
    								para.className = "important citation";
    								//équivalent à: 
    								//para.setAttribute('class', "important citation");
    							
  • Pratique lorsqu'on doit définir une seule classe, sans conserver les classes existantes.

Modification du style 2/3

Le tableau classList d'un élément

  • elt.classList: Renvoie toutes les classes d'un élément
  • On utilise les méthodes add, remove et replace pour changer les classes de l'élément
    
    								const conteneur = document.querySelector("#conteneur");
    								//Ajoute la classe `large` à conteneur
    								conteneur.classList.add('large');
    								//Supprime la classe `demo` de conteneur
    								conteneur.classList.remove('demo');
    							
  • La méthode toggle est utile pour désactiver et réactiver une classe.

Modification du style 3/3

Ajout de style en-ligne à un élément

  • La propriété style regroupe toutes les déclarations de style définies en-ligne sur un élément
    
    								const conteneur = document.querySelector("#conteneur");
    								conteneur.style.width = '100fr';
    							
  • Les noms des déclarations CSS doivent être convertis en `camelCase`
    
    								  conteneur.style.backgroundColor = 'lightgreen';
    								//Au lien de: 
    								//conteneur.style.background-color = 'lightgreen'; //INCORRECT
    							

Plan du chapitre

  • Modèle d'exécution asynchrone
  • Programmation événementielle et boucle d'événements
  • Gestion des événements en Javascript

Modèle d'exécution

  • Le code Javascript s'exécute de façon séquentielle, une instruction à la fois
  • Comme pour le langage C, tout appel de fonction est ajouté dans une pile d'exécution (stack) qui sera dépilée dès la fin de la fonction
>> Démonstration

Exécution parallèle

  • Il est possible d'exécuter des tâches en parallèle en C ou en Java (Threads)
  • Le Javascript est un langage mono-threadé mais qui permet un semblant de parallélisme grâce à l'exécution asynchrone et la boucle d'événements (event loop)
  • Note: L'introduction récente des WebWorkers permet d'effectuer un vrai parallélisme (pas au programme)

Exécution Asynchrone

  • Veut dire: lancer l'exécution d'un traitement et ne pas attendre la réponse
  • La pile d'exécution poursuit son exécution normale
  • Lorsque la réponse est obtenue, un événement est déclenché
  • On traite la réponse liée à l'évènement lorsque la pile d'exécution sera terminée

Exécution asynchrone: Pourquoi?

  • Certains traitements nécessitent un temps d'exécution long (> quelques ms)
  • Ce genre de traitements bloquent la pile d'exécution si ils étaient exécutés de façon synchrone
  • Ceci affecte la réactivité de la page: aucune mise à jour de la page ne peut avoir lieu tant que la pile d'exécution n'est pas terminée!
>> Illustration

Exécution asynchrone: Dans quel contexte?

  • Exécution temporisée (avec setTimeout et setInterval)
  • Suite à des événements qui se produisent sur la page pour lesquels on a défini un gestionnaire d'événement (ex.: click, déplacement de souris, clavier, etc.)
  • Toute requête de communication avec une machine distante.
  • Tout calcul ou traitement qui nécessite un temps supérieur à la milliseconde

setTimeout

Fonction qui permet de programmer une exécution différée d'un traitement après un délai en ms

Prend deux arguments:

  1. Une fonction de rappel qui sera appelée dès que le délai sera écoulé
  2. Un délai en millisecondes

						let faireQqeChose = function(){
							alert("Délai écoulé!");
						}
						//Exécution après 2 secondes
						setTimeout(faireQqeChose, 2000);
					

setTimeout - Fonction anonyme

  • Il est possible de passer une fonction de rappel anonyme:
    
    								//Exécution après 2 secondes
    								setTimeout(function(){
    									alert("Délai écoulé!");
    								}, 2000);
    							
  • Elle peut même être fléchée:
    
    								//Exécution après 2 secondes
    								setTimeout( () => alert("Délai écoulé!") , 2000);
    							

setTimeout - Question

  • Après combien de temps le message d'alerte s'affichera?
  • Qu'est-ce qui s'affichera en premier (l'alerte ou dans la console?)

						//Exécution après 2 secondes
						setTimeout( () => alert("Délai écoulé!") , 2000);
						let resultat = 0n;
						for(let i=0; i < 600000000; i++){
							resultat += BigInt(i);
						}
						console.log(`Le résultat est: ${resultat}`);
					
>> Illustration

Événements

  • Lorsque le navigateur traite et affiche un document Web, une multitude d'événements se produisent en permanence
  • La grande majorité des événements qui se déclenchent sont ignorés
  • Ceux qu'on a choisi de traiter (en fournissant un gestionnaire d’événement) seront considérés et du code sera exécuté

Exemple: le timeout, défini avec setTimeout, est un événement qui se produit lorsque le délai du timeout est expiré.

Exemples d'événements

  • Souris: click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave
  • Clavier: keydown, keypress, keyup
  • Formulaires: blur, change, focus, focusin, focusout, input, invalid, reset, search, select, submit
  • Presse papier: copy, cut, paste
  • Touch: touchstart, touchmove, touchend, touchcancel

Note: Cette liste est loin d'être exhaustive!

Gestion des événements

  • Pour réagir face à un événement, il faut "écouter" l'événement en définissant un gestionnaire d'événement sur l'élément de la page concerné
  • La méthode addEventListener() permet d'ajouter un gestionnaire d'événement pour un événement spécifique.
  • La méthode removeEventListener() permet de supprimer un gestionnaire d'événement pour un événement spécifique.
  • Ces méthodes sont définies dans la "classe" EventTarget (qui englobe presque tous les types!).

Ajout d'un gestionnaire d'événement

  • La fonction addEventListener reçoit, par défaut, deux paramètres: (1) le type d'événement à écouter et (2) la fonction de rappel
  • Elle doit être définie sur un élément pour lequel on souhaite écouter l'événement

						let mon_bouton = document.querySelector('button#mon-bouton');
						mon_bouton.addEventHandler(
							'click', 
							function(){alert("Bouton cliqué!")}
						);
						//La fonction anonyme sera exécutée à chaque fois qu'on 
						//clique sur le bouton.
					

Plan du chapitre

  • Qu'est-ce que JQuery?
  • Installation de jQuery
  • Sélecteurs
  • Manipulation du DOM
  • Gestion des événements
  • Effets et animations
  • Requêtes AJAX
  • La librairie Axios

Qu'est-ce que jQuery?

  • Librairie JavaScript rapide, petite et riche en fonctionnalités
  • Vise à faciliter la manipulation du document HTML, la gestion des événements, l'animation, et les requêtes
  • API facile à utiliser qui fonctionne compatible avec la majorité des navigateurs
  • Grande communauté de développeurs et une vaste gamme de plugins disponibles
  • Désavantage: une API différente de celle du DOM

Installation de jQuery

Comme toute librairie Javascript, il est possible de:

  • Télécharger jQuery dans votre projet localement depuis le site de jQuery
  • Inclure la librairie via CDN:
    
    							

Première utilisation de jQuery

jQuery déclare sa fonction principale $ qui agit comme sélecteur et est le point d'entrée à toutes les fonctionnalités offertes.

En javascript, le caractère "$" est un caractère permis pour nommer une fonction/variable.


						//Cache tous les éléments de type p
						$("p").hide();
					

Sélection des éléments

  • Syntaxe de base pour la sélection:
    
    									$(selecteur)
    								
  • "selecteur" peut-être une chaine de caractères avec un sélecteur de type CSS ou un élément du DOM
    
    									$('#conteneur div>p')
    									$(document)
    								
  • Le sélecteur retourne un objet jQuery (et PAS un élément du DOM). On utilise la méthode get pour obtenir le noeud du DOM correspondant à un objet jQuery.

    Défilez vers le bas pour voir un exemple de code.

Sélection: Objets jQuery


							let header_jq = $('header#top_page');
							let header_dom = $('header#top_page').get();

							//Pour changer le contenu de top_page: 
							header_jq.text("Allô"); //méthode 1: jQuery 
							header_dom.textContent = "Allô"; //méthode 2: DOM

							//Si le sélecteur retourne plusieurs éléments, 
							//la méthode get prend un indice (0 par défaut)
							let paragraphe3_dom = $('p').get(2);
						

Sélection: jQuery vs querySelector

  • document.querySelector() retourne uniquement le premier élément qui correspond au sélecteur. Si on souhaite retenir tous les éléments, il faut utiliser document.querySelectorAll()
  • Si on sélectionne plusieurs éléments, il faut itérer sur les éléments avec une boucle
  • jQuery permet d'effectuer un traitement sur le résultat d'un sélection, indépendamment du nombre d'éléments obtenus
    
    								//Toutes les div de classe "solution" seront cachées
    								$('div.solution').hide();
    							

Sélection et chaînage

  • Un sélecteur jQuery retourne un objet jQuery
  • Le même objet jQuery est retourné par la majorité des fonctions
  • Ceci permet de réaliser des opérations en chaine, comme:
    
    								$('.maClasse').css('color', 'red').show();
    							

Manipulation du DOM avec jQuery: Contenu

  • .html(): Obtenir ou définir le contenu HTML d'un élément
    
    								$('p#id1').html('Nouveau contenu');
    							
  • .text(): Obtenir ou définir le contenu textuel d'un élément
    
    								$('p').text('Texte mis à jour');
    							
  • .val(): Obtenir ou définir l'attribut value pour les éléments de formulaire
    
    								$("input#prenom[type='text']").val('Marie');
    							

Manipulation du DOM avec jQuery: Attributs

  • .attr(): Obtenir ou définir la valeur d'un attribut
    
    								$('img.missing').attr('src', '/images/missing.jpg');
    
    								let alt = $('a#accueil').attr('alt');
    							
  • .removeAttr(): Supprime un attribut des éléments sélectionnés
    
    								//Supprime l'attribut "title" de tous les éléments de type "a" 
    								//de la page 
    								$('a').removeAttr('title');
    							

Manipulation du DOM avec jQuery: Classes

  • .addClass() et .removeClass(): Ajout ou suppression d'une ou plusieurs classes à tous les éléments sélectionnés
    
    								$("p.important").addClass("surbrillance bienVisible");
    
    								//Le chaînage est très utile!
    								$("a.externe").removeClass("a-rouge").addClass("a-bleu");
    							
  • .toggleClass(): Active ou désactive une classe
    
    								/$('div').toggleClass('encadre');
    							

Manipulation du DOM avec jQuery: CSS

  • .css(): Obtenir ou définir la valeur d'une propriété css
    
    								//change la couleur du texte de tous les div en rouge
    								$('div').css('color', 'red');
    
    								//applique plusieurs styles en même temps
    								$('div').css({'background-color': 'blue', 
    											'font-size': '14px'});
    							

Gestion des événement avec jQuery

  • .on(): Attache un ou plusieurs gestionnaires d'événements pour les éléments sélectionnés.
    
    								//Cache un élément si il a été cliqué
    								$('p').on('click', function() { $(this).hide(); });
    							
  • Il es possible de définir le gestionnaire pour des événements multiples:
    
    								$('p').on({ 
    									mouseenter: function() { $(this).css('color', 'red'); },
    									mouseleave: function() { $(this).css('color', 'black'); } 
    								});
    							
  • .off(): Supprime un gestionnaire d'événement.
    
    								$('#monBouton').off('click');
    							

Gestion des événement avec jQuery: Délégation

  • La délégation consiste à définir des gestionnaires d'événements pour des éléments, mais au niveau de leur parent
  • Le gestionnaire d'événement s'appliquera ainsi à tous les enfants concernés, actuels et futurs!
  • Exemple:

    Source: jquery.com

    
    								$( "#list" ).on( "click", "a[href^='http']", 
    									function( event ) {
    										$( this ).attr( "target", "_blank" );
    									}
    								);
    							

Effets et animations

Quelques fonctions permettent de créer des effets d'affichage simplement

  • Effets de base:
    
    								$('#monElement').hide();
    								$('#monElement').show();
    								$('#monElement').toggle();
    							
  • Effets d'animation:
    
    								$('#monElement').fadeIn();
    								$('#monElement').fadeOut();
    								$('#monMenu').slideDown();
    								$('#monMenu').slideUp();
    							
  • Liste complète

Requêtes asynchrones

  • La fonction .ajax() permet d'effectuer des requêtes de façon asynchrones
  • Pas basé sur les Promesses comme c'est le cas avec fetch - utilise uniquement les fonctions de rappel

Naviguez vers le bas pour afficher un exemple de code avec .ajax()

Exemple de requête PUT avec .ajax()


							$.ajax({
								url: 'https://monapi.com/utilisateurs/123', 
								type: 'PUT',
								data: JSON.stringify({
									nom: 'Valjean',
									prenom: 'Jean'
								}),
								//Type de donnée envoyé
								contentType: 'application/json; charset=utf-8',
								//Type de donnée attendu du serveur
								dataType: 'json',
								//Fonction de rappel exécutée (async) en cas de succès
								success: function(response) {
									// Traitement en cas de succès
									// Supposons que la réponse contienne un objet utilisateur 
									// mis à jour, avec un attribut 'message' de confirmation
									console.log("Mise à jour réussie:", response.message);

									// Affiche également le nom et le prénom mis à jour
									console.log("Informations mises à jour:", response.nom, 
													response.prenom);

									// Par exemple, si vous voulez mettre à jour le contenu 
									// d'un élément HTML 
									$('#infoUtilisateur').html('

Mise à jour réussie: ' + response.message + + '. Nom: ' + response.nom + ', Prénom: ' + response.prenom + '.

'); }, //Fonction de rappel (async) exécutée en cas d'erreur error: function(xhr, status, error) { // Traitement en cas d'échec console.error("Erreur lors de la mise à jour", status, error); } });

Plan du chapitre

  • Qu'est-ce que JQuery?
  • Installation de jQuery
  • Sélecteurs
  • Manipulation du DOM
  • Gestion des événements
  • Effets et animations
  • Requêtes AJAX
  • La librairie Axios

Axios

  • Axios est une bibliothèque JavaScript basée sur les promesses pour effectuer des requêtes HTTP, à la fois dans les navigateurs et avec Node.js.
  • API simple et propre pour envoyer des requêtes HTTP asynchrone, travailler avec des promesses, et gérer les réponses.
  • Installation de Axios avec un CDN:

						 
						
						 
					

Requête GET


						axios.get('https://api.exemple.com/data')
						.then(function (response) {
							// Traite la réponse
							console.log(response.data);
						})
						.catch(function (error) {
							// Gère l'erreur
							console.error(error);
						});
					

Note: Le contenu de response.data sera automatiquement traité et converti en fonction de l'entête 'Content-Type' envoyée par le serveur

Il n'est donc pas nécessaire de faire JSON.parse(response.data) si le Content-type est envoyé correctement par le serveur.

Gestion des erreurs avec Axios

  • Si le statut de la réponse est autre que 2xx, Axios considère cela comme une erreur et le traitement se poursuit dans le bloc catch

						axios.get('https://api.exemple.com/data-inexistante')
						.then(function (response) {
							// Ce code ne sera pas exécuté si le serveur répond avec 
							// un statut d'erreur (non 2xx)
							console.log("Réponse réussie:", response.data);
						})
						.catch(function (error) {
							// Ce code est exécuté si le serveur répond avec un 
							// statut d'erreur (non 2xx)
							if (error.response) {
								// La requête a été faite et le serveur a répondu 
								// avec un statut d'erreur
								console.log("Erreur! Statut:", error.response.status);
							} else if (error.request) {
								// La requête a été faite mais aucune réponse
								// n'a été reçue
								console.log("Erreur de requête:", error.request);
							} else {
								// Une erreur s'est produite lors de la mise en 
								// place de la requête
								console.log("Erreur:", error.message);
							}
						});
					

Requête POST


						axios.post('https://api.exemple.com/data', {
							nom: 'Valjean',
							prenom: 'Jean'
						})
						.then(function (response) {
							console.log(response.data);
						})
						.catch(function (error) {
							console.error(error);
						});						
					

Requête PUT


						axios.put('https://api.exemple.com/utilisateurs/123', {
							nom: 'Martin',
							prenom: 'Luc'
						})
						.then(function (response) {
							console.log(response.data);
						})
						.catch(function (error) {
							console.error(error);
						});											  
					

Requête DELETE


						axios.delete('https://api.exemple.com/utilisateurs/123')
						.then(function (response) {
							console.log("Ressource supprimée avec succès.");
						})
						.catch(function (error) {
							console.error(error);
						});									  
					

</Chapitre 04>