Espace tutos dev’ & informatique 🐧

Coder sans jQuery : Remplacer $(‘selector’)

Publié le
Article sur comment coder sans jquery dollar selector

Introduction

Après l’article précédent sur le remplacement de $(function), nous allons poursuivre dans la même direction, cette fois-ci en faisant un sort à l’omniprésent $('selector'). Rien qu’en supprimant ces 2 types d’appels, pas mal de petits projets devraient pouvoir se passer de jQuery, pour peu qu’ils de dépendent pas de plugins tiers pour certaines de leurs fonctionnalités.

Avant de commencer, voici une petite anecdote… Savez-vous que l’emploi de $('selector') est tellement commun que la fonction a même été intégrée dans certains navigateurs ? Par exemple, même sans jQuery, Google Chrome inclut une fonction globale $('selector') qui est un alias de querySelector('selector') au niveau du document. Elles ne font pas exactement la même chose (l’une sélectionnant plusieurs éléments, l’autre un seul), mais c’est assez similaire pour être noté.

Note : comme la plupart des codes sources proposés sur le blog, le code présent dans cet article est compatible avec Internet Explorer à partir de la version 11.

Sélection d’éléments avec jQuery

La sélection d’éléments est la base de jQuery. Cela s’effectue avec la fonction jQuery('selector') – alias $('selector') – à laquelle on passe un paramètre décrivant les éléments à sélectionner, paramètre que l’on appelle, en toute logique, un sélecteur.

Ce sélecteur doit décrire zéro, un ou plusieurs éléments présents dans la page. Deux sortes de sélecteurs sont disponibles :

  • Les sélecteurs CSS, qui ne sont pas inconnus à quiconque travaille avec le CSS3 standard. On peut citer par exemple le sélecteur par identifiant #identifiant, par classe .classe, par attribut [attribut="valeur"], par position dans l’arborescence :first-child et :last-child, par état sélectionné :selected, etc… Ces sélecteurs sont naturellement supportés par tous les navigateurs compatibles CSS3, sans nécessiter la présence de la librairie.
  • Les sélecteurs spécifiques à jQuery, qui apportent des fonctionnalités utiles absentes de la spécification CSS3, non-supportées par les navigateurs par défaut. On peut citer par exemple :visible (éléments visibles), :hidden (éléments invisibles)…

A noter que la sélection d’éléments renvoie un objet de type jQuery qui agit comme une sorte de tableau des éléments concernés, ce dernier pouvant être vide si aucun élément de la page ne remplit le critère demandé. Il n’y a pas de différence selon le nombre de résultats : zéro, un ou plusieurs, il y a toujours un objet jQuery de retourné.

Pour synthétiser, niveau code ca donne ça :

$("#identifiant"); // 0, 1, ou plusieurs éléments choisis par identifiant
$(".classe"); // 0, 1, ou plusieurs éléments choisis par classe
$("p"); // 0, 1, ou plusieurs éléments choisis par balise
$("p.classe"); // on peut combiner les sélecteurs

Optimisation et remplacement de jQuery

Sans jQuery, on peut sélectionner des éléments avec les fonctions querySelector('selector') et querySelectorAll('selector'), qui respectivement renvoient un élément (type Element) et une liste (type NodeList). Elles prennent en charge les sélecteurs supportés par le navigateur en cours d’utilisation par le visiteur, donc autant dire que pour les sélecteurs CSS3 il ne devrait pas y avoir de problème. Ces méthodes sont disponibles au niveau du document, ainsi que des éléments eux-mêmes :

// Au niveau du document

document.querySelector("#identifiant"); // null ou 1 élément choisi par identifiant
document.querySelector(".classe"); // null ou 1 élément choisi par classe
document.querySelectorAll("p"); // 0, 1 ou plusieurs éléments choisis par balise

// Au niveau d'un élément parent

var parent = document.querySelector("#identifiant");
parent.querySelector("#autre"); // null ou 1 enfant choisi par identifiant
parent.querySelectorAll("p"); // 0, 1 ou plusieurs enfants choisis par balise

Une grosse différence est au niveau des retours de ces fonctions :

  • La fonction querySelector('selector') renvoie un élément si possible, mais retourne null si aucun n’est trouvé satisfaisant le critère. Il est donc très important de vérifier le résultat avant de l’utiliser, pour éviter des erreurs inattendues. Avec jQuery, c’est facultatif, étant donné qu’appeler des fonctions sur un objet jQuery vide ne fait rien.
  • La fonction querySelectorAll('selector') renvoie une NodeList , qui n’est pas un élément elle-même. On ne peut donc pas appeler de fonctions spécifiques aux éléments dessus (pas de querySelector('selector') sur une NodeList par exemple), alors qu’un objet jQuery peut exécuter les mêmes fonctions, que ce dernier contienne zéro, un ou plusieurs éléments. Il est nécessaire de boucler sur les éléments de la NodeList et de traiter les éléments les uns après les autres.

Il y a aussi une différence au niveau des sélecteurs supportés, les sélecteurs spécifiques à jQuery n’étant pas supportés du tout par les navigateurs. Il n’y a malheureusement pas de solution toute faite, il faut en général repenser la logique du code. Par exemple, remplacer une sélection des éléments visibles (avec $("p:visible") par exemple) par une sélection des éléments possédant une classe qui les rend visibles (avec document.querySelectorAll("p.show") par exemple). Cela dépend du projet et des choix d’implémentation, mais je n’ai pas encore rencontré de situation où un remplacement n’ait pas été possible, l’utilisation des sélecteurs spécifiques étant souvent due à une méconnaissance – ou à un empressement – du développeur précédent.

Conclusion

Voila, vous devriez pouvoir supprimer les appels à $('selector') de vos codes sources maintenant ! Il ne reste plus qu’à s’occuper du cas des écouteurs d’évènements (pour gérer les clics par exemple), et un bout de chemin aura été fait dans le nettoyage des projets de taille raisonnable. Ca sera l’affaire du prochain article.

Bonus : boucler sur une liste d’éléments (forEach)

Concernant les NodeList, il est possible d’en récupérer les éléments comme s’il s’agissait d’un tableau :

var liste = document.querySelectorAll("p");

for(var index = 0; index < liste.length; index++){
  var element = liste[index];
  // Faire quelque chose avec l'élément ici
}

Les navigateurs récents proposent également la fonction forEach(), plus concise :

var liste = document.querySelectorAll("p");

liste.forEach(function(element, index){
  // Faire quelque chose avec l'élément ici
});

Malheureusement, les vieux navigateurs (surprise, Internet Explorer 11 par exemple) ne proposent pas la fonction forEach() sur les NodeList. Pour y pallier la fondation Mozilla nous propose ce polyfill, à déployer avant le code utilisant forEach() :

if (window.NodeList && !NodeList.prototype.forEach) {
  NodeList.prototype.forEach = function (callback, thisArg) {
    thisArg = thisArg || window;
    for (var i = 0; i < this.length; i++) {
      callback.call(thisArg, this[i], i, this);
    }
  };
}

On peut aussi se passer de polyfill – pour peu que le navigateur supporte la fonction forEach() sur les tableaux comme c’est le cas pour Internet Explorer 11 – mais c’est moins lisible (je ne recommande pas, mais on le rencontre parfois dans certains projets) :

var liste = document.querySelectorAll("p");

Array.prototype.forEach.call(liste, function(element, index){
  // Faire quelque chose avec l'élément ici
});

Références

Mozilla Developers – Document.querySelector()
Mozilla Developers – Document.querySelectorAll
Mozilla Developers – NodeList.forEach()
jQuery Documentation – Extensions des sélecteurs

Photo de profil de Loïc Burtin Code Colibri développeur web à Dijon

A propos de l'auteur

Loïc Burtin

Développeur web indépendant, avec une tendance à couper les plumes en quatre pour que les sites se chargent plus rapidement.

Partagez cet article  =>