Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Twig pagination (proposal) and Page Tree (question) #443

Closed
bricebou opened this issue Jun 29, 2018 · 10 comments
Closed

Twig pagination (proposal) and Page Tree (question) #443

bricebou opened this issue Jun 29, 2018 · 10 comments

Comments

@bricebou
Copy link

bricebou commented Jun 29, 2018

HI,

I've worked on a pagination system using Twig and Twig only (after reading #404 and #419), that could be used in any pages of my website. I've managed to reproduce the one I generated with my version on Pico-Pagination for my online website, momh.fr.

So here is the code:

{% set excludedpages = 0 %}
{% set pagesbis = [] %}
{% for page in pages %}
  {% if page.meta["template"] == "category" or page.meta["template"] == "supcategory" or page.title == "Blog" %}
    {% set excludedpages = excludedpages + 1 %}
  {% else %}
    {% set pagesbis = pagesbis|merge([page]) %}
  {% endif %}
{% endfor %} 

{% set slicelength = 5 %}
{% set basepage = 1 %}
{% set pagiurl = base_url ~ "/?page=" %}
{% set maxpage = (pages|length - excludedpages) / slicelength %}

{% set maxpage = maxpage|round(0, 'ceil') %}

{% if url_param('page', 'int') is not null %}
  {% set basepage = url_param('page', 'int') %}
  {% set slicestart = slicelength * (basepage - 1) %}
{% else %}
  {% set slicestart = 0 %}
  {% set basepage = 1 %}
{% endif %}

{% set nextpage = basepage + 1 %}
{% set prevpage = basepage - 1 %}     

{% for page in pagesbis|slice(slicestart, slicelength, preserve_keys) %}
  <article class="post">
    <h1><a href="{{ page.url }}">{{ page.title }}</a></h1>
      <p class="meta clearfix">
        <span class="date_lsp">
          le {{ page.date|date("d/m/Y", "Europe/Paris") }} {% if page.meta["Category"] %}dans {{ page.meta["Category"] }} {% endif %}
        </span>
        {% if page.meta["Tags"][0] != "" %}
          <span class="tags_lsp">
            <i class="fa fa-tags"></i>{% for tag in page.meta["Tags"] %}<a class="hvr_over" href="{{ base_url }}/tag/{{ tag }}">#{{ tag }}</a>{% endfor %}
          </span>
        {% endif %} 
      </p>
      {# <p class="excerpt">{{ page.excerpt }}</p> #}
  </article>
{% endfor %}

<div class="pagination clearfix">
  <ul>
    {% if prevpage is not null %}
      <li class="pi" {% if prevpage < 1 %}style="visibility: hidden;"{% endif %}><a href="{% if prevpage == 1 %}{{ base_url }}{% else %}{{ pagiurl ~ prevpage }}{% endif %}" title="Plus récents" id="prev_page_link"><i class="fa fa-clock-o"></i><i class="fa fa-angle-right"></i></a></li>
    {% endif %}

    {% for item in range(1, maxpage|number_format) %}
      <li class="pi {%if item == basepage %} pi_a{%endif %}"><a href="{% if item == 1 %}{{ base_url }}{% else %}{{ pagiurl ~ item }}{% endif %}" class="page_item {%if item == basepage %} page_active{%endif %}">{%if item == basepage %}<i class="fa fa-clock-o"></i><span>{{ item }}</span>{% else %}{{ item }}{%endif %}</a></li>
    {% endfor %}

    {% if nextpage is not null %}
      <li class="pi" {% if nextpage > maxpage %}style="visibility: hidden;"{% endif %}><a href="{{ pagiurl ~ nextpage }}" title="Plus anciens" id="next_page_link"><i class="fa fa-angle-left"></i><i class="fa fa-clock-o"></i></a></li>
    {% endif %}
  </ul>
</div> {# END .pagination #}

I'm quite satisfied (because it's working ^^ and because I can apply this code, with minor changes, to my tag pages, generated with the PicoTags plugin) but unsatisfied due to the double array parsing (the first one to remove some pages - categories - and the second to display the results).

Maybe you can think of a better way of achieving this ?

I've thought of the new Page Tree system. First, I can't figure out how to use it, even with minimal examples I found in #412 or #414. Even, after reading https://phrozenbyte.github.io/Pico/in-depth/features/page-tree/

Here is a screenshot of my website content folder.
momh_content_structure

In the index.twig, called only for the content root index.md, I've tried several snippets without success... :-/

I think I understand that Page Tree could generate from scratch an array without the simple index.md nodes ? So, the length of this array wouldn't have to be modified...
Is that correct ? If so, could you give me first steps ?

Thanks again and in advance :)

@bricebou
Copy link
Author

bricebou commented Jul 1, 2018

I've tried to work on a better way to integrate this pagination on different template files and I produced this how-to on my website: http://momh.fr/tutos/Pico/pico_twig_pagination

@PhrozenByte You can copy this, if you think it's good and useful, into the picocms website.
If you find a better way, let me know !

Here it is: inside your index.twig (for example), paste this code and set the variables:

{#  number of pages to display per page #}
{% set pagi_slice_length = 5 %}
{#  the array of pages to use #}
{% set pagi_pages_array = pages %}
{#  the base URL of the page the pagination applied
    it can be a more complex string, concatenated like this:
    base_url ~ "/tag/" ~ current_tag
#}
{% set pagi_base_url = base_url %}
{#  the name to use as the URL parameter (?page=xxx) #}
{% set pagi_http_param = 'page' %}

{% if url_param(pagi_http_param, 'int') is not null %}
{% set pagi_basepage = url_param(pagi_http_param, 'int') %}
{% set pagi_slice_start = pagi_slice_length * (pagi_basepage - 1) %}
{% else %}
{% set pagi_slice_start = 0 %}
{% set pagi_basepage = 1 %}
{% endif %}

{% set pagi_maxpage = (pagi_pages_array|length / pagi_slice_length)|round(0, 'ceil') %}

{% for page in pagi_pages_array|slice(pagi_slice_start, pagi_slice_length, preserve_keys) %}      
    <article>
        <h2 class="h1"><a href="{{ page.url }}">{{ page.title }}</a></h2>
    </article>
{% endfor %}

{% include 'includes/pagination.twig' with [pagi_basepage, pagi_maxpage, pagi_base_url, pagi_http_param] %}

You have to create a includes/pagination.twig file in which you have to paste this code:

{% set pagi_next_page = pagi_basepage + 1 %}
{% set pagi_prev_page = pagi_basepage - 1 %}
{% if pagi_maxpage > 1 %}
  <ul>
    {% if pagi_prev_page is not null %}
      <li class="pi" {% if pagi_prev_page < 1 %}style="visibility: hidden;"{% endif %}><a href="{% if pagi_prev_page == 1 %}{{ pagi_base_url }}{% else %}{{ pagi_base_url ~ '/?' ~ pagi_http_param ~ '=' ~  pagi_prev_page }}{% endif %}" title="Newest posts" id="prev_page_link">Newest posts</a></li>
    {% endif %}

    {% for item in range(1, pagi_maxpage|number_format) %}
      <li class="pi {%if item == pagi_basepage %} pi_a{%endif %}"><a href="{% if item == 1 %}{{ pagi_base_url }}{% else %}{{ pagi_base_url ~ '/?' ~ pagi_http_param ~ '=' ~ item }}{% endif %}" class="page_item {%if item == pagi_basepage %} page_active{%endif %}">{{ item }}</a></li>
    {% endfor %}
    
    {% if pagi_next_page is not null %}
      <li class="pi" {% if pagi_next_page > pagi_maxpage %}style="visibility: hidden;"{% endif %}><a href="{{ pagi_base_url ~ '/?' ~ pagi_http_param ~ '=' ~ pagi_next_page }}" title="Older posts" id="next_page_link">Older posts</a></li>
    {% endif %}
  </ul>
{% endif %}

It's awful, but it works ! ^^

A live example: momh.fr/

@stale
Copy link

stale bot commented Jul 10, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in two days if no further activity occurs. Thank you for your contributions! 👍

@stale stale bot added the info: Stale label Jul 10, 2018
@PhrozenByte
Copy link
Collaborator

Comment for un-stale-ing this issue

Didn't forget about answering this, just haven't had time for it yet...

@stale stale bot removed the info: Stale label Jul 10, 2018
@bricebou
Copy link
Author

No worry @PhrozenByte :-)
I've just updated my second comment (I forgot the pagi_pages_array variable in my for loop).

@stale
Copy link

stale bot commented Jul 17, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in two days if no further activity occurs. Thank you for your contributions! 👍

@stale stale bot added the info: Stale label Jul 17, 2018
@bricebou
Copy link
Author

Comment for un-stale-ing this issue

I'm going to work on adding options to display only X items when the maxpage is too important.

@stale stale bot removed the info: Stale label Jul 19, 2018
@stale
Copy link

stale bot commented Jul 26, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in two days if no further activity occurs. Thank you for your contributions! 👍

@stale stale bot added the info: Stale label Jul 26, 2018
@bricebou
Copy link
Author

Just in time !

So I've worked on a a way to reduce the number of displayed pages !

Here is my new includes/pagination.twig:

{% set pagi_next_page = pagi_basepage + 1 %}
{% set pagi_prev_page = pagi_basepage - 1 %}
{% if pagi_max_near_by is null %}
  {% set pagi_max_near_by = 2 %}
{% endif %}

{% if pagi_maxpage > 1 %}
  <ul>
    {% if pagi_prev_page is not null %}
      <li class="pi" {% if pagi_prev_page < 1 %}style="visibility: hidden;"{% endif %}><a href="{% if pagi_prev_page == 1 %}{{ pagi_base_url }}{% else %}{{ pagi_base_url ~ '/?' ~ pagi_http_param ~ '=' ~  pagi_prev_page }}{% endif %}" title="Newest posts" id="prev_page_link">Newest posts</a></li>
    {% endif %}
    
    {% if pagi_basepage - pagi_max_near_by > 1 %}
      <li class="pi">&hellip;</li>
    {% endif %}
    
    {% for item in range(1, pagi_maxpage|number_format) %}
      <li {% if pagi_basepage - pagi_max_near_by > item or pagi_basepage + pagi_max_near_by < item  %}style="display:none;"{% endif %} class="pi {%if item == pagi_basepage %} pi_a{%endif %}"><a href="{% if item == 1 %}{{ pagi_base_url }}{% else %}{{ pagi_base_url ~ '/?' ~ pagi_http_param ~ '=' ~ item }}{% endif %}" class="page_item {%if item == pagi_basepage %} page_active{%endif %}">{{ item }}</a></li>
    {% endfor %}
    
    {% if pagi_basepage + pagi_max_near_by < pagi_maxpage %}
      <li class="pi">&hellip;</li>
    {% endif %}

    {% if pagi_next_page is not null %}
      <li class="pi" {% if pagi_next_page > pagi_maxpage %}style="visibility: hidden;"{% endif %}><a href="{{ pagi_base_url ~ '/?' ~ pagi_http_param ~ '=' ~ pagi_next_page }}" title="Older posts" id="next_page_link">Older posts</a></li>
    {% endif %}
  </ul>
{% endif %}

I've made a new blog post about that here: http://momh.fr/tutos/Pico/pico_twig_pagination_bis

And you can see it live here: http://momh.fr/?page=5

@stale stale bot removed the info: Stale label Jul 28, 2018
@PhrozenByte
Copy link
Collaborator

We already promote plugins and themes on our website, unfortunately there isn't really a counterpart for Twig snippets yet. Anyway, creating one might be a good idea. There's just the currently not really used Cookbook on our website. As always, help is highly appreciated!

The snippets look really great and are exactly the way it should be used. Just some minor notes:

  • includes/pagination.twig: {% if pagi_prev_page is not null %} is obsolete, it never evaluates to false. I guess you rather want to use {% if pagi_prev_page < 1 %} (and remove the style="visibility: hidden;").
  • includes/pagination.twig: Same for {% if pagi_next_page is not null %} (shoulud be {% if pagi_next_page > pagi_maxpage %})
  • includes/pagination.twig: What is pagi_maxpage|number_format for? The number_format Twig filter doesn't make much sense here.
  • includes/pagination.twig: Not really about the Twig snippet, but rather the CSS of your theme: It should be sufficient to mark the active page in the pages list just once: .pi_a for the li element and .page_active for the a element is redundant, .pi_a for li should be sufficient.

@stale
Copy link

stale bot commented Aug 11, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in two days if no further activity occurs. Thank you for your contributions! 👍

@stale stale bot added the info: Stale label Aug 11, 2018
@stale stale bot closed this as completed Aug 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants