III. Un espace de noms (« namespacing »)▲
III-A. Rappel▲
Nous avons vu que la clôture offre un espace privé où le symbole $ est exclusivement attribué à jQuery.
Nous avons vu que la fonction globale permet d'obtenir un point d'entrée dans la clôture jQuery, mais au prix d'une pollution de l'espace de noms.
III-B. Introduction▲
(4) Je cite4 :
« Un espace de noms est une notion permettant de lever une ambiguïté sur des termes qui pourraient être homonymes sans cela. Il est matérialisé par un préfixe identifiant de manière unique la signification d'un terme. Au sein d'un même espace de noms, il n'y a pas d'homonymes. Les espaces de noms aident à la construction de programmes modulaires ».
Fin de la citation4
(5) Je vous invite à lire, au minimum, les pages 3 à 6 de l'excellent tutoriel de Nourdine Falola : Espaces de noms (ou namespace) en JavaScript. Ces pages constituent l'introduction indispensable à la suite de cet article.
Idéalement, votre code ne doit être accessible qu'au travers d'un et d'un seul objet global.
III-C. Comment ?▲
Comme notre espace de noms contiendra du code jQuery, nous devons utiliser la clôture jQuery.
La première solution qui vient à l'esprit est de construire un objet global dans l'espace de noms window à l'intérieur d'une clôture jQuery.
On peut également construire un objet global dans l'espace de noms jQuery :
(
fonction
(
$){
$.
monObjet =
{
...
}
;
}
)(
jQuery);
à l'intérieur d'une clôture jQuery.
III-D. Solution▲
Après avoir testé ces deux approches, une troisième solution a ma préférence.
Il s'agit toujours de construire un objet global dans l'espace de noms window, mais c'est la clôture jQuery qui génère l'objet grâce à l'écriture JSON.
Suivant votre degré d'expérience dans l'écriture de code JSON cette solution peut vous paraître complexe, mais il me semble qu'elle est d'un usage plus simple que les deux approches évoquées ci-dessus. De même, la gestion des exceptions et la création des sous-espaces de noms me semblent plus faciles et plus fiables.
JavaScript est très efficace pour résoudre une expression d'appel complexe, vous ne devez pas craindre la très légère diminution des performances qui en résulte, car elle est compensée largement par l'aspect auto documentaire et la fiabilité de votre code.
III-E. Espace de noms dvjh▲
En notation JSON, l'objet global dvjh peut s'écrire comme suit :
try {
var dvjh =
{
isdvjh
:
"dvjh/danielhagnoul"
,
isMe
:
function(
){
return this.
isdvjh;
},
infos
:
function(
){
return "Espace de noms dvjh."
;
}
};
}
catch(
err){
alert
(
err);
}
Avec la génération par la clôture jQuery :
try {
var dvjh = (
function(
$) {
//notre clôture peut toujours contenir variables,
//fonctions et objets privés.
var isdvjh =
"dvjh/danielhagnoul"
;
return {
isMe
:
function(
){
return isdvjh;
},
infos
:
function(
){
return "Espace de noms dvjh"
;
}
};
}
)(
jQuery);
}
catch(
err){
alert
(
err);
}
Et le sous-espace de noms dvjh.math :
try {
dvjh.
math = (
function(
$) {
var isdvjh =
"dvjh_math/danielhagnoul"
;
if (
dvjh.isMe
(
) !=
"dvjh/danielhagnoul/"
) return null;
return {
isMe
:
function(
){
return isdvjh;
},
infos
:
function(
){
return "Espace de noms dvjh.math"
;
}
};
}
)(
jQuery);
}
catch(
err){
alert
(
err);
}
La gestion des exceptions et le test sur isMe nous assurent de l'existence d'un objet dvjh et que cet objet dvjh est bien le nôtre.
III-F. Composition de l'espace de noms dvjh le 9 août 2009▲
L'espace de noms dvjh doit être vu comme un « proof of concept » (une démonstration de faisabilité), il vous montre comment réaliser un espace de noms en jQuery, il ne s'agit pas d'un espace de noms de référence.
J'ai toutefois pris soin de le remplir soit avec des codes utiles pour jQuery soit avec des exemples de code intéressants.
Ci-dessous, le contenu de l'interface de l'espace de noms dvjh et de ses sous-espaces.
III-F-1. dvjh▲
Exception type dvjh : dvjh.exception(message, args);
alert(contenu de l'exception) : dvjh.displayException(exc);
Séparateur de texte : dvjh.separateur(s);
Interface de dvjh : dvjh.infos();
Le fichier dvjh.js contient également des fonctions utiles pour jQuery :
(6) jQuery delay plugin de James Padlosey ;
(7) Regex Selector for jQuery de James Padlosey ;
et le selecteur contains dans une clôture annexe.
(8) Ainsi que Function.prototype.memoize de Keith Gaughan qui est utilisé dans dvjh.math et dvjh.math.statistic.
(9) Je cite9 :
« La mémoization est une technique d'optimisation de code consistant à réduire le temps d'exécution d'une fonction en mémorisant ses résultats d'une fois sur l'autre. Bien que liée à la notion de cache, la mémoization désigne une technique bien distincte de celles mises en œuvre dans les algorithmes de gestion de la mémoire cache. »
« Une fonction mémoizée stocke les résultats de ses appels précédents dans une table et, lorsqu'elle est appelée à nouveau avec les mêmes paramètres, renvoie la valeur stockée au lieu de la recalculer. »
« Une fonction peut être mémoizée seulement si elle est référentiellement transparente, c'est-à-dire si sa valeur de retour ne dépend que de la valeur de ses arguments. »
« La mémoization est une façon de diminuer le temps de calcul d'une fonction, au prix d'une occupation mémoire plus importante. »
Fin de la citation9
III-F-2. dvjh.math▲
Modulo informatique : dvjh.modulo(a, b);
Nombre de Fibonacci : dvjh.fib(n);
Nombre d'or à la puissance n : dvjh.phi(n);
Interface de dvjh.math : dvjh.math.infos();
dvjh.math montre comment créer un sous-espace de noms. En dehors du modulo informatique, dvjh.math donne un exemple d'application de la mémoization pour le calcul du Nombre de Fibonacci.
III-F-3. dvjh.math.statistic▲
Factorielle de n : dvjh.math.statistic.fact(n);
Nombre d'arrangements à k éléments : dvjh.math.statistic.arran(n,k);
Nombre de combinaisons à k éléments : dvjh.math.statistic.combi(n,k);
Interface de dvjh.math.statistic : dvjh.math.statistic.infos();
dvjh.math.statistic montre comment créer un sous-sous-espace de noms et donne un exemple d'application de la mémoization pour le calcul de la Factorielle.
III-F-4. dvjh.calendar▲
Date vers jour julien : dvjh.calendar.date_to_jj(an,mois,jours,heures,minutes,secondes);
Jour julien vers date : dvjh.calendar.jj_to_date(jj);
Jour de la semaine : dvjh.calendar.joursemaine(jj);
Jour julien vers jour julien modifié : dvjh.calendar.jj_to_mjd(jj);
Jour julien modifié vers jour julien : dvjh.calendar.mjd_to_jj(mjd);
Interface de dvjh.calendar : dvjh.calendar.infos();
Les astronomes et les historiens amateurs ne se poseront pas la question de l'utilité des Jours julien. Pour les autres, je signale que la manipulation de dates par l'intermédiaire des JJ est beaucoup plus simple qu'il n'y paraît.
(10) Je cite10:
« La période julienne est une numérotation continue et décimale des jours, indépendante du calendrier, de l'année, du mois, du jour de la semaine et du numéro du jour dans le mois. »
« Elle a pour origine le 1er janvier de l'an 4713 avant notre ère (c'est-à-dire le 1er janvier - 4712 en notation des astronomes). »
« La continuité des jours permet de calculer un intervalle de temps sans risque d'erreur même s'il couvre à la fois le calendrier julien et grégorien. Les formules de calcul tiennent compte du changement de calendrier qui a eu lieu en 1582. »
« Exemple : le 1er janvier 1001 (calendrier julien) à 0 h correspond au jour julien 2 086 673,5 ; le 1er janvier 2001 (1000 ans plus tard, mais en calendrier grégorien) à 0 h correspond au jour julien 2 451 910,5. Entre ces deux dates, il s'est donc écoulé 365 237 jours. Remarquez qu'il ne s'est pas écoulé 365 250 comme on pourrait le déduire un peu rapidement. Il manque les 10 jours dus à l'introduction du calendrier grégorien et les 3 jours bissextils qui n'ont pas été ajoutés en 1700, 1800 et 1900. »
Fin de la citation10 .
III-F-5. dvjh.effects▲
Animer en suivant l'ordre : dvjh.effects.byOrder(jQueryObjets, params, duration, easing, callback);
Interface de dvjh.effects : dvjh.effects.infos();
dvjh.
effects.byOrder
(
$(
'.image_menu_on'
),
{
width
:
400
,
height
:
300
},
1000
,
'easeInSine'
,
function(
){
alert
(
'wow!'
)}
);
La fonction byOrder() applique à tour de rôle la même animation à chaque objet jQuery contenu dans l'array jQueryObjets.
Le code de la fonction byOrder() n'est pas de moi, je sais l'avoir vu et copié sur l'Internet, mais j'ai perdu la référence. Mille excuses à l'auteur !
III-F-6. dvjh.utilities▲
Regroupement de fonctions globales.
Interface de dvjh.utilities : dvjh.utilities.infos();
Sers de point d'ancrage pour les fonctions globales (objets globaux).
III-F-7. dvjh.utilities.contentTable()▲
dvjh.
utilities.contentTable
(
'conteneur'
,
'tdm'
,
6
,
{
tdmTitre
:
'Sommaire'
}
);
(11) Cette fonction globale (idée et code originaux de Giminik, version jQuery de Daniel Hagnoul) permet de construire une table des matières.
III-G. Fichiers▲
Le code de l'espace de noms dvjh et de ses sous-espaces est trop long pour être reproduit ici.
Je vous invite à copier et examiner les fichiers composant l'espace de noms et à regarder les tests.
III-H. Nota bene▲
Lorsque vous construirez votre propre espace de noms, pensez à lui donner un nom suffisamment long pour que le risque de collision avec un autre espace de noms soit réduit, il eut été préférable de nommer mon espace de noms danielhagnoul plutôt que dvjh, mais on se défait difficilement d'une mauvaise habitude.