GithubHelp home page GithubHelp logo

pico-pagination's Introduction

Pico Pagination Plugin

Provides basic pagination for Pico.

Changelog

1.7 - Changed date sorting to allow the use of any PHP valid date format 1.6 - Fixed a sorting issue when using subfolders. 1.5 - Added next_page_url and prev_page_url variables for Twig. Preparing to stop returning markup from the plugin in a future release—plugin should only return data and leave theming up to site builders. 1.4 - Changed to use of >/< in default next_text and prev_text variables and added more variables Google search-like numbered pagination.
1.3 - Added ablity for pagination to happen in subfolders on a site.
1.2 - Added back the ability to set the path segment to indicate pages ("page indicator" ) now that changes have been made in Pico v0.8 that allow it to work properly.
1.1 - Added ability to reverse the order in which the previous/next links are rendered.
1.0 - Initial release.

How it works

It's pretty simple. The plugin creates a second array of pages identical to the default pages called paged_pages. This second array is filtered by date (so only blog-type posts will be returned) and limited by the number of pages you want per page. Listing your paged results, therefore, is just a matter of iterating through the paged_pages variable instead of the pages one.

Additional variables that can be used in themes are created to accompany the paged results. See below.

Installation

  1. Copy the pagination.php file to the plugins folder of your Pico site.
  2. Update your theme to use the paginated pages generated by the plugin.
  3. Set configuration variables if defaults are not suitable.
  4. That's it!

Configuration settings

You can configure a number of settings by adding values to your site's config.yml file. The following are the available options and what they do.

Option Default Options Notes
pagination_limit int: 5 n/a Sets the how many items display on each page.
pagination_page_indicator str: "page" n/a Sets the word used in the URL that will indicate paged results. (i.e. http://yoursite.com/page/2)
pagination_filter_date bool: true true, false Sets whether the posts returned should be filtered to only those with dates or not.
pagination_next_text* str: "next >" n/a Sets the text for the next link.
pagination_prev_text* str: "< previous" n/a Sets the text for the previous links.
pagination_flip_links* bool: false true, false Reverses the order the links are ouput. This is to aid in providing links in the format of older/newer as opposed to previous/next.
pagination_output_format* str: "links" "links", "list" Sets whether {{ pagination_links }} will output two <a> tags or an unordered list.
pagination_sub_page bool: false true, false Sets whether there is a sub page for the pagination (i.e. not the root of the site). When this is set to true, you must create a subfolder in content with the same name as the "pagination_page_indicator" variable. See below for further information.

For reference, these values are set in config.yml using the following format (I'd place them toward the bottom in the "Custom" section):

*In a future release of Pico-Pagination, the plugin will stop returning markup and only return values. At that point, these config options will go away.

pagination_limit: 10
pagination_output_format: "list"

Setting up the theme

The plugin adds a couple new variables to the theme. They are:

  • {{ paged_pages }} - The new, paged array of pages for the theme
  • {{ next_page_url }} - The URL for the next page, empty string if none
  • {{ prev_page_url }} - The URL for the previous page, empty string if none
  • {{ page_number }} - The current page number
  • {{ total_pages }} - The total number of pages
  • {{ page_of_page }} - The page number out of the total number of pages (i.e. "Page 1 of 3", as a string)
  • {{ page_indicator }} - The page_indicator value from config, usually "page"
  • {{ pagination_links }}** - The generated next and previous links (output as either two links or an unordered list)
  • {{ next_page_link }}** - The next link only. Returns empty string if there isn't one
  • {{ prev_page_link }}** - The previous link only. Returns empty string if there isn't one

**This variable returns HTML so it must be used in Twig with the |raw filter. These will be deprecated at some point in the future as the plugin should only return data instead of markup—that's your job in your theme 😉.

To get a basic implementation of the pagination plugin going, use something like the following:

{% if is_front_page %}
{# Front page, list all blog posts #}
    
  <div class="posts-list">
  {% for page in paged_pages %}
    <div class="post">
      <h3><a href="{{ page.url }}">{{ page.title }}</a></h3>
      <p class="meta">{{ page.date_formatted }}</p>
      <p class="excerpt">{{ page.excerpt }}</p>
    </div>
  {% endfor %}
  </div>

  {# Pagination here 👇 #}
  {% if prev_page_url or next_page_url %}
    <ul class="pagination-links">
      {% if prev_page_url %}
        <li class="pagination-list-item">
          <a href="{{ prev_page_url }}" class="pagination-link pagination-link--prev">&larr; Previous Page</a>
        </li>
      {% endif %}
      {% if next_page_url %}
        <li class="pagination-list-item">
          <a href="{{ next_page_url }}" class="pagination-link pagination-link--next">Next Page &rarr;</a>
        </li>
      {% endif %}
    </ul>
  {% endif %}
  <p class="pagination-summary">{{ page_of_page }}</p>
  {# Pagination done #}
  
{% else %}
{# Other pages show individual post #}

  <div class="post">
    {% if meta.title %}<h2>{{ meta.title }}</h2>{% endif %}
    <p class="meta">{{ meta.date_formatted }}</p>
    {{ content }}
  </div>

{% endif %}

To note: the key difference here is that the Pico standard posts loop is iterating through paged_pages instead of pages. (This sample is taken from the Pico website and modified for the pagination plugin.)

Your Site Navigation

If you're familiar with Pico, this may be obvious, but for your main site menu, you can filter it so that content with dates (i.e. your blog posts) don't get output along with your other pages. This is pretty easy to do just with a little if statement. Here's an example:

<ul class="nav">
  {% for page in pages %}
  {% if not page.date %}
  <li><a href="{{ page.url }}">{{ page.title }}</a></li>
  {% endif %}
  {% endfor %}
</ul>

Using Older/Newer links instead of Previous/Next

⚠️ While the behavior in this section is still fully supported, in future releases of Pico-Pagination, the plugin will stop returning markup and instead leave that to you in your Twig theme. Please see updated example implementation.

A lot of blogs (or other chonologically listed content) will want pagination links that use chonological verbiage as opposed to the standard previous/next text. In order to do this, you can set the following config options in Pico's config.yml file.

pagination_flip_links: true
pagination_next_text: "< Older Posts"
pagination_prev_text: "Newer Posts >"

Note the first option set. This changes the order in which the links display so that the older link is first and the newer link is second.

Using a sub page for the pagination (e.g. for a blog that is not on the main site index)

Sometimes it is preferable to have your blog listed at /blog rather than on your main page, for example to allow for a landing page to be the first page visitors see.

To do this, set the pagination_sub_page to true, and the pagination_page_indicator variable to the page path, i.e. "blog":

pagination_sub_page: true
pagination_page_indicator: "blog"

Then, configure your page: Set up a folder called "blog" (or whatever you've chosen to use as the slug) in Pico's content folder, and keep all your blog posts in this folder. You will need an index.md in here for the pagination.

Finally set up 2 new templates, one for the index.md that has the above pagination code, the other for the posts (again, using the relevant code from above).

Customize to your needs

The plugin should return all necessary pieces of data to build out your pagination however you see fit. Here is an example that lists all the pages number and adds a CSS class to the current one:

<div class="pagination">
  {% if page_number > 1 %}
  <a href="{{ prev_page_url }}" class="button pagination-prev">Previous Page</a>
  {% endif %}

  <div class="pagination-pages">
    {% for page_num in 1..total_pages %}
    <a href="{{ base_url }}/{{ page_indicator }}/{{ page_num }}"{% if page_num == page_number %} class="active"{% endif %}>{{ page_num }}</a>
    {% endfor %}
  </div>

  {% if page_number < total_pages %}
  <a href="{{ next_link_url }}" class="button pagination-next">Next Page</a>
  {% endif %}
</div>

That's it. If you have questions, go ahead and ask. If you have issues, you can add them to the issue tracker.

🎉 Thank you to everyone who has helped contribute to this plug in!

If you see something that you think is missing, pop open the plugin file and see if you can add it. I'm happy to accept sensible MRs!

pico-pagination's People

Contributors

adonald avatar lomanic avatar oschettler avatar purerstamp avatar ramingesh avatar rewdy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pico-pagination's Issues

paged_pages for pagination_sub_page

If pagination_sub_page is set to true shouldn't paged_pages not only return pages from pagination_page_indicator sub folder?
Otherwise I don't get the sense for this option.

Previous post and Next post links in post individual page

Is it possible, using the plugin as is, to have two links for the previous and next posts in the individual post page?
Something like this below the post's content:
| << Previous post title | Next post title >> |

I've done it like this but the order is all messed up. Seems to be sorted alphabetically instead of sorted by date:

{% if prev_page.title %}
  <span class="prev-post">
    <a href="{{ prev_page.url }}" rel="prev">{{ prev_page.title }}</a>
  </span>
{% endif %}

{% if next_page.title %}
  <span class="next-post">
    <a href="{{ next_page.url }}" rel="next">{{ next_page.title }}</a>
  </span>
{% endif %}

Thanks in advance for your help.

Pagination is not working properly

Hi Andrew,

First I wanted to thank you for this plugin; I followed your instructions to set up the plugin and Pico to use it.

I have one issue though; by the time I reach the post limit for one page and the plugin kicks in, if I press next page I will the same page - e.g. all the posts listing again as for the first page instead of the one post, following the order and the age criteria.

Any ideas?

Thank you,

Razvan

Pagination w/ unexpected order / empty pages

Hi,
I'm tinkering with pico CMS. I installed the blank blog theme and then tried my hand on this plugin.
I inserted the template code into the index.html of that plugin
I am running into the following issue where the pagination doesn't do what I would expect. I have created 7 bogus blog pages in content/blog/. If I now limit pagination to 3, I receive an order 3-2-2 instead of 3-3-1 as I would expect. Limit 2 yields 2-2-1-2 and limit 1 delivers a bizarre empty page 6 when pages 7,8 still have content.

Ok, to give a fair description, I now pasted the template from your Readme into the default template and found sth that should help. The odd number is the Welcome page. It appears that your plugin counts it in while the blog theme then only lists the pages that have a date.

Kind regards,
Matthias

Article order problems when using sub folders

There seems to be a problem sorting articles when using sub folders. The pages are not all sorted by date but they are grouped by sub folder (with one confusing exception).

My setup:

artikel.twig

    <div id="main" role="main">
        <div class="container">
            {{ content }}
            <h1 class="postlist-header">Alle Artikel auf Freude am Film:</h1>
            {% for page in paged_pages|sort_by("time")|reverse if not page.hidden %}
                <div class="post">
                    <h2><a href="{{ page.url }}">{{ page.title }}</a></h2>
                    <p class="date">{{ page.date_formatted }} {% if "filmkritik" in page.url %} | Filmkritik {% endif %} {% if "werkschau" in page.url %} | Werkschau {% endif %} {% if "kurzkritiken" in page.url %} | Kurzkritiken {% endif %}</p> 
                    <p class="excerpt">{{ page.description }}</p>
                </div>
            {% endfor %}
            <div class="pagination">
                {% if page_number > 1 %}<a href="{{ base_url }}/{{ page_indicator }}/{{ page_number - 1 }}" class="button previous">Neuere Einträge</a>{% endif %}
                    <div class="pages">
                        {% for page_num in 1..total_pages %}
                        <a href="{{ base_url }}/{{ page_indicator }}/{{ page_num }}"{% if page_num == page_number %} class="active"{% endif %}>{{ page_num }}</a>
                        {% endfor %}
                    </div>
                {% if page_number < total_pages %} <a href="{{ base_url }}/{{ page_indicator }}/{{ page_number + 1 }}" class="button next">Ältere Einträge</a>{% endif %}
            </div>
        </div>
    </div>

config.yml:

pagination_limit: 10
pagination_next_text: "Weiter >"
pagination_prev_txt: "< Zurück"
pagination_sub_page: true
pagination_page_indicator: artikel

Folder structure:

/artikel (index [using artikel.twig] and 1 other page)
/artikel/filmkritik (9 pages)
/artikel/kurzkritiken (1 page)
/artikel/werkschau (1 page)

Expected result

Sorting of all pages by date, mixing all the folders

filmkritik 9
filmkritik 8
werkschau 1
filmkritik 7
filmkritik 6
filmkritik 5
kurzkritiken 1 
filmkritik 4
filmkritik 3
artikel 1
[new page]
filmkritik 2
filmkritik 1

Actual result

The pages seem to be grouped by folder, except the one page from "kurzkritiken"

filmkritik 9
filmkritik 8
filmkritik 7
filmkritik 6
filmkritik 5
kurzkritiken 1 
filmkritik 4
filmkritik 3
filmkritik 2
filmkritik 1
[new page]
werkschau 1
artikel 1

Define multiple sub pages for pagination?

I've defined:
$config['pagination_sub_page'] = true;
$config['pagination_page_indicator'] = "blog";
for posts in my /blog sub-folder, but I'd like to define another subfolder /music, for example, and be able to iterate through those for pagination. Would I need to create another array ex:paged_pages_2 to accomplish this or is there another method?

Thanks for all your work on this plugin!

can't be combined with other plugins and dynamic content (like search!)

While I had a few issues getting pagination working, I got that done. As far as my setup and testing goes, seems to be working for now.

Now I have a new problem. I've just implemented the Search plugin. Both seem to be working, as long as they are separated. The issue is, I don't see how to combine the two properly. (Maybe it's just me. It's past 4 in the morning).

The issue is, that Pagination filters ahead of time from all pages. Always! I can't just throw the search result in a folder and tell the pagination plugin to go from there. The search results are being created dynamically.

The Search plugin before worked directly with the pages array. Since this caused issues with other plugins as well, they actually noticed the issue, rewrote it in 2020 and now provide a FILTER. So, the search plugin can now be applied to any array/pages that are being thrown at it. That is a great way of handling data.

The issue is, there is no sense in applying the search AFTER pagination. It should be search filter first and pagination of the resulting pages afterwards. Applying pagination as a filter as well would solve the problem.

renaming file and class to able to load

Hi,
I tried to use it with Pico 2.1 and foound some installation issues:

[Sat Apr 01 09:45:39.898139 2023] [php7:error] [pid 837] [client 127.0.0.1:38800] PHP Fatal error: Uncaught RuntimeException: Unable to load plugin 'Pico-Pagination' from 'Pico-Pagination/Pico-Pagination.php': File not found in /var/www/html...

My solution was:

mv 10-Pagination.php Pico-Pagination.php

Next problem:

[Sat Apr 01 10:00:39.492419 2023] [php7:error] [pid 835] [client 127.0.0.1:41730] PHP Fatal error: Uncaught RuntimeException: Unable to load plugin 'Pico-Pagination' from 'Pico-Pagination/Pico-Pagination.php': Plugin class not found in /var/www/html/...

My solution was:

mv Pico-Pagination PicoPagination
mv Pico-Pagination.php PicoPagination.php
sed -e 's/class Pagination extends/class PicoPagination extends/' PicoPagination.php

Question: What if your 'blog' page isn't the index/front page?

I have my Pico theme set to show a static front page (on the index) and then have my list of blog entries generating on another page (/blog). This is all done through the index.html file using the twig language and if statements.

The issue I am running into, using this pagination plugin, is that when I click the 'next' link it ends up sending me to /page/2 (which is correct) but doesn't display the list containing the next set of blog entries. What get's displayed is the front page/index page.

Any thoughts?

I know the plugin works great as I've tried it on the default pico theme but I am wondering if you might have any thoughts or suggestions.

Link is not working: I always get back to index page

Hi!

I try to use you awesome plugin. Since it seems to work with so many people, the failure lies probably on my side.

My problem: I get back to the index page, when I click on a "older/newer" link.

I include the pagination on a subpage blog, therefore I changed the pagination_page_indicator to blog in my config.ymlfile. The link is correct: http://myurl.com/blog/2.

But when I click on the link I get directed to http://myurl.com. How can I avoid this?

Many pages

How not to display all pages when there are many?
Now: 1 2 3 4 5 6 7 8 9
Necessary: 1 2 3 ... 8 9

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.