ssg  
Where to Discuss?

Local Group

Preface

Goal: Apply Glenn McComb Pagination using Eleventy.

Source Code

This article use tutor-07 theme. We will create it step by step.


1: Source

I respect copyright. The code below copied, and pasted from:

I made a slight modification. But of course the logic remain the same.

I mostly write it down in my blog, because I do not want to forget what I learn. An easier place for me to find the modified version of this good code.


2: Preview: General

It is not easy to explain by words. Let me explain what we want to achive by using these images below. The brown box, is the active page. since we have 17 articles and 3 page for each pagination, then we have 9 pages of pagination. We have from first page (1), to last page (9).

Animation: Combined Version

This is the complete version. We will achieve this later.

11ty Pagination: Combined Animation

Animation: Stripped Version

I’m following Glenn McComb code, combined with my own code, and this is the result.

11ty Pagination: Adjacent Animation

Sample: An Example

Consider get one frame, a sample, because we need an example. This is what we want to achieve in this tutorial.

11ty Pagination: Adjacent Page 9

HTML Preview

The HTML that we want to achieve in this article, is similar as below.

<nav class="pagination is-small is-centered" ...>
    <ul class="pagination-list">
      <li><a class="pagination-link" ...>3</a></li>
      <li><a class="pagination-link" ...>4</a></li>
      <li><a class="pagination-link is-current" >5</a></li>
      <li><a class="pagination-link" ...>6</a></li>
      <li><a class="pagination-link" ...>7</a></li>
    </ul>
</nav>

Or in detail, you can breakdown each as below:

<nav class="pagination is-small is-centered"
     role="navigation" aria-label="pagination">
  <ul class="pagination-list">

      <li>
        <a class="pagination-link hoverable"
           href="/pages/page-3/index.html"
           aria-label="Goto page 3">
          3
        </a>        

           
      <li>
        <a class="pagination-link hoverable"
           href="/pages/page-4/index.html"
           aria-label="Goto page 4">
          4
        </a>
      </li>

      <li>
        <a class="pagination-link is-current brown"
           aria-label="Page 5">
          5
        </a>
      </li>

      <li>
        <a class="pagination-link hoverable"
           href="/pages/page-6/index.html"
           aria-label="Goto page 6">
          6
        </a>
      </li>

      <li>
        <a class="pagination-link hoverable"
           href="/pages/page-7/index.html"
           aria-label="Goto page 7">
          7
        </a>
      </li>

  </ul>
</nav>

We will achieve this with eleventy code.

The Riddle

How do we achieve this ?


3: Custom Pagination Filter

This would be better, if we move complex code from template, to a javascript helper.

Filter: isShowAdjacent

We need to add isShowAdjacent.

  // Pagination Page: Another tailor made script based on Glenn Mc Comb.
  // Checking Cursor Flag for Adjacent Pagination
  eleventyConfig.addNunjucksFilter("isShowAdjacent",
    function(cursor, current, totalPages, adjacentLinks) {
      return pagination.isShowAdjacent(cursor, current, totalPages, adjacentLinks);
    }
  );

Do not forget to load the script first.

  const pagination = require("./views/_11ty/pagination");

And the script is shown below:

 
// Pagination links : Based on Glenn Mc Comb
// https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/
// Adjacent: Number of links either side of the current page

exports.isShowAdjacent = function(cursor, current, totalPages, adjacentLinks) {
  // initialize variables
  let showCursorFlag = false;

  const maxLinks      = (adjacentLinks * 2) + 1;
  const lowerLimit    = 1 + adjacentLinks;
  const upperLimit    = totalPages - adjacentLinks;
  
  if (totalPages > maxLinks) {
    // Complex page numbers.
    
    if (current <= lowerLimit) {
      // Lower limit pages.
      // If the user is on a page which is in the lower limit.
      if (cursor <= maxLinks)
         showCursorFlag = true;
    } else if (current >= upperLimit) {
      // Upper limit pages.
      // If the user is on a page which is in the upper limit.
      if (cursor > (totalPages - maxLinks))
         showCursorFlag = true;
    } else {
      // Middle pages.
      if ( (cursor >= current - adjacentLinks)
      &&   (cursor <= current + adjacentLinks) )
         showCursorFlag = true;
    }
  } else {
    // Simple page numbers.
    showCursorFlag = true;
  }

  return showCursorFlag;
}

11ty Pagination: Pagination Helper: isShowAdjacent

You can pipe this filter later as code below:

  {% set showCursorFlag = cursor | 
           isShowAdjacent(current, totalPages, adjacentLinks) %}

This showCursorFlag should be checked in every loop.

Skeleton

To get more understanding about this filter, consider to examine this skeleton below:

exports.isShowAdjacent = function(...) {
  // initialize variables ...
  
  if (totalPages > maxLinks) {
  // Complex page numbers.    
    if (current <= lowerLimit) {
      // Lower limit pages ...
    } else if (current >= upperLimit) {
      // Upper limit pages ...
    } else {
      // Middle pages ...
    }
  } else {
  // Simple page numbers.
    ...
  }

  return showCursorFlag;
}

4: Math: Basic Algebra

Assumption

Consider our previous example, a blog post contain seventeen posts. This time with two adjacent. It means, two indicators before selected page, and another two indicators after selected page,

# CONST

Total Post   = 17
Per Page     = 2

adjacentLinks = 2

# COMPUTED

totalPages   = 9

Equation

We should manually, do the math.

EQUATION

maxLinks   = (adjacentLinks * 2) + 1 = 5
lowerLimit =  1 + adjacentLinks      = 3
upperLimit =  9 - adjacentLinks      = 7

The real code is shown as below:

  {% set adjacentLinks = 2 %}
  {% set current       = pagination.pageNumber + 1 %}
  {% set maxLinks      = (adjacentLinks * 2) + 1 %}
  {% set lowerLimit    = 1 + adjacentLinks %}
  {% set upperLimit    = totalPages - adjacentLinks %}

Again, that source above are, ported from:

Table

The result is on this table below.

# ALGEBRA

+------------+-------+-------+-------+-------+-------+
| pagination |   2   |   3   |   5   |  10   |  20   |
+------------+-------+-------+-------+-------+-------+
| VARIABLE                                           |
| totalPages |   9   |   6   |   4   |   2   |  N/A  |
| maxLinks   |   5   |   5   |   5   |   5   |  N/A  |
| lowerLimit |   3   |   3   |   3   |   3   |  N/A  |
| upperLimit |   7   |   4   |   2   |   0   |  N/A  |
+------------+-------+-------+-------+-------+-------+

5: Adjacent Code

This utilized showCursorFlag with complex algorithm.

Layout: Nunjucks Blog

Consider use pagination/03-adjacent partial, in blog.njk.

  {% include "pagination/03-adjacent.njk" %}

Checking The Flag

In every loop, this flag should be check first and use later.

    {% for cursor, link in pagination.links | hashIt %}

      {% set showCursorFlag = cursor | 
               isShowAdjacent(current, totalPages, adjacentLinks) %}

      {# Use Flag: Show Pager. #}
      ...

    {% endfor %}

Using The Flag

And showing the number whenever the showCursorFlag comes out. With similar code as previous article.

    {# <!-- Page numbers. --> #}
    {% for cursor, link in pagination.links | hashIt %}

      {% set showCursorFlag = cursor | 
               isShowAdjacent(current, totalPages, adjacentLinks) %}

      {# Use Flag: Show Pager. #}
      {% if showCursorFlag %}
      <li>
        {% if cursor == current  %}

        <a class="pagination-link is-current {{ color }}"
           aria-label="Page {{ cursor }}">
          {{ cursor }}
        </a>

        {% else %}

        <a class="pagination-link hoverable"
           href="{{ link }}"
           aria-label="Goto page {{ cursor }}">
          {{ cursor }}
        </a>

        {% endif %}
      </li>
      {% endif %}

    {% endfor %}

Preview

This is what we have achieved in this tutorial.

11ty Pagination: Adjacent Pagination

The Same Riddle

How does it works ?

Really! It is confusing.

Luckily, there is explanation for this, for the curious one.

Math in Details

I provide separate article with thorough explanation of the logic, used by this Glenn McComb Pagination.


What is Next ?

Do not stop reading. Consider continue to [ Eleventy - Pagination - Logic ]. We are going to reverse engineering, the Glenn McComb Pagination using Math and Table.

Thank you for reading.