Search code examples
jekyllliquidjekyll-paginator

How to paginate Jekyll's data items using Liquid


Hi I'm trying to access elements from the previous and next arrays. To be exact I want to access the previous and next url of pages. This is what I have done so far.Thanks!

{% assign page_venue = site.data.venues-array | where: "venueID",   page.venue | first %
//This outputs the current url
{{venue.url}}

This is part of the yml file:

venueID: Red-Radish
name: Red Radish
url: redradish
building: 65
neighborhood: University Union

venueID: Poly-Deli
name: Poly Deli
url: polydeli
building: 19
neighborhood: University Union

venueID: Myrons
name: Myron's
url: myrons
previous: MustangStation
building: 19
neighborhood: University Union

So let's say I'm the second venue (Poly-Deli), I would like to see this:
Current url: polydeli
Previous url: reddish
Next url: myrons
I tried using the following to output the previous and next urls but it dindn't work:

<p>{{page.next.url}}</p>
<p>{{venue.next.url}}</p>
<p>{{paginate.next.url}}</p>
<p>{{paginator.next_page}}</p>

Someone helped me, and it did work, but it outputs the whole list. I just want to output something like this because this because I have 30 arrays(30 different venues):
Current url: polydeli
Previous url: reddish
Next url: myrons

And this is the code that outputs the whole list:

{% for venue in site.data.venues-array %}

  {% assign next = forloop.index0 | plus: 1 %}
  {% assign previous = forloop.index0 | minus: 1 %}
    <div>Name: {{ venue.name }}</div>
    <div>Current URL: {{ venue.url }}</div>

    <div>Previous url:{{ site.data.venues-array[previous].url }}</div>
    <div>Next URL is:{{ site.data.venues-array[next].url }}</div>
    <hr>

{% endfor %} 

Solution

  • As I've mentioned in my previous comment, I was not able to find a suitable plugin to paginate a _data collection. There are a few available but all require a lot of hacking plus they are quite bloated for such a simple requirement.

    You can add the following HTML and JS to the content part of your venues page. (I.e. underneath the front-matter).

    HTML:

    ---
    ---
    <div class="venue">
    
    </div>
    

    JavaScript:

    <script type="text/javascript">
    
      /**
       * Setting for whether to keep looping or not.
       * If set to true, the first venue will show the URL of the last venue as
       * the previous venue, while the last venue will show the URL of the first
       * venue as the next one.
       *
       * If set to false, the first venue will not include a previous URL, while the last venue * * won't display the next URL.
       */
      var infinite = true
    
      // Gets all the venues adta and parses it as JSON.
      var venues = '{{ site.data.venues-array | jsonify }}'
      venues = JSON.parse(venues)
    
    
      // Inits the html content.
      var html = ''
    
      // The array index of the current venue.
      var currentVenueIndex = 0
    
      /**
       * Displays the current venue. Includes the previous and next links.
       *
       */
      var generateHtmlForCurrentVenue = function (venueName) {
        var venueContent = '<p>Current Venue Name: ' + venueName + '</p>' +
    
        getPreviousLink() + getNextLink()
    
        html = venueContent
      }
    
      /**
       * Gets the previous URL link unless we're not infinitely looping and the
       * current Venue is the first item in the array.
       */
      var getPreviousLink = function () {
        link = ''
        if (!infinite&& currentVenueIndex == 0) {
          return link
        }
        previousIndex = 0
        if (currentVenueIndex == 0) {
          previousIndex = (venues.length - 1)
        } else {
          previousIndex = (currentVenueIndex - 1)
        }
    
        return '<p>Previous: <a href="#" class="previous-venue">' +
          venues[previousIndex].url + '</a></p>'
    
      }
    
      /**
       * Gets the next URL link unless we're not infnitely looping and the
       * current Venue is the last item in the array.
       */
      var getNextLink = function () {
        link = ''
        if (!infinite&& currentVenueIndex >= (venues.length -1)) {
          return link
        }
        nextIndex = 0
        if (!(currentVenueIndex >= (venues.length - 1))) {
          nextIndex = (currentVenueIndex + 1)
        }
        return '<p>Next: <a href="#" class="next-venue">' +
          venues[nextIndex].url + '</a></p>'
      }
    
    
      /**
       * Shows the Previous Venue.
       */
      var showPreviousVenue = function () {
        if (currentVenueIndex == 0) {
          currentVenueIndex = (venues.length -1)
        } else {
          currentVenueIndex --
        }
        $('.venue').html('')
        generateHtmlForCurrentVenue(venues[currentVenueIndex].name)
        $('.venue').html(html)
      }
    
      /**
       * Shows the Next Venue.
       */
      var showNextVenue = function () {
        if (currentVenueIndex == (venues.length -1)) {
          currentVenueIndex = 0
        } else {
          currentVenueIndex ++
        }
        $('.venue').html('')
        generateHtmlForCurrentVenue(venues[currentVenueIndex].name)
        $('.venue').html(html)
      }
    
      /**
       * Previous venue link click event handler.
       */
      $(document.body).on('click', '.previous-venue', function (event) {
        event.preventDefault()
        showPreviousVenue()
      })
    
    
      /**
       * Next venue link click event handler.
       */
      $(document.body).on('click', '.next-venue', function (event){
        event.preventDefault()
        showNextVenue()
      })
    
      generateHtmlForCurrentVenue(venues[currentVenueIndex].name)
    
      $('.venue').html(html)
    
    </script>
    

    You can change whether to keep looping or not by toggling the infinite variable as explained in the code's comments.

    Please note:

    I have an older version of Jekyll on my system (v3.0.2) and thus the jsonify filter breaks when there are single quotes in the text values of the venues-array.yml. I.e. Myron's breaks and I could not escape it as shown below: enter image description here

    If you have the Jekyll >= 3.2 then I believe you will not have this issue as Jekyll will automatically use the UTF-8 encoding in advance of running the filter. I cannot upgrade my machine due to a client's site requiring this version and without a Docker container. If you do have this issue, try:

    1) Enforce UTF-8 on your yml file. or 2) Clean up single quotes in advance of the filter or 3) Don't use single quotes :)

    Escaping did not work for me.

    Other than that, all works perfectly as shown below:

    enter image description here