Pagination « à la Facebook »

Ceci est une « contribution pédagogique », qui montre par l’exemple comment développer une nouvelle fonctionnalité pour SPIP.

SPIP propose un système de pagination qui marche très bien, on peut également faire une pagination « à la Facebook » qui en cliquant un lien permet d’ajouter au dessous des éléments affichés des publications plus anciennes sans recharger toute la page.

C’est l’occasion d’utiliser le critère {ajax} qui permet exactement ceci lors de l’appel d’une inclusion.

La doc de SPIP est comme d’habitude très claire et très précise.

Lien
-  ajax pour les inclure sur spip.net

Prenons l’exemple d’une page d’accueil où sont affichés les 5 derniers billets. Nous allons ajouter un lien « Billets plus anciens » au dessous du 5e billet, qui déclenchera l’affichage de 5 billets supplémentaires.

Sur le squelette sommaire.html, la boucle qui affiche les 5 derniers articles se présente ainsi :

<BOUCLE_recents(ARTICLES){!par date}{0,5}>
<h1><a href="#URL_ARTICLE">[(#TITRE|supprimer_numero)]</a></h1>
... 
</BOUCLE_recents>

Tout d’abord déplaçons cette boucle sur un squelette inclus inc-recentposts.html

Sur sommaire.html, le squelette est inclus avec

<INCLURE{fond=inc-recentposts}{env}{nb=#ENV{nb,5}}{ajax}>

La variable nb sert à donner le nombre d’articles à afficher [1], par défaut égal à 5, le critère {ajax} indique que seul le fichier inclus devra être rafraîchi lorsqu’on clique un lien portant la classe ajax.

Dans le fichier inclus, le critère d’itération de la boucle principale doit donc être modifié pour afficher les nb premiers articles et non les 5 premiers.

<BOUCLE_recents(ARTICLES){!par date}{0,#ENV{nb}}>
<h1><a href="#URL_ARTICLE">[(#TITRE|supprimer_numero)]</a></h1>
... 
</BOUCLE_recents>

Au bas de la boucle, ajoutons un lien ajaxé qui déclenche le rafraîchissement du squelette inclus en incrémentant nb de 5.

<p><a class="ajax" href="[(#SELF|parametre_url{nb,[(#ENV{nb}|plus{5})]})]">Billets plus anciens</a><p>

A ce stade ça fonctionne, mais au moment du rafraichissement le focus revient sur le haut du fichier inclus, la page remonte au premier billet. Pour plus de lisibilité, il vaut mieux que la page reste où elle est.

Utilisons une ancre, nommée #more, placée sur le dernier élément affiché avant ajout, soit le nb-5e post.

Pour ajouter cette ancre, l’affichage du détail des posts devient :

<BOUCLE_recents(ARTICLES){!par date}{0,#ENV{nb}}>
<h1[ (#COMPTEUR_BOUCLE|plus{5}|=={#ENV{nb}}|?{id,""})="more"]><a href="#URL_ARTICLE">[(#TITRE|supprimer_numero)]</a></h1>
... 
</BOUCLE_recents>

L’appel ajaxé des billets supplémentaires devient donc :

<p><a class="ajax" href="[(#SELF|parametre_url{nb,[(#ENV{nb}|plus{5})]})#more]">Billets plus anciens</a><p>

Et voilà !

Exemple sur cette page : http://another.teacher.free.fr/

Notes

[1on peut également passer le nombre d’articles à afficher dans l’URL

Discussion

13 discussions

  • Salut,

    ça fonctionne aussi avec SPIP3, si des genTEs veulent ajouter ça à la compatibilité su coup...

    merci

    Répondre à ce message

  • 1

    Bonjour,

    J’essaye de mettre en place tout ça sur mon site : ça marche, sauf l’ajax justement !
    En gros le lien « Articles plus anciens » fonctionne, l’ancre fonctionne en plaçant la page sur le dernier article affiché mais c’est toute la page qui est rechargée et non en mode ajax.

    J’avoue que je ne comprends pas.
    La class ajax doit-elle est créée en plus dans la feuille de style ? (j’ai essayé en l’ajoutant ou non dans mes styles, c’est pareil).

    Bref, si jamais quelqu’un a une piste… Je suis sans doute passé à côté de quelque chose.
    Merci en tout cas pour le tuto super pédagogique :)

    • Ok je viens de trouver (http://forum.spip.org/fr_210125.html), commentaire #9 : il ne faut pas oublier la balise #INSERT_HEAD à insérer dans le Head, pour que le squelette charge les css et js nécessaires à Ajax.

      Suffit de le savoir… !

    Répondre à ce message

  • sepukarot

    Merci pour cette chouette alternative aux bien pénibles « précédents-suivants » !

    Répondre à ce message

  • 5

    Bon en fait... c’est pas compliqué...

    Il faut rajouter dans la boucle « Articles » :
    #SET{total,#TOTAL_BOUCLE}

    et ensuite sur le lien, un test :
    [(#GET{total}|>={nb}|?{'',' '})<p><a class="ajax" href="[(#SELF|parametre_url{nb,[(#ENV{nb}|plus{5})]})#more_#ID_RUBRIQUE]">Articles plus anciens</a><p>]

    C’était pas plus compliqué que ça et ça évite à mes visiteurs de me demander pouquoi il y a encore le lien quand ils sont arrivés au bout.

    • Salut !
      Peux-tu preciser où dans la boucle article exactement ?
      Merci

    • Ben en fait c’est le bout de code qui appelle la liste des articles...

      Ca remplace ça : <p><a class="ajax" href="[(#SELF|parametre_url{nb,[(#ENV{nb}|plus{5})]})#more]">Billets plus anciens</a><p> qu’on te donne dans l’article ci-dessus.

    • en fait c’est surtout une précision quand tu dis :

      Il faut rajouter dans la boucle « Articles » :

      #SET{total,#TOTAL_BOUCLE}

      dans l’exemple

      <BOUCLE_recents(ARTICLES){!par date}{0,#ENV{nb}}>
      <h1[ (#COMPTEUR_BOUCLE|plus{5}|=={#ENV{nb}}|?{id,""})="more"]><a href="#URL_ARTICLE">[(#TITRE|supprimer_numero)]</a></h1>
      ... 
      </BOUCLE_recents>

      par ex tu le places où ?

    • En effet, ça c’était pas clair, j’ai créé une boucle de comptage qui précède la boucle article décrite dans l’article

      <B_comptage_articles>
              #SET{total_#ID_RUBRIQUE,#TOTAL_BOUCLE}
      <BOUCLE_comptage_articles(ARTICLES){branche}>
      </BOUCLE_comptage_articles>

      Je rajoute la variable #ID_RUBRIQUE dans le nom de la variable parce que j’utilise cette astuce plusieurs fois sur la même page. Si tu ne l’utilises qu’une fois, tu n’as pas besoin de cette bidouille ;)

      N’oublie pas de mettre un espace entre
      <BOUCLE_comptage_articles(ARTICLES){branche}>

      et

      </BOUCLE_comptage_articles>

    • ok merci !

      super super super !!!!!!!!!!

    Répondre à ce message

  • 5

    J’ai troué une solution au problème de n’afficher que des paquets de 5 éléments, soit les 5 premiers (articles 1, 2, 3, 4 ,5), puis les articles 6, 7, 8, 9, 10 et ainsi de suite.

    Ce que j’ai fait, c’est d’ajouter une variable nommée debut qui est à 0 au début et incrémentée de 5 comme la variable nb via un deuxième paramètre passé dans l’appel ajax.

    <BOUCLE_recents(ARTICLES){id_secteur=3}{id_article!=31}{!par date}{#ENV{debut},#ENV{nb}}>
            <p align="left"[(#COMPTEUR_BOUCLE|plus{5}|=={#ENV{nb}}|?{id,""})="more"]>#PUCE<a href="#URL_ARTICLE">[(#TITRE|supprimer_numero|couper{50})]</a></p>
    </BOUCLE_recents>
    
    <p>
            <a class="ajax" href="[(#SELF|parametre_url{debut,[(#ENV{debut}|plus{5})]})|parametre_url{nb,[(#ENV{nb}|plus{5})]})#more]">Billets plus anciens</a>
    <p>
    • Valéry

      Mais du coup on ne voit plus les 5 premiers articles, non ? Finalement ça revient à faire ce que fait la pagination

      #PAGINATION{precedent_suivant}

      (le « précédent » en moins) ?

      Le problème est que l’ajax dans les inclure est fait pour recharger une partie de la page alors que ce que l’on cherche à faire ici c’est d’ajouter du contenu dans la page, ce qui n’est pas la même chose.

      Il y a surement une piste là : http://www.infinite-scroll.com/ (en anglais) voir le chapitre « Custom trigger, non-automatic. Twitter-style » avec un plugin jQuery.

    • Je ne saisi pas ton interrogation. Va voir ici ce que ça donne : http://fureurdunoir.free.fr/spip.php?rubrique41 et dis moi moi ce qui ne te conviens pas.

    • @guihard : comment as-tu fait pour virer l’ancre de pagination sur ton « précédent/suivant » de ta colonne de gauche ? Tu as utilisé #PAGINATION{precedent_suivant} ou tu as fait un « truc » à ta sauce ? Si c’est le cas, ça t’embête de partagé le code ? :D D’avance merci.

    • Ajout : si tu regardes sur ma page : http://www.sden.org/ mon « précédent/suivant » est beaucoup moins classe que le tien :)

    • Je n’utilise pas du tout les #PAGINATIONprecedent_suivant comme il est indiqué dans les messages précédents.

      Voici le code utilisé :

      <h4>Publications précédentes</h4>
      <div id="ajaxe">
      	<BOUCLE_recents(ARTICLES){id_article!=31}{!par date}{#ENV{debut},#ENV{nb}}{0,20}> <!-- {id_secteur=2} -->
      		#SET{total,#GRAND_TOTAL}
      		[(#COMPTEUR_BOUCLE|plus{5}|=={#ENV{nb}}|?{id,""})="more"]#PUCE<a href="#URL_ARTICLE" [title="Lire l'article : (#TITRE|textebrut|entites_html)"]>[(#TITRE|supprimer_numero|couper{50})]</a><br />
      		#SET{boucle,#COMPTEUR_BOUCLE}
      	</BOUCLE_recents>
      <hr />
      	<!-- Test pour ne pas afficher le lien si 5 premiers articles affiches -->
      		<div class="ajaxe-prec">
      		[(#GET{boucle}|=={5}|?{'',' '})
      		<a class="ajax" href="[(#SELF|parametre_url{debut,[(#ENV{debut}|moins{5})]})|parametre_url{nb,[(#ENV{nb}|moins{5})]})#more]" title="Les 5 articles précédents">Précédentes</a>
      		]
      		</div>
       
      		<!-- Test pour ne pas afficher le lien si dernier article affiche -->
      			[(#GET{total}|=={#GET{boucle}}|?{'',' '})
      			<div class="ajaxe-next">
      			<a class="ajax" href="[(#SELF|parametre_url{debut,[(#ENV{debut}|plus{5})]})|parametre_url{nb,[(#ENV{nb}|plus{5})]})#more]" title="Les 5 articles suivants">Suivantes</a>
      			</div>
      			]
       
      et on appelle tout cela via ceci :
      	<INCLURE{fond=inc/inc-recentposts}{env}{debut=#ENV{debut,0}}{nb=#ENV{nb,5}}{ajax}>

    Répondre à ce message

  • Petit correctif.

    Avant la boucle articles (si vous paginez des articles), il faut mettre la boucle suivante

    <B_comptage_articles>
            #SET{total,#TOTAL_BOUCLE}
    <BOUCLE_comptage_articles(ARTICLES){id_rubrique}>
    </BOUCLE_comptage_articles>

    et enfin de boucle, pour le lien :

    [(#GET{total}|<={#ENV{nb}}|?{'',' '})<p><a class="ajax" href="[(#SELF|parametre_url{nb,[(#ENV{nb}|plus{5})]})#more_#ID_RUBRIQUE]">Articles plus anciens</a><p>]

    Répondre à ce message

  • Histoire de pousser le truc jusqu’au bout... vous auriez une idée pour faire disparaître le lien « plus d’articles » quand on est arrivé au bout le liste ?

    Répondre à ce message

  • OOps,

    j’ai oublié le bout de code de l’inclure

    <INCLURE{fond=inc/inc-recentposts}{env}{nb=#ENV{debut,0}}{nb=#ENV{nb,5}}{ajax}>

    Répondre à ce message

  • 2
    Nicolas Hoizey

    Joli !

    Comme souligné par Fil, ce serait plus judicieux de ne pas recharger ce qui est déjà là, si c’est possible. Charger les 5 suivants à la place du lien lui-même, par exemple.

    Cela éviterait du même coup le problème de déplacement dans la page.

    En tout cas, belle idée, bravo !

    • réponse @ nicolas et @ fil

      j’y ai pensé, mais je n’ai pas trouvé comment faire. en effet on peut ne mettre que le lien dans l’inclure, et ajouter juste 5 billets de plus au-dessus avec ajax, mais si on clique une deuxième fois sur le lien, il va recharger tout à partir du 6e de toutes manières, non ?

      je vais essayer de trouver autre chose, vos idées sont les bienvenues !

      et quoi qu’il en soit sinkiou pour les commentaires :) ça fait plaisir

    • Nicolas Hoizey

      Et si le lien fait partie de ce que tu recharges ?

    Répondre à ce message

  • 4

    hello et merci :)

    l’ancre apparaît bien, mais elle est générée par ajax, tu ne peux pas la voir en affichant la source, seulement en affichant la source générée (avec web developer par exemple)

    • Non, je t’assure que sur http://another.teacher.free.fr/ il n’y a aucun id='more' dans le retour ajax, ce qui provoque d’ailleurs une erreur javascript lorsque SPIP essaye de se positionner dessus.

    • hello

      merci, en effet l’ancre ne s’affichait pas, il y avait une boulette dans mon code (le détail de chaque post est dans un fichier inclus et j’avais un peu négligé de faire passer le compteur aux l’inclusions, ça risquait pas de marcher). maintenant elle s’affiche mais du coup ça scrolle un peu quand on affiche de nouveaux billets. bizarre, quand il n’y a pas d’ancre du tout dans le lien ça revient tout en haut du fichier inclus, et quand il y a un lien vers une ancre qui n’existe pas ça marche bien - excepté l’erreur javascript. comment faire pour que ça ne bouge pas sans erreur ?

    • je crois que ton ancre s’affiche un billet trop haut. Du coup ça te fait peut-être revenir en arrière.
      En vrai le cas sans scroll n’a pas été prévu, bonne remarque.

    • yep, j’ai essayé plus haut, plus bas, ça scrolle toujours dans un sens ou dans l’autre à moins que le h1 soit pile en haut du viewport quand on clique... j’imagine qu’on doit pouvoir relever la position de la page par rapport au haut et repositionner pareil, mais je ne sais pas faire. je crois que je vais enlever l’ancre pour que ça ne bouge plus (paradoxal), quitte à avoir une erreur :)

    Répondre à ce message

Ajouter un commentaire

Qui êtes-vous ?
  • [Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom

Dernière modification de cette page le 15 octobre 2009