Javascript non-intrusif, chapitre 4 : l’appel des scripts de la forêt
Cet article est le quatrième d'une série qui en compte 5.
La principale technique utilisée pour garder notre code Javascript non-intrusif est de le stocker dans un fichier séparé au lieu de le mettre en vrac dans le balisage HTML. Pour exécuter les fonctions présentes dans notre fichier .js
, nous devons les appeler lors du chargement de la page. Ceci peut être fait de plusieurs façons, chacune ayant ses avantages et ses inconvénients.
La méthode « à l'ancienne »
Lorsque nous étions jeunes et innocents, nous ajoutions onload
à l'élément body
.
HTML : <body onload="foo();">
Mais nous savons désormais que c'était une mauvaise méthode et qu'il ne faut surtout plus l'utiliser à présent !
Si nous appelons le(s) script(s) dans l'élément body
, nous n'avons rien changé dans la mesure où nous mélangeons encore le balisage et les appels d'événements. Il nous faut séparer les appels et les placer dans le fichier .js
.
La méthode séparée
Pour faire cela, nous lions l'appel à l'événement onload
de l'objet window
.
Lorsqu'on n'utilise qu'une fonction, il n'est pas nécessaire d'ajouter des parenthèses à la fin de son nom, car cela aurait pour effet de renvoyer le résultat de la fonction au lieu de la déclencher.
Si nous avons plus d'une fonction, il faut par contre utiliser une fonction anonyme qui appellera les autres, en utilisant cette fois-ci des parenthèses.
Javascript : window.onload=foo; ou window.onload=function(){ foo(); bar(); baz(); }
Cette méthode d'appel de fonctions ne s'applique évidemment pas qu'à l'objet window
. Comme montré précédemment, nous pouvons l'ajouter à n'importe quel objet de la page. Cela est compris et interprété par tous les navigateurs compatibles Javascript/DOM.
L'inconvénient, c'est que nous ne sommes pas ici totalement non-intrusifs. Si nous avions plus d'un .js
à inclure, chacun écraserait les appels onload
des autres.
La méthode vraiment non-intrusive
Il existe une option permettant d'ajouter des gestionnaires d'événements à des gestionnaires déjà existants. Malheureusement, les différents navigateurs gèrent cette fonctionnalité de façon différente, et la version Mac d'Internet Explorer ne la gère pas du tout.
Scott Andrew a écrit une sympathique petite fonction réutilisable qui fait exactement cela, et qu'on peut appeler en passant en paramètres l'objet auquel il faut attacher l'événement, le type d'événement, et le nom de la fonction à appeler.
function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, false); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', foo); addEvent(window, 'load', bar);
L'inconvénient majeur reste que ceci n'attachera rien du tout sur les version Mac d'IE.
La voix d'Opera
J'ai reçu un e-mail du support technique d'Opera m'expliquant que l'exemple précédent (NdT : visiblement corrigé depuis) n'était pas tout à fait correct, et c'est d'ailleurs la raison pour laquelle il est (NdT : ou a pu être) différent de celui présenté sur le site de Scott :
La fonction
addEvent
n'est pas tout à fait conforme aux standards. Elle fonctionne pour l'instant avec Firefox, mais une fois que ce bug aura été corrigé elle ne fonctionnera plus du tout. C'est la raison pour laquelle elle ne fait pas exactement ce à quoi vous vous attendez dans Opera, qui est conforme aux standards sur ce point. Le problème est que vous définissez un gestionnaire d'événements « capturant » en utilisanttrue
en troisième paramètre dans la fonctionaddEventListener
:if (obj.addEventListener){ obj.addEventListener(evType, fn, true);Ce
true
devrait en fait êtrefalse
. En utilisanttrue
, le gestionnaire ne se déclenchera pour aucun des éléments pour lequel il est programmé. Par exemple, si vous l'utilisez sur un élémentli
, rien ne se passera, sauf si les élémentsli
ont des enfants. Faites le test dans Opera :)
Quelques lectures complémentaires
Les événements sont des sujets complexes et assez confus en Javascript. Pour le développement de sites Web, les exemples proposés ici suffisent, mais si on se plonge dans le développement d'applications Web, il faudra approfondir le sujet. Allez jeter un œil aux liens disponibles dans l'annexe « Articles utiles » (NdT : voir la traduction du dernier article de la série) pour plus d'informations sur les événements et sur les différentes façons de les appliquer à des éléments.
Pourquoi ne pas essayer ?
Il vous suffit de télécharger cet exemple, et de réaliser les tâches fixées. Suivez les liens pour voir les solutions possibles. Le code Javascript est directement intégré dans le HTML de mes exemples, alors qu'il devrait être inséré dans un fichier externe. J'ai en effet tout mis dans un seul fichier pour simplifier votre lecture.
- Prenez ce tableau et utilisez une fonction non-intrusive pour changer la couleur des lignes impaires. Ajoutez une autre couleur lorsque l'utilisateur passe la souris au-dessus d'une ligne. Voir la solution.
- Ajoutez une fonction à chaque élément
p
doté d'une classetrigger
qui permette d'afficher ou de masquer l'élément suivant (en mettant sa propriété CSSdisplay
àblock
ounone
). Voir la solution.
» À suivre : « Javascript non-intrusif, chapitre 5 : un exemple de formulaire amélioré en Javascript ».
http://www.onlinetools.org/articles/unobtrusivejavascript/chapter4.html