Overblog
Editer l'article Suivre ce blog Administration + Créer mon blog
13 juin 2010 7 13 /06 /juin /2010 23:00

Attaquons-nous au programme bodyCateg.js dont le mode d'emploi se trouve ici.

Ce  démontage  est un peu différent des autres : je me suis appuyé sur un programme existant plutôt que de partir de zéro. La confection du programme fut brève, cet article le sera aussi.

Petite analyse

Le programme projeté se trouve face à une page de blog, que doit-il faire ? Réponse rapide :

  1. si la page ne contient ni article ni résumé d'article : rien ;
  2. sinon, si la page contient des articles ou résumés d'article de catégories différentes : encore rien ;
  3. enfin, si et seulement si tous les articles ou résumés sont de même catégorie : ajouter une classe au body.

Trouver tous les articles (ou résumés) d'une page pour lire leur catégorie, on l'a déjà fait : voir  Démontage : 'Styler' les articles selon leur catégorie . Seule change ici l'utilisation de ces catégories, on verra ça en détail plus loin. Partons donc de ce programme de traitement des articles.

Premier jet

 function bodyCateg() { var rArt=document.getElementById('article1'),testReg=/\barticle\b/,i,r,rr,newClass; if (!rArt) rArt=document.getElementById('articleSeul'); if (!rArt) {rArt=document.getElementById('extraitArticle1'); testReg=/\bextraitArticle\b/;} if (!rArt) return; do { if (!rArt.className || !testReg.test(rArt.className)) continue; newClass='categorie-aucune'; rr=rArt.getElementsByTagName('a'); for (i=0;r=rr[i];i++) { if (!r.className || !/\blinkTopic\b/.test(r.className)) continue; newClass=r.href.split('\/'); newClass=newClass[newClass.length-1]; newClass=newClass.split('.'); newClass=newClass[0]; break; } rArt.className+=' '+newClass; }while(rArt=rArt.nextSibling); } bodyCateg(); 

Ça, c'est le programme reclasseArticles.js dans lequel je n'ai changé que le nom de la fonction : reclasseArticles est devenu bodyCateg.

Clarification

Ce programme est essentiellement une boucle sur tous les articles s'il en existe, boucle qui détermine et utilise la catégorie d'article de la même manière pour tous les articles. Celui que nous voulons faire est un peu différent : il doit trouver la catégorie du premier article puis la comparer à celle de chacun des autres articles. La suite du programme dépend du résultat de cette comparaison.

Première idée, autant pour préparer l'avenir que pour y voir plus clair : mettre à part le calcul de catégorie, autrement dit créer une fonction :

 function bodyCateg() { function getCateg(a) { var i,r,rr,c; c='categorie-aucune'; rr=a.getElementsByTagName('a'); for (i=0;r=rr[i];i++) { if (!r.className || !/\blinkTopic\b/.test(r.className)) continue; c=r.href.split('\/').pop().split('.')[0]; break; } return c } var rArt=document.getElementById('article1'),testReg=/\barticle\b/,newClass; if (!rArt) rArt=document.getElementById('articleSeul'); if (!rArt) {rArt=document.getElementById('extraitArticle1'); testReg=/\bextraitArticle\b/;} if (!rArt) return; do { if (!rArt.className || !testReg.test(rArt.className)) continue; newClass=getCateg(rArt); rArt.className+=' '+newClass; }while(rArt=rArt.nextSibling); } bodyCateg(); 

Prenez le temps de comparer : vous verrez que ces deux programmes sont équivalents. Alors pourquoi n'avoir pas écrit ainsi d'emblée ? Pure flemme ! Remarquez aussi que la fonction getCateg est écrite à l'intérieur de la fonction principale bodyCateg : fidèle à mes principes d'encapsulation, j'ai voulu que cette fonction n'ait de sens que dans bodyCateg, qu'elle ne risque pas d'entrer en conflit avec un possible autre getCateg défini ailleurs.

Modification

Maintenant on fait du neuf : il faut d'abord récupérer la classe du premier article, ensuite modifier la boucle pour qu'elle n'examine que les articles suivants. Je vous propose (impose, mais chut !) ceci :

 function bodyCateg() { function getCateg(a) { var i,r,rr,c; c='categorie-aucune'; rr=a.getElementsByTagName('a'); for (i=0;r=rr[i];i++) { if (!r.className || !/\blinkTopic\b/.test(r.className)) continue; c=r.href.split('\/').pop().split('.')[0]; break; } return c } var rArt=document.getElementById('article1'),testReg=/\barticle\b/,categ; if (!rArt) rArt=document.getElementById('articleSeul'); if (!rArt) {rArt=document.getElementById('extraitArticle1'); testReg=/\bextraitArticle\b/;} if (!rArt) return; categ=getCateg(rArt) // Catégorie du premier article while(rArt=rArt.nextSibling) { // NB : la boucle commence APRES le 1er article if (!rArt.className || !testReg.test(rArt.className)) continue; if(getCateg(rArt)!=categ)return; // Dès qu'un article sort du rang : abandon } // Si on arrive ici tout va bien // Traitement final } bodyCateg(); 

Tant que j'y étais j'ai changé le nom newClass en categ : m'a semblé plus parlant. Notez aussi le passage d'une boucle do {...} while(...) à une boucle while(...) {...} : la première s'exécute au moins une fois et décide à la fin de recommencer ou non, l'autre décide au début de s'exécuter (encore) une fois ou non. L'une n'est pas plus  astucieuse  ou  élégante  que l'autre, elle est simplement adaptée ou non à ce qu'on veut faire.

Complétion

Ne reste plus que le // Traitement final. Remarquez qu'on n'y parvient que si toutes les conditions sont remplies :

  1. il y a au moins un article ou résumé – sans quoi un return nous éjecte,
  2. tous les autres articles ou résumés sont de la même catégorie ou absence de catégorie que le premier – sans quoi le return de la boucle nous éjecte.

Ce traitement final consiste à ajouter une classe au body de la page. Chance, non seulement ce n'est pas très compliqué mais, ça aussi, on l'a déjà fait dans  Démontage : 'Styler' les pages de blog selon leur URL . La vie est bien faite et voilà la solution :

 var rBody=document.getElementsByTagName('body')[0]; rBody.className+=(rBody.className ? ' ' : '')+categ; 

Conclusion(s)

Conclusion 1 : la rime en "on" est une des plus fournies de la langue française.

Conclusion 2 : voilà le programme terminé, une fois les diverses var regroupées :

 function bodyCateg() { function getCateg(a) { var i,r,rr,c; c='categorie-aucune'; rr=a.getElementsByTagName('a'); for (i=0;r=rr[i];i++) { if (!r.className || !/\blinkTopic\b/.test(r.className)) continue; c=r.href.split('\/').pop().split('.')[0]; break; } return c } var rArt=document.getElementById('article1'),testReg=/\barticle\b/,categ ,rBody=document.getElementsByTagName('body')[0]; if (!rArt) rArt=document.getElementById('articleSeul'); if (!rArt) {rArt=document.getElementById('extraitArticle1'); testReg=/\bextraitArticle\b/;} if (!rArt) return; categ=getCateg(rArt); while(rArt=rArt.nextSibling){ if (!rArt.className || !testReg.test(rArt.className)) continue; if(getCateg(rArt)!=categ)return; } rBody.className+=(rBody.className ? ' ' : '')+categ; } bodyCateg(); 

Mine de rien, si vous avez bien suivi tous mes  démontages , vous commencez à avoir une jolie petite série de techniques JS…


Comme à chaque fois, je vous signale mes bonnes adresses : Apprendre JavaScript.

commentaires

Archives