Bloguons JavaScript

Parce que je me dis tout le temps : « Faut que j'écrive ça quelque part. »
Home

Aller au menu | Aller à la recherche

Remplacer jQuery

Si vous faites la maintenance d'un site web où il y a du javascript qui utilise la bibliothèque jQuery, vous pourriez être tenté de vouloir mettre à la porte cette dernière qui, bien que sa dernière mouture ait été allégée du support d'anciens navigateurs microsoftiens, devient de plus en plus obsolète en termes de nécessité et de fonctionnalités. Effectivement, à quoi ça sert de charger un code compressé de 30 kibi-octets alors que vous pourriez dialoguer avec votre DOM et vos requêtes AJAX directement en utilisant le javascript vanille?

Cependant, il faut avouer que la conversion jQuery vers javascript vanille ne peut pas se faire sans heurt. Il y a des concepts jQuery qui ne se retrouvent pas ailleurs.

On va essayer de les lever ici.

Fil des billets Fil des commentaires

La force de la méthode forEach()

, 11:50

Pour boucler dans un lot d'éléments DOM, rien de mieux que d'utiliser .forEach(), et ainsi de remplacer la méthode jQuery .each().

Lire la suite...

insertAdjacentHTML, alternative à jQuery append(), prepend(), before() et after()

, 10:47

Billet très court. Ce remplacement est assez facile à réaliser.

Lire la suite...

fetch(), la suite : annuler les requêtes

, 13:29

Dans mon billet sur fetch(), j'avais laissé entendre que je ne comprenais pas tout de la méthode.

Lire la suite...

Remplacer slideDown() et slideUp() dans jQuery

, 22:46

Ce n'est pas facile de trouver une solution aisée à remplacer les méthodes $.slideDown() et $.slideUp(), qui servent essentiellement à plier et déplier des boîtes verticalement. Heureusement, Javascript a assez évolué pour pouvoir programmer une alternative assez succincte.

Lire la suite...

jQuery doit mourir

, 02:27

Ok, le titre est un peu exagéré. Mais jQuery est devenu somme toute une tare dans la programmation JavaScript. Aujourd'hui, utiliser jQuery retarde l'apprentissage du JavaScript. jQuery demande le chargement d'une bibliothèque de plus de 200 kibioctets, ce qui peut paraître léger pour un ordinateur de bureau, mais très lourd pour un mobile. Et son utilisation, tout comme n'importe quelle bibliothèque, impose souvent ce constat : on charge du code qui ne sera jamais utilisé.

Ceci dit, je dois reconnaître les bons coups de jQuery, et sa grande pertinence au moment où il a été créé. Le projet est publié pour la première fois en janvier 2006, à un moment où Internet Explorer 7 n'était même pas encore sorti. Et Internet Explorer 6, rempli de bogues. Mozilla Firefox gagnait des parts de marché. Google Chrome n'existait pas. Bref, à ce moment-là jQuery facilitait l'utilisation de JavaScript, un langage qui n'était pas interprété de la même façon par les deux navigateurs concurrents, dont l'un avait été littéralement abandonné par son éditeur (IE6 était sorti en 2001). jQuery "patchait" les lacunes de l'un et même parfois celles de l'autre. jQuery permettait alors de coder du JavaScript sans se soucier si c'était du JavaScript IE ou du JavaScript Mozilla.

Depuis sa création, Google Chrome est apparu, utilisant le même moteur de rendu que KHTML, un navigateur sous Linux. Respectueux des standards du web, tout comme Mozilla Firefox, et agressif du côté de sa mise en marché, il est devenu le navigateur dominant, éclipsant Internet Explorer. Microsoft renomme IE en Edge, et finit par utiliser le même moteur de rendu que Chrome, étant devant le fait accompli qu'il ne pouvait pas suivre la cadence de l'évolution des standards, face à deux navigateurs concurrents utilisant des moteurs de rendu à code source ouvert. Depuis que jQuery est né, les téléphones cellulaires ont fait leur apparition, avec le premier iPhone en 2007, suivi d'Android peu de temps après, et qui a fait que la majorité de la navigation web se fait sur mobile que sur un ordinateur de bureau. Tous ces navigateurs tournent avec un moteur JavaScript respectant un standard ECMAScript. jQuery n'a ici plus besoin de "patcher".

Donc aujourd'hui, les navigateurs doivent exécuter du code JavaScript court et rapide à exécuter. L'utilisation de jQuery permettait de coder court, mais jQuery lui-même ne l'était vraiment pas. Et plus il y a de code JavaScript dans une page, plus la création d'objets jQuery (à force de faire des $() par ci, et des $() par là), devient lourde en mémoire. Et à mesure que le JavaScript évolue, avec l'apparition de querySelector() et querySelectorAll(), ainsi que de fetch() et closest(), plus le besoin de recourir à jQuery s'amenuise. Tant et si bien qu'en 2022, jQuery n'est carrément plus utile.

Non seulement, il n'est plus utile, mais il nuit à la compréhension pour le novice de ce qu'est le DOM. À force de vouloir encapsuler les éléments de la page web dans ses objets, jQuery crée une distance inutile pour traiter la page web.

Qui plus est, sur des sites en maintenance, il peut conduire à l'apparition de code mort. document.getElementById('serie').classList.add('fr') est équivalent à $('#serie').addClass('fr'). Mais si plus tard, on supprime du code HTML l'élément "#serie", le code jQuery continuera de s'exécuter sans aucun message d'erreur, alors qu'il aurait dû être supprimé aussi en même temps.

De plus, le code jQuery exécute une création d'objet jQuery contenant une liste d'objets sur laquelle il va itérer pour ajouter à tous les éléments la classe 'fr', alors que le programmeur sait très bien qu'il n'a pas de liste à impliquer dans son opération. En termes de rapidité, document.getElementById('serie') est 25 fois plus rapide que $('#serie').

Voilà pourquoi en partie l'existence de ce blogue. Je veux faire connaître JavaScript dans ce qu'il a de plus pur, sans bibliothèques. Vous remarquerez alors à quel point le langage est rapide et puissant lorsqu'il est débarrassé de cossins voulant révolutionner ce qui est déjà révolutionnaire.

La beauté de la combinaison de addEventListener() et closest()

, 03:51

Pour remplacer la méthode jQuery.on(), ou son ancêtre jQuery.live(), qui permettent d'attacher un événement virtuellement à des éléments qui n'existent pas encore au moment de l'appel, ces deux méthodes sont très utiles.

EventTarget.addEventListener() existe depuis longtemps. En fait, c'est Internet Explorer (encore) qui a été le dernier à l'intégrer, à sa version 9. Ça fait quand même une couple de lunes.

La méthode Element.closest(), quant à elle, est un peu plus récente. Implémentée dans Chrome et Firefox au début de 2016 et dans Edge fin 2017, elle permet d'imiter quelque peu la méthode jQuery.parent() lorsqu'elle contient un sélecteur CSS, à la différence suivante:

Considérant :

<div class='a'>
<div id='moi' class='b'><;/div>
</div>

document.getElementById('moi').closest('.b').className='b c'; // Ajoutera la classe 'c' dans div#moi
$('#moi').parent('.b').addClass('c'); // Ne fera rien.

Autrement dit, element.closest() commence à chercher à partir de lui-même, alors que $(element).parent() commence à chercher à partir de son premier parent.

addEventListener + closest = $.on()

Là où ça devient intéressant, c'est que la méthode jQuery.live(), et son successeur $.on() qui permettent d'attacher un événement à des éléments de la page qui peuvent apparaître ou disparaître en cours de route, devient plus facile à faire en javascript vanille.

Là où l'on utilisait:

$("body").on("click", "a", function(event) {
   event.preventDefault();
   alert("Tu as cliqué sur un lien!")
});

On peut maintenant utiliser, sans jQuery:

document.body.addEventListener("click", event => {
   const a = event.target.closest("a");
   if (!a) return;
   event.preventDefault();
   alert("Tu as cliqué sur un lien!")
});

Javacript - La suppression des événements avec removeEventListener() au lieu de $.off()

, 20:45

L'affaire qui se passe, c'est que $(el).on() ne fait pas seulement la même chose que el.addEventListener(). $(el).on() enregistre aussi l'événement dans une liste d'événements d'un certain type (ex:'click') pour que si jamais on fasse $.off() sur le même type d'événement, ça puisse les effacer.

Une façon de faire pour effacer tous les événements possibles sur un élément serait el.outerHTML=el.outerHTML; ... sauf que ça supprime TOUS les événements de TOUS les types.

Idéalement, 2 trucs:

  • Soit on nomme l'événement (autrement dit, une fonction qu'on retient dans une variable) :
    var el = document.querySelector('textarea');
    var foo = () => console.log('Allô!');
    el.addEventListener('click', foo); // ajoute
    el.removeEventListener('click', foo); // enlève
    
  • Soit on attache l'événement à son élément parent, au pire à document.body (live binding) :
    document.body.addEventListener('click', e => {
        const el = e.target.closest('textarea'); 
        if (!el) return;
        console.log('Allô!');
    }

Remplacer $.get(), $.post(), $.ajax() et $.getJSON() par fetch()

, 20:27

Dieu merci, on a créé une méthode pour remplacer l'inutilement compliqué XMLHttpRequest. Par contre, fetch() retourne un type d'objet qui n'est pas toujours bien compris par les développeurs. Et je m'y inclus...

Mais bon, ça permet toujours bien de créer des appels XHR sans trop de code superflu.

Pour un appel avec la méthode GET, remplacer :

$.get(url,function(data){/*CODE*/});

par :

fetch(url).then(p => p.text()).then(data => {/*CODE*/});

Pour un appel avec la méthode GET qui est sensé retourner un objet JSON, remplacer :

$.getJSON(url, function (data) {/*CODE*/});

par :

fetch(url).then(p => p.json()).then(data => {/*CODE*/});

Pour un appel avec la méthode POST, remplacer :

$.post(url,{a:1,b:2},function(data){/*CODE*/};

par :

fetch(url,{method:'POST',body:"a=1&b=2"}).then(p=>p.text()).then(data => {/*CODE*/});

Et pour un POST retournant un JSON, réutiliser la méthode ci-dessus en changeant p.text() par p.json().

Évidemment, j'y vais sommairement, parce que l'utilisation successive des méthodes .then() n'y est pas pour faire joli; cela permet surtout de trapper les exceptions, en ajoutant par exemple un .catch() à la toute fin, au cas où l'appel retournerait une erreur 404, un objet JSON cassé, ou je ne sais quoi d'autre.

 

La "sérialisation" des formulaires

, 17:13

C'est tellement facile avec jQuery, et jadis autrement plus compliqué en JS vanille. Heureusement, ça s'est (un peu) amélioré dans les dernières années, avec la venue de deux nouveaux types d'objets : FormData et URLSearchParams.

Normalement les deux expressions suivantes devraient donner le même résultat :

const r = $(form).serialize();
// ou
const r = (new window.URLSearchParams(new FormData(form)).toString());

Je dis bien « devrait », mais ça se peut qu'il y ait des différences d'encodages. Bref, on ne peut pas remplacer une expression par l'autre en toute confiance sans tester.