30 décembre 2013

Surligner les titres du menu de votre blog blogger

Je viens de passer 3h bien bêtes pour que le menu de mon blog (qui est en fait le widget "liste des pages" /pageList) veuille bien rester en surbrillance (highlighting) lorsque l'on est dans la rubrique choisie. C'est tellement plus compréhensible quand on sait dans quelle rubrique on est.

Le problème est que sur Blogger, les rubriques sont ou bien des pages statiques (et là la surbrillance fonctionne d'origine) ou bien des liens. Dans mon cas certaines de mes rubriques sont en fait des filtres des articles de mon blog par thème : ce sont en fait des recherches par mot clé. Ex : http://stephane-rouilly.blogspot.fr/search/label/machines.

Quand on se plonge un peu dans le modèle d'un blog blogger on trouve tout un jeux d'instructions et de variables qui sont préprocessés coté serveur. Ex :



<b:widget id='PageList1' locked='true' title='Pages' type='PageList'>
<b:includable id='main'>
  <b:if cond='data:title'><h2><data:title/></h2></b:if>
  <div class='widget-content'>
    <ul>
      <b:loop values='data:links' var='link'>
        <b:if cond='data:link.isCurrentPage'>
          <li class='selected'><a expr:href='data:link.href'><data:link.title/></a></li>
        <b:else/>
          <li><a expr:href='data:link.href'><data:link.title/></a></li>
        </b:if>
      </b:loop>
    </ul>
    <b:include name='quickedit'/>
  </div>
</b:includable>
</b:widget>

Et justement cette boucle (loop) permet normalement de mettre en surbrillance (class='selected') la rubrique (li) du menu (ul) dans laquelle on se trouve (data:link.isCurrentPage). Sauf qu'elle ne fonctionne que si ce sont des pages statiques (pages et non pas articles) et pas des liens.

En cherchant beaucoup, on trouve finalement que data:link.isCurrentPage est en fait équivalent à data:blog.url == data:link.href. Mais si on remplace l'un par l'autre cela ne fait pas de différence et on ne rentre jamais dans le if...

Reste alors notre bonne vieille amie la bidouille pour nous sortir de là : on peut capturer les 2 paramètres et effectuer la comparaison non pas coté serveur (puisque Blogger les trouve toujours différents...) mais coté client, en Javascript :
if("<data:link.href/>" == "<data:blog.url/>")

Il faut alors faire cette comparaison pour chaque rubrique (donc générer ce test pour chaque itération de la boucle) et ajouter la classe CSS "selected" en Javascript (où "?" sera remplacé plus tard) :
document.getElementById(?).className = "selected";

Reste à ajouter cette classe à la bonne rubrique (li) et donc à identifier cette rubrique avec un id html. Pour cela il faut un indice dans la boucle, c'est l'élément "index" que j'ai appelé "i". On aura alors une un li avec un id avec pour nom kiki concaténé avec un indice i (et ça ne s'écrit pas très simplement en langage Blogger en plus !):
<li expr:id='"kiki" + data:i'>

Voila donc le code modifié d'une partie du widget pageList (pour y accéder : Modèle>personnaliser>widget>pageList) résultant :
 <ul>
        <b:loop index="i" values="data:links" var="link">
          <b:if cond="data:blog.url == data:link.href">
<li class="selected"><a expr:href="data:link.href" href=""><data:link .title=""></data:link></a></li>
<b:else>
			<b:if cond="data:link.isCurrentPage">
<li class="selected"><a expr:href="data:link.href" href=""><data:link .title=""></data:link></a></li>
<b:else>
<li expr:id="&quot;kiki&quot; + data:i"><a expr:href="data:link.href" href=""><data:link .title=""><script>if("<data:link.href/>" == "<data:blog.url/>") document.getElementById("kiki"+<data:i/>).className = "selected"; </script></data:link></a></li>
</b:else></b:if>
          </b:else></b:if>
          
        </b:loop>
      </ul>

Pour se faire une petite idée du principe, voici ce que génère Blogger comme page de rendu avec ce code coté serveur :
<ul>
<li id='kiki0'><a href='http://stephane-rouilly.blogspot.fr/search/label/mobiles'>Mobiles<script>if("http://stephane-rouilly.blogspot.fr/search/label/mobiles" == "http://stephane-rouilly.blogspot.fr/search/label/mobiles") document.getElementById("kiki"+0).className = "selected"; </script></a></li>
<li id='kiki1'><a...



Ce n'est pas super propre mais ça marche. Et je n'ai pas trouvé mieux en ligne. Si vous avez une meilleure solution, ça m'intéresse beaucoup évidemment. En attendant, voici déjà une solution à l'huile de coudes ! J'ai eu un peu de mal de passer autant de temps sur une telle broutille...

Aucun commentaire: