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

As a User, I want pagination, so that ... #116

Closed
pismute opened this Issue Dec 23, 2011 · 31 comments

Comments

Projects
None yet
5 participants
@pismute
Contributor

pismute commented Dec 23, 2011

I need pagination. For example, if I have a template file index.html.coffee, then Docpad generate it to index-0.html, index-1.html, index-2.html, ....

Is it possible? Tell me how to do.

@balupton

This comment has been minimized.

Member

balupton commented Dec 28, 2011

Hey @pismute :-)

Can you let me know for what purpose you need pagination? As in, what value does pagination bring to you?

Depending on the answer to that, will depend on the solution we could provide. For instance, is it necessary creating multiple files, or would just having hidden divs with some url magic do the trick.

Thanks mate :-)

@pismute

This comment has been minimized.

Contributor

pismute commented Dec 29, 2011

I want creating multiple files.

For example. I have many documents on my old blog. I want to move it. Anyway, my index.html is a list for all of summary of documents. In this case, I think my Index.html is too big.

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Feb 24, 2012

Is there any progress on this or at least workaround. I am facing the same issue.

@balupton

This comment has been minimized.

Member

balupton commented Feb 24, 2012

@dimitarkolev the priority of tasks go to which ones get the most voice behind them, so I'll bump this one up a notch.

Would you both @pismute and @dimitarkolev be able to talk a bit about what you would expect the paging functionality to be like? As the next step is building clear requirements for this so we can make sure everyone is happy.

Here are my current thoughts:

  1. It can be accomplished now by putting the different pages into different files, e.g. article.html.md, then article-page2.html.md, then article-page3.html.md - then creating a layout called paged-article which they all use, this layout will inherit from your standard article layout but include a page count and navigation in the bottom. The navigation would be constructed by doing something like:
    • The paged article document:

      ---
      title: 'Article - Page 2'
      pageNumber: 2
      layout: 'article-paged'
      ---
    • The paged article layout:

      ---
      layout: 'article'
      ---
      
      <%-@content%>
      
      <h2>Page Navigation:</h2>
      <% for document in @database.find(url: $beginsWith: @document.relativeBase).sort('pageNumber'): %>
          <a href="<%=document.url%>">Page <%=document.pageNumber%></a>
      <% end %>
    • The article layout:

      ---
      layout: 'default'
      ---
      
      <div class="article">
          <%-@content%>
      </div>
  2. Using a client-side solution, you could write all your pages in the same document and wrap them in a div.page then use javascript to insert the page nav and navigation.
  3. Another option is somehow creating a plugin for docpad, which would somehow do something.

What are your thoughts on the first solution? I'd be happy to provide an example of this working.

Or what is your dream intuitive solution for pagination? How could pages be handled perfectly in your opinion?

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Feb 25, 2012

I believe that the best solution will be to have something like that

<% @document.fork 'newpage-name.html' userState %>

And put this in the layout when i want to create a new page in the outout. The user can use this not only for paging but also for creating multiple versions of the same content, like sorting or filtering, etc. I can handle the paging myself or create a plugin that will do it. So in general it will be great to be able to split the output into several html files and pass along some state information.

@balupton

This comment has been minimized.

Member

balupton commented Feb 25, 2012

If I understand you correctly, a plugin would be created that would scan documents for <% @document.fork 'newpage-name.html' userState %> when it hits that, it would split the the following data into a new file specified then, until it hits the end of the file or the next document fork...

Perhaps I've misinterpreted something, but this seems like quite a lot of effort and quite a complex paradigm to introduce to docpad, especially compared to the more straightforward approach of writing each page as it's own document (something which would already be supported). If I've got that correct, then I'm not sure I can see enough value add to justify heading in that direction, personally.

Although I'm happy to debate and brainstorm this further!

@balupton

This comment has been minimized.

Member

balupton commented Feb 25, 2012

Perhaps one way to go is to have the following:

---
multi: true
filename: 'article.html.md'
page: 1
title: 'Article - Page 1'
---

This is a cool article. <a href="<%=@plugins.paging.nextPage(@document)%>">Next page!</a>



---
filename: 'article-page2.html.md'
page: 2
title: 'Article - Page 2'
---

This is page 2.

However, I still don't feel confident that the value add of adding support of this is so great compared to just physically splitting them into multiple files.

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Feb 25, 2012

My idea was not have any logic for data split its up to user to decide what content he wants on each page from docpads point of view it will be just process the same document and output it with different name.
So no flowing data split or some fancy logic in there just an option to have two or more html files generated from one document.

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Feb 25, 2012

An example for paging will be something like that (In this case userState will be used for passing pageNumber):

<% for document in @database.[get articles from M to N based on document.userState]): %>
    <a href="<%= @document.baseName + (document.userState+1) + document.extenstion %>">Next Page <%= @document.userState + 1 %></a>
<% end %>
<% if [there are more pages] %>
    <% @document.fork @document.baseName + (document.userState+1) + document.extenstion, @document.userState+1 %>
<% end %>

It will be even easier for sorting and filtering. From my perspective its sort of the multi solution with an automation.

@pismute

This comment has been minimized.

Contributor

pismute commented Feb 26, 2012

1 is good idea. But I think it is not for list pages fo docs. I need a helper plugin accepting special document for pagination.

For example:

  • index.html.eco.paged
    ---
    layout: 'default'
    pageSize: 10
    ---
    <% for document in @document %>
        <% if @page.start <= index <= @page.limit %>
            ...
        <% end %>
    <% end %>
    <% for num in [0..@page.total] %>
        <% if num = @page.number %>
            Page <%=num%>
        <% else %>
            <a href="index.html-<%=num%>.html">Page <%=num%></a>
        <% end %>
    <% end %>
  • Plugin

This plugin injects @page object to each page When it generates html files like index-1.html, index-2.html.

@balupton

This comment has been minimized.

Member

balupton commented Feb 26, 2012

Interesting and good ideas!

For any auto splitting of files, we'll need to figure out how that will work as it's not currently supported.

I'd imagine when @pismute's plugin hits the document, it will have to clone the document model, populate it with the new values, and store this new document into the database - and hopefully the next step in the rendering process will pick it up. Any other ideas how this could work?

@balupton

This comment has been minimized.

Member

balupton commented Feb 26, 2012

It seems the plugin event to go about this would be parseAfter, where we would scan the database for all documents with pageSize defined, find them, and then cycle through the pageSize cloning the model each time and storing all the new models in the database. So that way when rendering starts, we have our pages inside the database ready to be rendered. This would also mean that we don't need the .paged extension.

The only downside of the pageSize approach I can see is that you have to keep that in sync with how many pages you actually write, whereas @dimitarkolev's suggestion was to have some pseudo function type thing which keeps track of how many pages you have.

To accomplish this auto detection of pages would be quite tricky from my initial thoughts on it. As at the parsing point, we have not yet processed the document's body - so anything inside it would not have rendered yet.

Perhaps a brainstorm session over skype would be best? I'm in Sydney time zone, and anytime between 6pm and 11pm works for me. http://everytimezone.com/

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Feb 27, 2012

6pm-8pm your time if fine for me, if pismute is ok we can pick a date and make the skype meeting.
As a side node, we can count the pages having something like:
---
layout: 'default'
pageSize: 10
pages: '/articles/*.html'
---

@pismute

This comment has been minimized.

Contributor

pismute commented Feb 27, 2012

I hope to do that. But, I have a big problem, My English is bad. I think it is better you guys to make meeting without me. I am sorry.:) I cannot hear you.--;

@balupton, parseAfter is Great. I think I totally understand it. @dimitarkolev's page pattern is good idea. we can use ant path pattern or blob patterns to count target documents.

paged extension is a example. What i am saying is I need a [special] document for pagination. Following is ok.

---
multi: true
---

otherwise we can make another document types like layout. so that we make documents in src/multi such as src/documents or src/layouts. I just imagine I have to tell a plugin this document is for pagination

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Feb 27, 2012

I think
pageSize: 10
is enough to differentiate multi documents - the default will be 0 if its more than 0 you will have pagination. This way there will be no need for different folders and extra meta properties.

@balupton

This comment has been minimized.

Member

balupton commented Feb 27, 2012

Cool, I'll leave Skype on tonight then :-)

I think the following is the best solution so far. There is no automatic detection of pages within the documents, but at least it will work quite well.

  • Some article:

    ---
    layout: 'page'
    pageTotal: 10
    ---
    <% if @pageNumber is 0 %>
       Page 1
    <% else if @pageNumber is 2 %>
        Page 2
    <% end %>
    
  • Page layout:

    <% for page, pageNumber in @pages %>
        <% if pageNumber is @pageNumber %>
            Page <%-pageNumber+1%>
        <% else %>
            <a title="<%=@page.title%>" href="<%-@page.url%>">Page <%-pageNumber+1%></a>
        <% end %>
    <% end %>
    

This means the page plugin will hook onto parseAfter, scan for pageSize. And inject the following templateData variables:

pageNumber: null # for the current page number, starting at 0
pages: [] # an array of the generated documents inside the page

If this works for you guys, let's go ahead with that. Let's still try and come up with a solution for automatic detection of page though. Here is my current brainstorm for that:

---
layout: 'page'
pageTotal: 10
---

Page 1

=== page ===

Page 2

Your thoughts?

@pismute

This comment has been minimized.

Contributor

pismute commented Feb 28, 2012

Great idea. It is enough for me.

Thank you guys.

@balupton

This comment has been minimized.

Member

balupton commented Nov 23, 2012

For newcomers, this gist is how we currently accomplish paging - https://gist.github.com/3695876

Doing a suggestion like the above can be possible, but isn't yet as no one has done the plugin up for it - hehe. It is on the todo list.

@benjamind

This comment has been minimized.

benjamind commented Nov 30, 2012

I've just published a plugin that does paging in a similar way to described above.

https://npmjs.org/package/docpad-plugin-paged

Hopefully it should work for you, it allows generating multiple files from a single document either through specifying a pageCount property so you can control how many times the document is re-rendered, or through specifying a pagedCollection property which specifies the name of a collection to loop over.

I haven't yet managed to get the unit-testing working on the plugin as I couldn't figure out how it works with DocPad, but I've been testing it on my own DocPad sites and it seems ok.

Let me know what you think and if there are any issues.

@hanjianwei

This comment has been minimized.

hanjianwei commented Jan 5, 2013

hi, @benjamind

Does the plugin work for jade template? I tried it with Jade template. The index.html was rendered perfectly but the index.1.html was not rendered. (I will write a test later)

I am new to docpad, but the created document should inherite extensions, right?

@hanjianwei

This comment has been minimized.

hanjianwei commented Jan 5, 2013

The document fork idea of @dimitarkolev is really cool! We can group documents with same tag into one page and group posts by date. These are basic requirements for a blog. Jekyll uses generator to implement these but document fork seems more friendly.

Anyway a single input with multiple outputs is reasonable. You can have one md file rendered to both html and pdf, one viewed online and the other for download.

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Jan 5, 2013

@hanjianwei Dont blame jade its not working with eco either, or at least i am still not able to make it work. Still investigating...

@benjamind

This comment has been minimized.

benjamind commented Jan 5, 2013

@dimitarkolev @hanjianwei hey guys. Sounds like the plugin has been broken again in a recent build. Lots of changes recently related to document loading. Am away from the PC this weekend but will try and take a look at this on Monday. Otherwise feel free to fork and investigate and I will merge any fixes you come up with.

We need to move this plugin into the docpad umbrella so it can be tested as part of the development process.

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Jan 5, 2013

After some time playing around with the plugin i found out that for some reason document.render({templateData:docpad.getTemplateData()},complete) is not working as expected. It just outputs the raw content of the page but does not do any rendering. I believe its something very small that got changed is causing this behavior, but so far i can not tell what. Besides this issue its great plugin and its making docpad complete. Without it there are many scenarios(for static site generation) docpad cant handle.

@balupton

This comment has been minimized.

Member

balupton commented Jan 5, 2013

v6.21 redid the parsing and loading, so there could be a regression that we didn't catch.

@benjamind I've created https://github.com/docpad/docpad-plugin-paged which you now have write access to, so push up your stuff there, also add me as an owner of the plugin so I can fix things if something breaks with a new docpad build :)

Alternatively, you could transfer your repo to the docpad org, rather than pushing to the new repo. This will require me to delete the one I just created.

@benjamind

This comment has been minimized.

benjamind commented Jan 5, 2013

Thanks, have pushed up the current version there. I assume to add you as an owner of the plugin I just need to add you to the maintainers list in the package.json and deploy a new version up to npm?

Before I do that I wanted to confirm/fix the bug above, but am currently having a bit of a problem reproducing it. Could just be post-new years haze confusing my brain but it appears the current version of docpad in github isn't working correctly. This issue appears to have resurfaced as I can't hit my site when using docpad run without generating the getByCid error. generate seems to be working well enough and the plugin seems to be outputting as expected.

Can anyone else confirm the paged plugin as working/not working?

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Jan 5, 2013

I just found out that i was not using latest docpad version, after an update it looks like its working now.

@benjamind

This comment has been minimized.

benjamind commented Jan 5, 2013

@dimitarkolev just did the same here, seems all good.

@balupton ignore my earlier comment about the getByCid bug, forgot to recompile docpad after pulling latest. Looks like its all good, have added you as an owner on the plugin on npm too. Should do the same for the sitemap plugin sometime but I want to confirm it all working first.

@dimitarkolev

This comment has been minimized.

dimitarkolev commented Jan 5, 2013

I just found out that the actual reason for paged not working was a fact that on the site im working i used partials plugin. And i did tested the new version on another site which does not use partials.

So paged plugin does not work when partials plugin is used. (Both are used in completely different documents)

Here is a link to a very simple project that illustrates the issue http://dox.bg/files/dw?a=eaf4873702
Requied Plugins: docpad-plugin-eco, docpad-plugin-marked, docpad-plugin-paged and docpad-plugin-partials

@benjamind

This comment has been minimized.

benjamind commented Jan 5, 2013

Aha. Nice one. Will look into this and compatibility with the clean URLs plugin next week.

@balupton

This comment has been minimized.

Member

balupton commented Apr 24, 2013

Closing. All respective issues inside here have been completed. If there is still anything present, open a new issue on the corresponding repo. Thanks everyone :) 👍

@balupton balupton closed this Apr 24, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment