Adding previous/next buttons (for blog-entry batches)

It won’t, I’m afraid.

It was one my first attempts to give back to the community, and it has a fairly narrow range. It’s designed to let you navigate back and forth between a list of tiddlers that share a common tag. That’s it.

This sounds like an interesting challenge, and if I find time I’ll fiddle with it too

Hello again! I think I have a working solution that you can drag and drop. You will surely want to tinker with the aesthetics. But the function is more or less solid.

NOTE: This version needs TiddlyWiki v5.3.x because it uses the new <thisTiddler> variable to make the code simpler for setting its own field values. (If you don’t have such a recent version, I’d encourage you to upgrade, or reach out for follow-up…)

Just visit this demo link, and DRAG the tiddler there to your own site (and confirm the import). (Don’t worry — it won’t drag over the content of the dummy blog posts — just the frame for holding a set of posts, with navigation among the sets. I made ChatGPT generate a set of dummy blog posts about itself, but once the tiddler is on your site, it should simply display whatever is tagged “Blog” there.)

This version fixes the earlier “butfirst” glitch, and puts both the variables into fields of the same “blog frame” tiddler. This means that the solution is now “self-contained” in a way that the prior one was not. (It used a system tiddler to hold the startval).

I have the interval field set to 5, so that the demo has enough to scroll through (I didn’t generate very many dummy posts). Set the interval however you like!

I’ll also paste the code below, in its current form (to make this thread not useless beyond the half-life of my demo blog). Note dragging the actual tiddler has the benefit of including the interval and startval fields, so if you copy the code below, you would want to add those fields manually.

<$let topic="Blog" blogcount={{{ [tag<topic>!sort[created]count[]] }}} interval={{{ [<thisTiddler>get[interval]] }}}>

<div style="text-align:center;"> 
<$list filter="[<thisTiddler>get[startval]compare:number:gt[0]]">
<$button><$action-setfield $tiddler=<<thisTiddler>> $field=startval startval="0" />
RESET to TOP</$button>
</$list></div>
<$list filter="[<thisTiddler>get[startval]compare:number:gt[0]]">
<$button><$action-setfield $tiddler=<<thisTiddler>> $field=startval startval={{{ [<thisTiddler>get[startval]subtract<interval>] }}} />
PREVIOUS (Show posts from <$text text={{{ [<thisTiddler>get[startval]subtract<interval>add[1]] }}}/> to <$text text={{{ [<thisTiddler>get[startval]] }}}/>)
</$button></$list>
<$list filter="[<thisTiddler>get[startval]add<interval>compare:number:lt<blogcount>]">
@@float:right;<$button><$action-setfield $tiddler=<<thisTiddler>> $field=startval startval={{{ [<thisTiddler>get[startval]add<interval>] }}} />
NEXT (Show posts from <$text text={{{ [<thisTiddler>get[startval]add<interval>add[1]] }}}/> to <$text text={{{ [<thisTiddler>get[startval]add<interval>add<interval>] }}}/>)
</$button>@@</$list>

@@clear:both;<br>@@
<hr>

<div style="text-align:center;"> 
//Items tagged __<<topic>>__ from <$text text={{{ [<thisTiddler>get[startval]add[1]] }}}/> to <$text text={{{ [<thisTiddler>get[startval]add<interval>] }}}/> (of <<blogcount>> total)://</div>

<$let startval={{{ [<thisTiddler>get[startval]] }}}>

<$list filter="[tag<topic>!sort[created]butfirst<startval>limit<interval>]">
  <div class="blog">
  <h2><$link/></h2>
  <p style="font-weight: bold; font-style: italics;"><$view field="created" format="date" template="DD MMM YYYY hh:0mm" /></p>
<$transclude mode="block"/>
  </div>
</$list>

</$let></$let>
2 Likes

You may also be interested — at some point — in checking out this solution, which is related:

@TheScribe it may be helpful to modify the title of this topic to indicate it is not simply next/previous but “Next/previous N items in a list” or group of items etc…

  • As a result of this title I spent some time polishing a next previous button solution that proved to be somewhat off topic here. Although I will eventually share it. If you change the title I can delete this reply.

I used my editorial privileges to add clarification to title. Obviously, @TheScribe can further edit or revoke my edit.

Recently, I’ve noticed so many posts whose titles don’t quite put their themes in focus. It’s especially hard for relative novices to recognize which differences make a difference, though!

I tried this, and it resulted in a reasonable demo.

To use it, download pagination.json (1.6 KB) and drag it to your wiki.

Then create a tiddler with the fields items-per-page and page-number, and in the body, call the macro pagination passing it a filter describing the blog posts you would like to include.

It might look like this:

title: My Blog
items-per-page: 5
page-number: 1

<<paginate "[tag[Blog]!sort[created]]" >>

And that’s it!

On the demo page are a list of Potential improvements I could see making to this, but it’s reasonably functional as is.

3 Likes

Thank you @Springer and @Scott_Sauyet for the suggestions. I’ve tried them both, and got both of them to work well. Neither was difficult to use or change to suit my needs.

On this occassion, I’ve decided that the pagination.json worked exactly how I envisioned. I’m super happy with the result and I’m another step closer to finishing my website.

1 Like

Hi, I tried your Wizard Nav plugin, very well made.
I was wondering if there was a way to “combine” the two creations, it might be interesting:


Something like a pagination that always has items-per-page: 1 where you can navigate not only with previous and next but you can also navigate by selecting the desired tiddler in a tag-pill (like you can in the Wizard Nav)
But with the advantage that you can transclude the tiddler instead of opening it (as happens in Wizard Nav)

Or to put it in other words, a Wizard Nav where you don’t navigate in the storyview, but within the same “container” tiddler using transclusions


(I said items-per-page: 1 because I wouldn’t know if this thing is possible if the number is higher.)

Just a thought.

Anyway, excellent creations, congratulations! :balloon:

I can see why we might want to consider that.

But I would be very afraid of making a Frankenstein’s monster if we actually tried. I certainly wouldn’t try to build on either one of them to create the other; they’re too logically far apart. If we were to try this, I would expect it to start from scratch.

Wizard Nav Pagination
Invocation Tagging convention Explicit macro/procedure call
Target tiddlers All tiddlers sharing a common tag, where that tag itself is tagged Wizard The result of an arbitrary filter
Body handling N/A - standard TW handling The body is generated by pagination script An enhancement might use a supplied macro/procedure instead
Footer An (overridable) ViewTemplate generates the footer The footer is encoded in the pagination script

But a common pagination/navigation control would make a lot of sense. I would love to see something that could be extracted to be used by both of these. I don’t have a real sense, though, of what its interface would be like.

Good points, thanks for the reply.
I’ll think about it, if I have ideas/any files to share, I will :+1:t2:

  • It seems if we can build or enhance how we select a position in a list may be a first step.

It is my view that as a community we are quite good at building point solutions in a plugin or package and driving low level changes in the code.

  • However, we are not so good at developing shared community solutions, or de facto standards higher up in the “application” stack. Perhaps a discussion for another day. My hunch is it needs to start with a supportive infrastructure.

Until we can find away to enhance collaboration in the community, the challenge of bringing two solutions together may be best served either making a third combined solution, or by breaking both into separate modules with as many as practical being common.

Note: I maintain a “watching brief” on such subjects and continue to investigate the handling of set/lists, their navigation, reuse and combinations.

  • I will now take the idea of such navigation as being able to set a position in a list/set such that other navigation and pagination tools can access it.

We might also need useful ways to deal with a list of lists. I think it should already be possible, but it’s not at all obvious.

I’m not sure that it’s more than tangentially related, but since we already have the nth / zth operators for cases where you want, e.g., the third title in a list, it occurred to me yesterday that I would expect a title in a list to know its current position in that list. Clearly this information is already available, since list widgets can define a counter variable, but there’s no easy way to access that counter within the list filter itself. a b c +[nth[3]] will give me c, but there’s no simple way to derive 2 from b and 3 from c in the same filter.

I eventually discovered that Evan Balster had written a custom addposition operator back in 2016 (!) which did everything I needed at the time, but it’s a pity that it never made it into the core. Or, perhaps, a <counter> variable that gets defined within the context of a subfilter or a :filter/:map run, as <currentTiddler> is redefined to refer to each input string?

  • “in the same filter.” limits possibilities, but not inside TiddlyWiki script.

Actually there are a few ways to do this. You can use the $set widget to set a list-variable (A variable containing a list) and access the list members by an index, or use allbefore<currentTiddler>count[]to find the position in a list.

  • But this discussion may go too far off topic.

Other methods include;

  • storing a list in a javascript array
  • Maybe using the map accumulator add 1 not multiple?
  • Inside a list widget with the counter variable

I’ve probably just duplicated code that you’ve already received, but it felt like a fun coding exercise that I wanted to jump into without looking at other code already given.

Drag the attached into TiddlyWiki.com

List of tiddler titles in groups of 10 per page.json (1.3 KB)

The result:

2 Likes

That’s going to be difficult with a list like a b c d c a b e f a b c. Should b yield 2, 7, 11, or all of them?

I think I’d expect it to follow the normal deduplication rules. a b c d c a b e f a b c = d e f a b c unless you’re taking special steps to preserve the duplicates, so b = 5. If you are preserving duplicates, then b = 2 7 11.

(Edit: This would be the converse of the nth operator: a b c d c a b e f a b c +[nth[5]] = b, while ... +[nth[2]] = e, and +[nth[7]] and +[nth[11]] return a blank result. =a =b =c d =c =a =b e f =a =b =c +[nth[11]] does return b.)

It’s an interesting point, though, and I admit I haven’t checked to see how Evan chose to handle it.

EDIT now that I’m back at my computer: Evan’s addposition operator does work exactly as I’d expect.

image

1 Like

Nice! One issue. This is overcomplicated, occasionally wrong, and mostly unnecessary:

<$let tid_count={{{ [all[tiddlers]sort[]limit[54]count[]] }}}
      page_count={{{ [<tid_count>divide[10]floor[]] =[<tid_count>divide[10]subtract<page_count>!match[0]then[1]] +[sum[]] }}}>

If you change the limit to 60, you will get a page_count of 7.

I don’t know if his is because of rounding in the Javascript’s underlying floating point specification, or has something to do with the odd use of <page_count> in the definition of page_count, but I’m not sure that’s important, because it can be much simplified with the use of ceil instead of floor:

<$let tid_count={{{ [all[tiddlers]sort[]limit[60]count[]] }}}
      page_count={{{ [<tid_count>divide[10]ceil[]] }}}> 

Hi @Springer,
inspired by the code I’d need a little help to improve the code:

<$let topic="2023" blogcount={{{ [tag<topic>!sort[published]count[]] }}} interval=23>

Suche nach __<<topic>>__  <span style="font-size: 0.7em; color: rgba(204, 204, 255, 0.6);">&emsp; <$text text={{{ [{$:/blog-startval}] }}}/> - <$text text={{{ [{$:/blog-startval}add<interval>subtract[1]] }}}/> (von <<blogcount>>)</span>

grafik

<blogcount> is the max: 245
adding the <interval> will exceed the <blogcount> (=253)

I’d like to have:

"If <$text text={{{ [{$:/blog-startval}add<interval>subtract[1]] }}}/> is gteq <blogcount> than <blogcount>; else <$text text={{{ [{$:/blog-startval}add<interval>subtract[1]] }}}/>

means: If 253 >= 245 than 245; else add the interval 23

How can that be done?

Thanks, Stefan

If I understard correctly, what you’re concerned about (adding the interval only if it wouldn’t send the value past the actual count of items) is what I tried to handle by having the “NEXT” button show up only if adding the interval would not result in a value beyond the blogcount:

<$list filter="[<thisTiddler>get[startval]add<interval>compare:number:lt<blogcount>]">
@@float:right;<$button><$action-setfield $tiddler=<<thisTiddler>> $field=startval startval={{{ [<thisTiddler>get[startval]add<interval>] }}} />
NEXT (Show posts from <$text text={{{ [<thisTiddler>get[startval]add<interval>add[1]] }}}/> to <$text text={{{ [<thisTiddler>get[startval]add<interval>add<interval>] }}}/>)
</$button>@@</$list>

Of course, you could change what action the button does, instead. But I think having the button disappear (or more elegantly, make itself greyed-out) makes for a clearer user interface.

If I’ve misunderstood, please follow up!