This repository has been archived on 2025-03-28. You can view files and clone it, but cannot push or open issues or pull requests.
coryd.dev-eleventy/src/posts/2023/lazy-select-based-pagination-eleventy.md
2023-12-11 13:28:47 -08:00

3.1 KiB

date title description draft tags
2023-03-27 Lazy select-based pagination in Eleventy I've relaunched, rebuilt and rewritten my personal blog more times than I can count, and I've had a trail of posts I've never fully migrated at each turn. This weekend, while relaxing and watching movies I ported them into Eleventy and, in doing so, found that the pagination implementation I was using didn't scale well with the number of pages I added. false
Eleventy
JavaScript
development

I've relaunched, rebuilt and rewritten my personal blog more times than I can count, and I've had a trail of posts I've never fully migrated at each turn. This weekend, while relaxing and watching movies I ported them into Eleventy and, in doing so, found that the pagination implementation I was using didn't scale well with the number of pages I added.

I quickly explored having the current page act as a floating index of sorts wherein I would cap the number of pages shown at, say, 5 and then show the previous and next two pages on either side. Limiting the rendered count in liquid.js was as simple as using the limit filter, but tracking the floating index and numbers on either side was more difficult than I would have liked.

Given that I was already iterating through all pages in my posts collection, my next thought (and the choice I ran with) was to fold all the enumerated values into a <select> and use that to give users more control when paging. That select lives in paginator.liquid#17-28 and looks like this:

  <div class="flex flex-row items-center">
    <select
      id="pagination"
      class="block w-12 h-12 rounded-full text-white dark:text-gray-900 bg-blue-500 hover:bg-blue-500 dark:hover:bg-blue-300 mr-1 focus-visible:outline-none focus-visible:bg-blue-400 appearance-none text-center"
      style="text-align-last:center">
      {% for pageEntry in pagination.pages %}
        <option {% if page.url == pagination.hrefs[forloop.index0] %}selected{% endif %} value="{{ forloop.index }}">{{ forloop.index }}</option>
      {% endfor %}
    </select>
    <span>
      of {{ pagination.links.size }}</span>
  </div>

When the select is changed, Javascript is executed to update the current uri to the appropriate page — that logic lives in an IIFE in base.liquid:

(function() {
    const pagination = document.getElementById('pagination');
        if (pagination) {
          pagination.addEventListener('change', (event) => {
            const page = parseInt(event.target.value)
            if (page === 1) {
              window.location.href = '/'
            } else {
              window.location.href = `/${
                event.target.value - 1
              }/`
            }
        })
    }
})()

You can see all of that rendered here.