Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cycle through num pages at a time #12

Closed
ninjasort opened this issue Feb 29, 2016 · 24 comments
Closed

cycle through num pages at a time #12

ninjasort opened this issue Feb 29, 2016 · 24 comments
Labels

Comments

@ninjasort
Copy link

What would be the best way to approach pagination links that show 5 items at a time and move the offset every 6th page? Thanks.

@blakeembrey
Copy link
Owner

I'm not sure I follow this part: "move the offset every 6th page". Could you describe more of what you're trying to do? Are you saying you want to show "1-5", then "6-10", etc. without moving the displayed pages in the middle (e.g. on page 5 it still shows "1-5")?

@ninjasort
Copy link
Author

Yeah, showing 1-5, 6-10, 11-15, etc. Every 6th page would rotate the grouping.

@blakeembrey
Copy link
Owner

It should be pretty simple math.

var firstPage = Math.floor(currentPage / 6) * 6

Then do a loop the size of the pages forward. Feel free ask more questions 😄

@ninjasort
Copy link
Author

Sorry, how did you come up with that equation?

@blakeembrey
Copy link
Owner

Honestly, I guess intuition? Well, you wanted to have "ranges" of pagination - so that means finding the first page. Assuming the range is 6 pages, you need to get 3 = 0, 9 = 1, ... Then it's just a matter of knowing how to do that, which (one way) is dividing the current page by the range, then multiplying it by the range again to get the lower bound of what you want. I don't know if this helps though?

@ninjasort
Copy link
Author

Doesn't that just give you the current index though? What if you only want a new set after you've passed the 5th page?

@ninjasort
Copy link
Author

Is there no way to just build this in? pagination.group {% for page in pagination.group %}

@blakeembrey
Copy link
Owner

Divide by 5, multiply by 5. It gives you the current index, yes. You can then get the page, whatever you need to do. No, I don't see why it needs to be built in - it's simple and non-standard, I can't think of any pagination that acts like you describe.

@ninjasort
Copy link
Author

I'm using liquid and I have the following:

{% for page in pagination.pages | limit:5 %}
                  <li>
                    <a class="{% if pagination.num == page.pagination.num %}active{% endif %}" href="/{{ page.path }}">
                      {{ page.pagination.num }}
                    </a>
                  </li>
{% endfor %}

This outputs 1,2,3,4,5 but when I click next it goes to 2,3,4,5,6. Having a pagination.group would allow someone to set a limit and bound so that way you could just do:

{% for page in pagination.group %}
                  <li>
                    <a class="{% if pagination.num == page.pagination.num %}active{% endif %}" href="/{{ page.path }}">
                      {{ page.pagination.num }}
                    </a>
                  </li>
{% endfor %}

And you'd get [1],2,3,4,5 then 1,[2],3,4,5 all the way until the 6th page, which would shift the bound and select the next group 6,7,8,9,10. This way, similarly to pagination.index, you get a the active group by bound instead of needing to create a collection from template logic.

@ninjasort
Copy link
Author

It's definitely a common use case for pagination. When do you ever just see one link for pagination when using numbers?

@blakeembrey
Copy link
Owner

blakeembrey commented Mar 2, 2016

@cameronjroe But it's never really you're implementation. If you look at some pagination sections, it's typically centered, not the odd segmented behavior:

image

@blakeembrey
Copy link
Owner

When do you ever just see one link for pagination when using numbers?

I have no idea what this comment is about. Obviously pagination needs more numbers, I feel like that's been established. For custom pagination behavior like yours, just write a custom for loop.

var count = 5
var start = Math.floor(currentIndex / count) * count

for (var i = start; i < pages.length; i++) {
  // Do stuff.
}

I don't use liquid so you'll need to figure out how to write that in your template engine. Or just change the data before you render it.

@ninjasort
Copy link
Author

@ninjasort
Copy link
Author

This is a plugin though, wouldn't it be ideal to abstract template logic into a few simple variables to pass in. I'm not working within js, and most people won't be since metalsmith templating is done with handlebars or liquid.

@blakeembrey
Copy link
Owner

Cool. But I'd still just code it. Isn't your current code wrong right now? It looks like your always limiting it to 5? Can you do function calls in your template engine?

@blakeembrey
Copy link
Owner

If you wish to do a PR, go ahead.

@blakeembrey
Copy link
Owner

If you do a PR, please follow the current behavior getPages.

@ninjasort
Copy link
Author

I can get it to work in the template logic, but all I'm really confused about is how to get the pagination.index by fives.

@blakeembrey
Copy link
Owner

var start = Math.floor(currentIndex / 5) * 5

@ninjasort
Copy link
Author

That doesn't work. And it already exists on pagination.index. I need the same set of pages when pagination.index == 1,2,3,4,5. Then when pagination.index == 6,7,8,9,10, I need the next set of pages.

@blakeembrey
Copy link
Owner

What are you saying? The above is example code. What exists on pagination.index? That literally is currentIndex in my code examples. Please use StackOverflow in the future, I don't have all day to answer general math questions. My understanding from what you've said is exactly what I've posted.

var pages = 5
var start = Math.floor(pagination.index / pages) * pages
var end = Math.min(start + pages, pagination.pages.length)

for (var i = start; i < end; i++) {
  // Do something with the page at this index.
}

@ninjasort
Copy link
Author

This was actually what I was looking for:

{% assign mod = pagination.index | modulo:5 %}
                {% assign diff = pagination.index | minus:mod %}
                {% assign end = diff | plus:4 %}
                {% for index in (diff..end) %}
                  {% assign page = pagination.pages | get:index %}
                  <li>
                    <a class="{% if pagination.num == page.pagination.num %}active{% endif %}" href="/{{ page.path }}">
                      {{ page.pagination.num }}
                    </a>
                  </li>
                {% endfor %}

@blakeembrey
Copy link
Owner

Looks good. That's why I asked if you could use functions, because I'm not familiar with your template library. That's pretty much the same logic as above, just in your custom form, so if you can't use functions it might not be helpful even if it's built in (as it'd require a function call).

(Math.floor(12 / 5) * 5) === (12 - (12 % 5))

@ninjasort
Copy link
Author

Ideally this would just exist as I showed above:

var pagination = require('metalsmith-pagination')

metalsmith.use(pagination({
  'collections.articles': {
    perPage: 5,
    template: 'blog.liquid',
    first: 'index.html',
    cycleLength: 5, // creates a cycle of 5 pages at a time that change when modulo cycles through every 5th item
    path: 'page/:num/index.html',
    pageMetadata: {
      title: 'Archive'
    }
  }
}))

It would also be super convenient to just have the active class as either a string 'active' or '' depending on if the index is the current index. page.activeClass

{% for page in pagination.group %}
  <li>
    <a class="{{ page.pagination.activeClass }}" href="/{{ page.path }}">
      {{ page.pagination.num }}
    </a>
  </li>
{% endfor %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants