ssg  
Article Series

Jekyll in General

Jekyll Plain

Where to Discuss?

Local Group

Preface

Goal: Apply Glenn McComb Pagination using Jekyll.

Source Code

This article use tutor-05 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 box without underline, 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).

This is what we want to achieve in this tutorial.

Jekyll Pagination: Basic Adjacent Pagination

Layout Liquid: Blog

Consider use pagination-v1/03-adjacent.html partial, in _layouts/blog.html.

{% include pagination-v1/03-adjacent.html %}

Animation: Combined Version

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

Jekyll Pagination: Combined Animation

Animation: Stripped Version

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

Jekyll 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.

Jekyll Pagination: Adjacent Page 9

HTML Preview

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

<nav role="navigation">
  <!-- Page numbers. -->
    [ <a href="/pages/blog-3">3</a> ]
    [ <a href="/pages/blog-4">4</a> ]
    [ 5 ]
    [ <a href="/pages/blog-6">6</a> ]
    [ <a href="/pages/blog-7">7</a> ]
</nav>

The Riddle

How do we achieve this ?


3: Custom Pagination in Liquid

This would be a long liquid code.

  1. First of all, we need to setup flag named page_current_flag, to decide which pagination should be shown, and which should be hidden.

  2. The second step, is to define which variable required to make decision.

  3. The third step, is to perform conditional decision.

  4. Show pagination based on the flag above.

This utilized page_current_flag with complex algorithm.

Prepare Variable

Adjacent initialization:

    {% capture spaceless %}
      {% assign page_current  = paginator.page %}

      {% assign link_offset   = 2 %}  
      {% assign link_max      = link_offset  | times: 2 | plus: 1 %}

      {% assign limit_lower   = link_offset  | plus: 1 %}
      {% assign limit_upper   = total_pages  | minus: link_offset %}
  
      {% assign min_lower     = link_max %}  
      {% assign max_upper     = total_pages  | minus: link_max %}
    
      {% assign lower_offset  = page_current | minus: link_offset %}  
      {% assign upper_offset  = page_current | plus: link_offset %}  
    {% endcapture %}

And, common initialization, before that:

{% capture spaceless %}
  {% assign total_pages = paginator.total_pages %}
{% endcapture %}

<nav role="navigation">
  {% if total_pages > 1 %}
  
    {% capture spaceless %}
      <!-- Get paginate_root from page in frontmatter -->
      {% if page.paginate_root == nil %}
        {% assign paginate_root = "/" %}
      {% else %}    
        {% assign paginate_root = page.paginate_root %}
      {% endif %}
      {% assign p_first = paginate_root | prepend: site.baseurl %}

      ... 
    {% endcapture %}

    ...
  {% endif %}
</nav>

Jekyll Pagination: Liquid: Adjacent Variables

Calculating Flag Value

The long complex calculation

    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}

      {% capture spaceless %}
        <!-- Flag Calculation -->
        {% assign page_current_flag = false %}

        {% if total_pages > link_max %}
        <!-- Complex page numbers. -->

          <!-- Lower limit pages. -->
          <!-- If the user is on a page which is in the lower limit.  -->
          {% if page_current <= limit_lower %}
            <!-- If the current loop page is less than max_links. -->
            {% if page_cursor <= min_lower %}
              {% assign page_current_flag = true %}
            {% endif %}

          <!-- Upper limit pages. -->
          <!-- If the user is on a page which is in the upper limit. -->
          {% elsif page_current >= limit_upper %}
            <!-- If the current loop page is greater than total pages minus $max_links -->
            {% if page_cursor > max_upper %}
              {% assign page_current_flag = true %}
            {% endif %}

          <!-- Middle pages. -->
          {% else %}
          
            {% if (page_cursor >= lower_offset) and (page_cursor <= upper_offset) %}
              {% assign page_current_flag = true %}
            {% endif %}

          {% endif %}

        {% else %}
        <!-- Simple page numbers. -->

          {% assign page_current_flag = true %}
        {% endif %}
      {% endcapture %}

      <!-- Show Pager. -->
      ...

    {% endfor %}

Jekyll Pagination: Liquid: page_current_flag

I know this is also a looong code. We are going to make this simpler, by using filter plugin in later chapter.

Using Flag Value

    <!-- Page numbers. -->
    {% for page_cursor in (1..total_pages) %}

      {% capture spaceless %}
        <!-- Flag Calculation -->
        {% assign page_current_flag = false %}

        ...
      {% endcapture %}

      <!-- Show Pager. -->
      {% if page_current_flag == true %}
        {% if page_cursor == page_current %} 
          [ {{ page_cursor }} ]
        {% else %}

          {% capture spaceless %}
          {% if page_cursor == 1 %}
            {% assign p_link = p_first %}
          {% else %}
            {% assign p_link = site.paginate_path
                             | relative_url
                             | replace: ':num', page_cursor %}
          {% endif %}
          {% endcapture %}

          [ <a href="{{ p_link }}">{{ page_cursor }}</a> ]
        {% endif %}
      {% endif %}

    {% endfor %}

Skeleton

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

      {% capture spaceless %}
        <!-- Flag Calculation -->
        {% assign page_current_flag = false %}

        {% if total_pages > link_max %}
        <!-- Complex page numbers. -->

          <!-- Lower limit pages. -->
          {% if page_current <= limit_lower %}
            ...

          <!-- Upper limit pages. -->
          {% elsif page_current >= limit_upper %}
            ...

          <!-- Middle pages. -->
          {% else %}
            ...

          {% endif %}

        {% else %}
        <!-- Simple page numbers. -->

          {% assign page_current_flag = true %}
        {% endif %}
      {% endcapture %}

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

link_offset  = 2

# COMPUTED

total_pages  = 9

Equation

We should manually, do the math.

EQUATION

max_links   = (link_offset * 2) + 1 = 5
lower_limit =  1 + link_offset      = 3
upper_limit =  9 - link_offset      = 7

The real code is shown as below:

    {% capture spaceless %}
      {% assign page_current  = paginator.page %}

      {% assign link_offset   = 2 %}  
      {% assign link_max      = link_offset  | times: 2 | plus: 1 %}

      {% assign limit_lower   = link_offset  | plus: 1 %}
      {% assign limit_upper   = total_pages  | minus: link_offset %}
    {% endcapture %}

Again, that source above are, ported from:

Table

The result is on this table below.

# ALGEBRA

+-------------+-------+-------+-------+-------+-------+
| pagination  |   2   |   3   |   5   |  10   |  20   |
+-------------+-------+-------+-------+-------+-------+
| VARIABLE                                            |
| total_pages |   9   |   6   |   4   |   2   |  N/A  |
| max_links   |   5   |   5   |   5   |   5   |  N/A  |
| lower_limit |   3   |   3   |   3   |   3   |  N/A  |
| upper_limit |   7   |   4   |   2   |   0   |  N/A  |
+-------------+-------+-------+-------+-------+-------+

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 ?

Consider continue reading [ Jekyll Plain - Pagination - Logic ].

Thank you for reading.