CentraleSupélecDépartement informatique
Gâteau du Glouton
3 rue Joliot-Curie
F-91192 Gif-sur-Yvette cedex
jQuery: une bibliotheque JS pour le web

Introduction

jQuery est une bibliothèque JavaScript, c'est à dire un ensemble de fonctions, permettant de manipuler très facilement et de façon très concise l'arbre DOM. Cette librairie vient par ailleurs avec de nombreux plugins facilitant la vie du programmeur web.

Un autre effet de bord, c'est que la librairie jQuery gomme une partie des incompatibilités entre les navigateurs internet, en particulier avec AJAX, rendant le code plus portable.

Et on peut utiliser les fonctions jQuery dans n'importe quel programme JavaScript ! Bref, ce serait dommage de s'en passer.

Comment l'utiliser ?

La bibliothèque vient en deux format: non-compressée, donc lisible mais "lourde" à télécharger, et compressée, donc plus raisonnable en taille, mais illisible (ouvrez-les pour comparer !).

Avec une version hébergée en ligne:

Dans l'entête du document:

<script type="text/javascript"
        src="https://code.jquery.com/jquery-1.12.0.min.js"></script>

Inconvénient: il faut être connecté à internet, donc non-utilisable en local.

Avec une version téléchargée localement

On télécharge le fichier, on le place dans le même dossier que le fichier html, puis dans l'entête du document:

<script type="text/javascript" src="jquery.js"></script>

Des références

Concept

La librairie jQuery définit un type d'objet particulier, l'objet jQuery: il s'agit essentiellement de l'encapsulation de collections (c'est à dire de tableaux) d'éléments de l'API DOM. En plus de cela, la librairie jQuery ajoute de nombreuses méthodes pratiques pour tout un tas de choses usuelles que l'on peut avoir envie de faire sur des collections d'éléments DOM.

La fonction $()

jQuery définit une fonction principale : jQuery() aussi appelée $(). Il y a 3 grands types d'utilisations :

Avec du texte représentant un « sélecteur »

Retourne un objet jQuery qui référence un ou plusieurs nœuds DOM ayant « matché » le sélecteur. C'est donc une fonction de recherche.

Par exemple:

$("#id")   // retourne l'élément du DOM (version jQuery) avec l'ID en question

Avec du texte représentant du HTML

Crée un ou plusieurs éléments DOM et retourne un objet jQuery qui le/les référence. C'est donc une fonction de création.

Par exemple:

$("<h1>")   // Crée un nouveau noeud (jQuery) @@<h1>@@

Avec un élément DOM

Retourne un objet jQuery qui référence l'élément: transforme la représentation DOM classique en DOM jQuery.

Par exemple:

$(document.body)   // Retourne un noeud jQuery représentant le sous-arbre de la balise <body>

Donc $() permet d'encapsuler un objet DOM dans un objet jQuery. Par exemple:

var d = window.document.body;
var e = $(d);
var f = e[0];

littéralement copie window.document.body dans f:

  1. on met le DOM tree window.document.body dans d
  2. on l'encapsule dans l'objet jQuery e
  3. cet objet contient une collection d'un seul élément DOM: d. On le récupère avec e[0], et on met le résultat dans f

À savoir

On travaille toujours avec des pointeurs. Donc dans l'objet jQuery, on a une référence à l'emplacement dans l'arbre. Donc ajouter une propriété à quelque chose dans un objet jQuery ajoute effectivement la propriété à l'arbre, et donc à ce qui est représenté par le navigateur.

Les sélecteurs

Sélection des noeuds :

  • Par nom d'élément (balise) : $("nomElt")
  • Par identifiant : $("#id")
  • Par classe : $(".nomClasse")
  • Tous : $("*")

En tenant compte de la hiérarchie :

  • Tous les descendants : $("nomEltAncetre nomEltDescendant")
  • Descendants directs : $("nomEltParent > nomEltEnfant")
  • On peut composer pour descendre plusieurs niveaux : $("#idGrandParent > nomEltParent > nomEltEnfant")

En tenant compte des attributs :

  • Test de l'existence : $("nomElt[nomAttr]")
  • Test de la valeur : $("nomElt[nomAttr='value']")

La fonction .find()

Si vous avez encapsulé la racine d'un arbre DOM dans un objet jQuery, vous pouvez sélectionner parmis ses descendants avec les sélecteurs du dessus.

Exemple

$("ul").find("a")

va sélectionner toutes les balises a qui sont dans des listes non-ordonnées. Notez que les balises a peuvent être arbitrairement profond dans le sous-arbre issu de ul.

On peut faire

$("ul").find("a").each(function(i) { console.log($(this).text()) })

pour afficher joliment dans la console les texte de chaque balise a.

Filtres

jQuery définit également des versions « raccourcies » de certaines expressions de sélection souvent utilisées, notamment en ce qui concerne les formulaires

  • Dans l'expression d'un sélecteur : $("selecteur:filtre")
  • Avec la fonction « filter » : $("selecteur").filter(":filtre") ne garde de la sélection que les éléments qui passent le filtre.
  • Avec la fonction « not »: $("selecteur").not(":filtre") ne garde de la sélection que les éléments qui ne passent pas le filtre.

Exemples de filtres :

  • Type d'élément : :input, :checkbox, :radio, :password
  • État d'élément : :focus, :checked, :selected
  • Ou encore : :even, :odd, :empty, :contains(...texte...)

Les fitres sont compositionnels:

$("input").filter(":checkbox").not(":checked")

rend la liste des noeuds <input> de type checkbox qui ne sont pas encore sélectionnés.

  • On peut aussi utiliser une fonction pour décrire un filtre.

Filtres avec une fonction

On peut aussi filter des éléments à l'aide d'une méthode dédiée: par exemple

function isText() {
  return (this.nodeType == 1);
}

répond "vrai" si l'élément est un noeud élément (voir la liste des type de noeuds pour s'en convaincre).

Notez que l'on utilise l'objet this pour faire référence à l'objet (DOM!) traité: la fonction va être appliqué comme une méthode à chacun des éléments de la collection.

Donc si on fait après

alert($("body *").filter(isText)[0]);

on affiche le premier noeud descendant de body qui rend "vrai" lorsque on lui applique la méthode.

Attention

Dans la fonction isText:

  • this est un objet DOM
  • Si on veut travailler dessus avec une méthode jQuery, on utilise $(this) qui est l'encapsulation de l'objet DOM dans un objet jQuery.

Opérations sur les collections

Obtenir la taille de la collection : $("td").length

Sélectionner des éléments de la collection :

  • Premier : $("td").first()
  • Dernier : $("td").last()
  • Ième : $("td").eq(i)

Appliquer une fonction à tous les éléments d'une collection :

function monAction(index) {
    console.log(index + ":" + $(this)); 
}

$("td").each(monAction);
// affiche successivement chacun des éléments td

Note

  • on utilise dans cette exemple une fonction nommée. On pourrait aussi faire avec une fonction non nommée.
  • "this" est l'objet courant, donc il change à chaque tour de boucle.
  • C'est un objet de l'API DOM! Donc si on souhaite l'utiliser comme objet jQuery, il faut l'encapsuler dans la fonction $().

Manipulation du DOM

Avec jQuery, on peut faire toutes les opérations usuelles sur le DOM de façon plus concise.

Navigation

A partir d'un élément de l'arbre, on peut

  • Accéder aux attributs : .attr("nomAttr")
  • Accéder aux parents, aux ancêtres : .parent() et .parents()
  • Accéder aux enfants : .children()
  • Accéder aux frères : .siblings(), .next() et .prev()
  • Accéder au texte de l'élément : .text()
  • Accéder à l'ensemble du sous-arbre sous forme de texte avec balises : .html()
  • Accéder à la valeur d'un noeud <input>, <select> ou <textarea>: .val().

Les accesseurs qui rendent des collections de noeuds peuvent aussi prendre un sélecteur et/ou un filtre en argument.

De manière général, les opérations de jQuery travaillent avec les noeuds DOM qui sont des balises, et pas avec par exemple les noeuds texte. En général ce n'est pas un problème car le plus souvent la méthode .text(), ou à la rigueur .html() suffit

Il est néanmoins possible de récupérer tous les fils des éléments d'une collection avec la méthode .contents(), y compris, donc, les noeuds de texte.

La méthode .contents()

Voir la doc pour plus de détails.

Exemple

Un exemple complet (bien que peu utile) de ce qui peut être fait:

"use strict";

function coin(s) {
  return (s.replace(/[^\s][^\s][^\s][^\s]/g, "coin"));
}

function isTextNode() {
  return (this.nodeType === 3);
}

var textNodes = $( "body *" ).contents().filter(isTextNode);

textNodes.replaceWith(function () { return (coin(this.wholeText)); } );
  • La methode replace prends une expression régulière et un remplacement éventuel. La chaine \s matche les espaces, tab, sauts de ligne. Le ^ demande de matcher tout caractère qui ne se trouve pas entre les crochets. Donc [^\s] matche tout caractère qui n'est pas un espace. Le g à la fin demande de remplacer toutes les sous-chaines qui matchent.
  • Comme vu précédemment, .contents() va rendre tous les noeuds qui vérifient "body *", y compris les noeuds de type texte (ce qui nous intéresse).
  • On retrouve le fait que l'objet this est un objet DOM qui se trouve dans la collection de l'objet jQuery: on peut donc lui appliquer des méthodes et attributs DOM (par exempe wholeText).
  • Pour faire fonctionner ce code dans le sratchpad, placez-vous sur une page du cours (ça devrait marcher sur n'importe quelle page sur le web qui ne va trop faire de choses évoluées en javascript, mais c'est à vous d'essayer).

Création de noeuds

Pour créer un nouvel élément: $("<baliseElement>") Par exemple:

$("<h1>")

Pour y mettre des attributs, on rajoute un objet (qui peut être non-nommé) avec les attributs qu'on souhaite:

$("<img>", { src : "http://www.supelec.fr/offres/doc_inline_src/374/biglogo.jpg",
             alt : "Le logo de l'école" } )

Rappelez-vous, un objet est essentiellement une table d'association. Cela se prête donc bien à l'ajout d'attributs et de valeurs.

Modification de l'arbre

A partir d'un élément de l'arbre :

  • Insertion/modification d'attribut : .attr("nomAttr", "valeur")
  • Insertion :
    • D'enfants : .append(...), .prepend(...)
    • De frères : .after(...), .before(...)
    • De parents: .wrap(...)
    • De texte : .text(...)
    • D'un sous-arbre entier : .html(...)
  • Remplacement de l'élément par un autre : .replaceWith(...)
  • Suppression de l'élément : .remove(), ou .detach()

Note

Certaines fonctions comme .html() ou .text() se comporte différemment avec et sans argument.

Styles CSS

On peut aussi manipuler le CSS de la page à l'aide de jQuery

Propriètés CSS individuellement

  • Lecture: .css("nomPropriete")
  • Modification: .css("nomPropriete", "valeur")
  • Modification de plusieurs propiétés: .css({"prop1": "val1", "prop2": "val2", ...})

Ajout/suppression de classes CSS

Il faut que ces classes soient déjà existantes: on ne peut pas manipuler le contenu du fichier de style .css avec jQuery.

  • .addClass("nomClasse")
  • .removeClass("nomClasse")

Événements

L'événement ready

En javascript standard, L'événement load est émis lorsque TOUTE la page est prête (y compris par exemple le chargement des images). jQuery propose une alternative : l'événement ready, qui est émis lorsque tous les éléments du DOM sont définis, mais que le contenu n'est pas encore là. Donc c'est un événement qui a lieu avant l'événement load.

Attention

Avec jQuery:

  • load: est associé à la fenêtre (object window)
  • ready: est associé au document (object document)

Gestionnaire d'événements

Pour associer une action à un objet (ou une collection d'objets) jQuery en fonction d'un événement, on utilise:

objetJQuery.nomEvenement(function(){
    // code à exécuter lorsque l'événement se produit
});

Notez que l'action est ici spécifiée sous la forme d'une fonction anonyme. On aurait aussi pu le faire avec une fonction nommée:

function maFonction() {
    // du code à exécuter 
}        

puis ensuite associer la fonction à l'événement plus loin:

objetJQuery.nomEvenement(maFonction);

Référence

Tous les événements jQuery sont ici. Plus précisément:

Exemple: clic de souris

$("h2").click(function(){
  console.log($(this).text());
});

Pour désactiver le comportement par défaut de l'élément vis-à-vis des événements :

$("a").click(function(event){
  console.log($(this).text());
  event.preventDefault();
});

Notes

  • On utilise click, et pas onclick
  • Comme la gestion des événements se programme sur l'arbre DOM, on a besoin d'attendre qu'il soit prêt... Il faut donc faire ces appel au sein
    • de l'evenement ready si on a pas besoin du contenu (la taille des images par exemple)
    • de l'evenement load si on a besoin de tout.

Voir plus bas les exemples.

Attention

Comme load est associé à la fenêtre (object window), on doit faire

$(window).load(function() { ... });

ou

$(window).load(nomDeLaFonction); // ATTENTION: PAS DE ()

Comme ready est associé au document (object document), on doit faire

$(document).ready(function() { ... });

ou

$(document).ready(nomDeLaFonction); // ATTENTION: PAS DE ()

Effets d'animation

jQuery permet également de déclencher des effets d'animation sur des éléments de l'arbre DOM :

  • .hide() pour cacher un élément
  • .show() pour... le montrer
  • .toggle() pour le montrer si il était caché, et le cacher sinon

Les même avec des effets:

  • .fadeOut() et .slideUp()
  • .fadeIn() et .slideDown()
  • .fadeToggle() et .slideToggle()

Arguments optionnels:

  • temps, en millisecondes, pour la durée de l'animation
  • fonction de callback, appelée automatiquement à la fin de l'animation

Pour tous les détails, n'hésitez pas à aller voir la doc de l'API: http://api.jquery.com/.

Une série de démos

Cette série de démos est prévue pour fonctionner avec JSbin. Prenez soin de sélectionner "auto-run JS" tout à droite, et/ou de cliquer sur le bouton "run JS" si rien ne se passe. Prenez aussi soin d'afficher la console... (Ctrl+Shift+K)

Sélecteurs et filtres

À chaque clic sur le lien "ici", on affiche dans la console le nombre de checkboxes non sélectionnées:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Comptons les checkboxes</title>
  <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
  <script type="text/javascript">
    function f () {
      console.log($("input").filter(":checkbox").not(":checked").length);
    }
  </script>
</head>
<body>
  <form>
  <input type="checkbox">aaa</input>
  <input type="checkbox">bbb</input>
  <input type="checkbox">ccc</input>
  </form>
  <a onclick="f();">ici</a>
</body>
</html>

Insertion dans l'arbre DOM

Insertion simple

Lorsque l'arbre DOM est prêt (événement ready), on ajoute une balise <h1> ainsi qu'un texte.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>jQuery !</title>
    <script type="text/javascript"
       src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <script type="text/javascript">
       $(document).ready(function(){
          $(document.body).append( $("<h1>").text("Voici un titre") );
       });
     </script>
  </head>
  <body>
  </body>
</html>

Insertion d'un noeud parent

On va utiliser la méthode .wrap sur le lien, pour insérer un noeud <h1>:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Ajout d'un noeud parent</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script type="text/javascript">
    "use strict";

    $(document).ready(function(){
      $("#link").wrap( $("<h1>") );
    });
     </script>
  </head>
  <body>
    <a id="link" href="http://jquery.com/">jQuery</a>
  </body>
</html>

Recherche dans l'arbre et action

Simple affichage dans la console

Avec l'événement load:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Listons les listes</title>
  <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
  <script type="text/javascript">
    "use stric";
    function f() {
      $("li").each(function(){
         console.log($(this).text());
      });
    }

    $(window).load(f); // ATTENTION: object window ; pas de () sur f
  </script>
</head>
<body>
  <ul>
  <li>aaa</li>
  <li>bbb</li>
  <li>ccc</li>
  </ul>
</body>
</html>

Avec l'événement ready:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Listons les listes, bis</title>
  <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
  <script type="text/javascript">
    "use stric";
  function f() {
    $("li").each(function(){
       console.log($(this).text());
    });
  }

  $(document).ready(f);
  </script>
</head>
<body>
  <ul>
  <li>aaa</li>
  <li>bbb</li>
  <li>ccc</li>
  </ul>
</body>
</html>

Modification du style

Plutôt que simplement afficher dans la console le résultat, on va attribuer des actions pour certains événements, par exemple changer leur CSS. Pour voir que quelque chose s'est passé, placer la souris sur la liste: les items devraient changer de couleur.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Listes de noel</title>
  <script src="https://code.jquery.com/jquery-1.11.3.js"></script>
  <script type="text/javascript">
    "use stric";

    function setRed() {
      $(this).css("color", "red");
    }

    function setBlack(){
      $(this).css("color", "black");
    }

    function f() {
      $("li").each(function(){
         $(this).mouseenter(setRed);
         $(this).mouseleave(setBlack);      
      });
  }

  $(document).ready(f);
  </script>
</head>
<body>
  <ul>
  <li>aaa</li>
  <li>bbb</li>
  <li>ccc</li>
  </ul>
</body>
</html>

Des choses qui se cachent et qui s'affichent

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hide and Seek</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script type="text/javascript">
    "use strict";

    function monAction() {
      $(this).next().slideToggle();
    }

    $(document).ready(function(){
      $("h2").each(function() {
        $(this).next().toggle();      // cache le paragraphe au depart
        $(this).click(monAction);     // pour changer le statut quand on clique sur le titre
      });
    });
     </script>
  </head>
  <body>
    <h2>Soupe</h2>
    <p>Bon pour la sante</p>
    <h2>Carotte</h2>
    <p>Bon pour les lapins</p>
    <h2>Cornichon</h2>
    <p>Bonne conservation</p>
    <h2>Salsifis</h2>
    <p>Pas bon du tout</p>
  </body>
</html>

Une page qui defile a l'infini

<html>
  <head>
    <link rel="stylesheet" type="text/css" href="test.css"/>
    <script type="text/javascript"
            src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
    <script type="text/javascript">

      $(window).scroll(function(event) {

          // Si le nombre de pixels scrollés jusqu'à présent
          // plus la taille de la fenêtre
          // est supérieur à la hauteur de document.body moins epsilon,
          // c'est qu'on est en bas de la page.
          if(window.scrollY + window.innerHeight > document.body.scrollHeight - 100) {
              // et dans ce cas, on ajoute 10 éléments
              for(var i = 0; i < 10; ++i) {
                  $(document.body).append($("<h1>").text("Titre numéro " + n));
                  ++n;
              }
          }
      });

      var n = 0;

      $(window).load(function (){
          // Au chargement, création d'une 20aine d'éléments pour remplir la page
          var i;
          for(i = 0; i < 20; ++i) {
              $(document.body).append($("<h1>").text("Titre numéro " + n));
              ++n;
          }
      })
    </script>
  </head>
  <body>
  </body>
</html>

Pour finir: Attention, pour pouvoir utiliser jQuery

  • Ne pas oublier d'inclure la bibliothèque jQuery dans la page HTML concernée...
  • Attendre que le DOM soit chargé avant d'utiliser les fonctions jQuery !