Nouveautés Safari 3.1 : getElementsByClassName
jeudi 10 avril 2008 - 3 commentaires
Allez, on continue dans Webkit (parce que ça me botte en ce moment). Je ne suis pas tombé sur beaucoup d'articles en français résumant les nouveautés de Safari 3.1. Et comme on n'est jamais mieux servi que par soi-même...
Commençons par getElementsByClassName
. Kékecé ? À l'instar des getElementById
, getElementsByTagName
, getElementsByName
c'est une méthode pour récupérer des éléments du DOM selon un critère, en l'occurence la ou les classes. Par exemple, sur la page d'accueil de ce blog, document.getElementsByClassName('post').length
renvoie 20 mais document.getElementsByClassName('post odd').length
renvoie 10. Comme toutes ces consœurs, cette méthode marche aussi à partir d'un élément du DOM, restreignant ainsi les résultats.
Il faut faire attention en manipulant la liste renvoyée. Elle est "live", c'est-à-dire que tout changement dans le DOM la modifie (comme getElementsByTagName
).
Exemple:
var list = document.getElementsByClassName('post'); for (var i=0; i < list.length; i++) { list[i].parentNode.removeChild(list[i]); alert(list.length); }
En exécutant cette fonction sur la page d'accueil, on verra disparaître un billet sur deux et la NodeList
diminuera au fur et à mesure. Attention donc en manipulant les résultats. Pour être sûr de ce qui va se passer, on peut recopier le tout dans un tableau classique, mais attention aux performances.
Cette méthode est actuellement supportée par Safari 3.1 (of course) et bientôt Firefox 3 et Opera 9.5. Elle fait partie du brouillon pour HTML 5.
Vous voyez évidemment à quoi ça sert ? Ça accélère considérablement tous les accès qu'on peut faire, si on l'utilise. Et comme de plus en plus de gens utilisent des librairies pour ne pas s'embêter avec les compatibilités entre navigateurs, on va vérifier qu'on bénéficie bien de cette amélioration quand disponible. On va surtout étudier les méthodes du style $ ou $$, qui permettent de sélectionner des éléments à partir d'un sélecteur CSS
- Prototype n'a pas. Pire, ça peut casser dans les anciennes versions.
- jQuery : y a pas non plus.
- mootools : y a pas.
- YUI : non plus.
- base2 : non plus.
Bilan : Ah bah c'est pas génial. Si j'étais mesquin, je dirais que c'est une raison de plus pour ne pas utiliser de librairies Javascript. À leur décharge, ce n'est pas vraiment nécessaire puisqu'elles utilisent XPath lorsque c'est disponible et c'est disponible sur tous les navigateurs ayant cette méthode. Pour jQuery, c'est regrettable, puisqu'elle n'a pas d'implémentation XPath. Bien évidemment, XPath est plus rapide que DOM, mais tout de même plus lent que getElementsByClassName.
Mais finalement, on verra bientôt qu'il y a d'autres méthodes pour nous aider.
Commentaires
Calme, ces navigateurs ne sont pas encore sortis alors laisse le temps aux bibliothèques d'intégrer les nouveautés. Quand au moins un de ces navigateurs sera publié, là on pourra regarder car (malheureusement) certaines lib implémenteront un fallback.
Je dis malheureusement parce que getElementsBy* est le genre de fonctionnalités qu'on ne pourra pas implémenter en javascript. Si fallback il y a il sera incomplet ou différent de la spec et de l'implémentation des navigateurs.
Le problème vient du fait que les navigateurs retournent des listes de noeuds "live", qui sont impactées par les changements dans le DOM. Les bibliothèques ne peuvent que retourner des tableaux statiques contenant des références vers les noeuds DOM.
Demander aux bibliothèques javascript d'implémenter getElementsByClassName quand le navigateur ne le supporte pas c'est leur demander de faire de violer les specs et d'avoir des implémentations divergeantes.
Ils ont choisi de ne pas le faire, et ils ont raison là dessus. Si tu veux un tableau statique de noeuds DOM, toutes ces bibliothèques ont déjà des méthodes pour ça.
Déjà, Safari 3.1 est bien sorti :) C'est pour cela que j'ai regardé les libs.
Par contre, mon message est ambigu. Je parlais d'utiliser getElementsByClassName pour leurs recherches basées sur les sélecteurs CSS. Ça demande de changer leur algo (et c'est pas immédiat), mais quel bénéfice pour les utilisateurs.
Par contre, je vais modifier le billet, parce que j'avais oublié de préciser le côté "live" de la liste retournée.
La technique getElementsByClassName est trés interressante car ses performances sont meilleures que tout autre méthodes de sélection même si on ne passe pas par les fonctions natives de Firefox 3 ou Safari 3.
A noter que si on simule cette fonction via XPath, c'est moins bon.
Et pour info, c'est beaucoup plus rapide en Javascript (pour le rendu) de modifier la class d'un element plutot que de modifier ses attributs de style CSS un par un.
Perso, j'utilise une lib* compatible IE6/Firefox2/Safari pour les profiles de LiFE2Front, et çà me permet de faire du tri/filtrage de contenu instantanément avec de bonnes performances. Mais inconvenient ; çà fait grincer Prototype, JQuery, Yahoo! UI, ou Dojo :o(
(*) cliquer sur ma signature pour voir une démo avec mon profil. La lib est citée dans les crédits en bas de page.