PageTurner Issues

When I first started with TW I needed a way to ‘turn pages’ going from one tiddler to the next. Someone on this list, I forget who, gave me a tiddler, PageTurner, which did that beautifully, code below.

<$list filter="[<currentTiddler>tag[Artworks]]">
<div style="float:right;">
   <$vars prev={{{ [tag[Artworks]sort[]before<currentTiddler>] }}}>
   <$vars next={{{ [tag[Artworks]sort[]after<currentTiddler>] }}}>
   <$reveal default=<<prev>> type="nomatch" text="">
   <$button tooltip=<<prev>>> {{$:/core/images/chevron-left}}
      <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>> />
      <$action-navigate $to=<<prev>>/>
   </$button>
   </$reveal>
   <$reveal default=<<next>> type="nomatch" text="">
   <$button tooltip=<<next>>> {{$:/core/images/chevron-right}}
      <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>> />
      <$action-navigate $to=<<next>>/>
   </$button>
   </$reveal>
   </$vars>
   </$vars>
</div>
</$list>

I now want to do something similar yet different. The problem is that the code works perfectly if I restrict the filters to all artworks.

But my requirement is for a subset of Artworks, for example, all artworks of a type or within a specific date range. I guess I could provide a number of PageTurner tiddlers, each handling a specific filter but I prefer generic solutions. I sort of need to provide my filter as a parameter to this code but can not see a way to do that. I would love it if I could store required filters on separate tiddlers and then use the contents of a tiddler to provide the filter statement to be interpreted at run time.

For example, have a tiddler PG1 with text of [<currentTiddler>object_type[Artist Books]] and have the filter code in PageTurner read something liked <$list filter=<<PG1>>

Each artwork tiddler has a field object_type which specifies the type of work that it is, so, Painting, Artist Book, Print, etc.

Can anyone shed some light on this for me?

bobj

3 Likes

I’m pretty certain that code came from me.

Here’s how to modify it to achieve your new goal (“provide my filter as a parameter”):

\procedure PageTurner(filterTiddler)
<$let filt={{{ [<filterTiddler>get[text]] }}}>
<$list filter="[<filt>!match[]then<currentTiddler>subfilter<filt>]">
<div style="float:right;">
   <$vars prev={{{ [subfilter<filt>sort[]before<currentTiddler>] }}}>
   <$vars next={{{ [subfilter<filt>sort[]after<currentTiddler>] }}}>
   <$reveal default=<<prev>> type="nomatch" text="">
   <$button tooltip=<<prev>>> {{$:/core/images/chevron-left}}
      <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>> />
      <$action-navigate $to=<<prev>>/>
   </$button>
   </$reveal>
   <$reveal default=<<next>> type="nomatch" text="">
   <$button tooltip=<<next>>> {{$:/core/images/chevron-right}}
      <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>> />
      <$action-navigate $to=<<next>>/>
   </$button>
   </$reveal>
   </$vars>
   </$vars>
</div>
</$list>
\end

Notes:

  • Start by enclosing the code within a \procedure definition, so that you can
    • pass a tiddler title as a parameter
    • invoke it with a simple <<PageTurner tiddlername>> syntax
  • Tag this tiddler with $:/tags/Global so the PageTurner procedure can be used in other tiddlers
  • Next, create a separate tiddler (e.g., “PG1”), containing: [object_type[Artist Books]]
    • Note that this filter does NOT include <currentTiddler>, which is automatically added as needed in the PageTurner procedure’s code
  • Lastly, where you were using your previous code, replace it with <<PageTurner PG1>>

Also, for your specific example of limiting the previous/next navigation to the current tiddler’s object-type, you could make these changes:

  • Instead of defining a global \procedure, just place this code into a tiddler tagged with $:/tags/ViewTemplate:
<$list filter="[<currentTiddler>get[object-type]]" variable=thistype>
<div style="float:right;">
   <$vars prev={{{ [all[]object-type<thistype>sort[]before<currentTiddler>] }}}>
   <$vars next={{{ [all[]object-type<thistype>sort[]after<currentTiddler>] }}}>
   <$reveal default=<<prev>> type="nomatch" text="">
   <$button tooltip=<<prev>>> {{$:/core/images/chevron-left}}
      <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>> />
      <$action-navigate $to=<<prev>>/>
   </$button>
   </$reveal>
   <$reveal default=<<next>> type="nomatch" text="">
   <$button tooltip=<<next>>> {{$:/core/images/chevron-right}}
      <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>> />
      <$action-navigate $to=<<next>>/>
   </$button>
   </$reveal>
   </$vars>
   </$vars>
</div>
</$list>

Notes:

  • The initial $list widget detects if the current tiddler has a non-blank object-type field. If it does, that field’s value is copied into the thistype variable. This filter also automatically limits the display of the content that follows to only those tiddlers that have an object-type field.
  • The calculation of prev and next then uses the <thistype> variable to find the previous/next tiddler that has the same object-type as the current tiddler.

enjoy,
-e

3 Likes

Fantastic @EricShulman . Fancy a knighthood?

If only it were in my power… :slight_smile:

Maybe this should be added to the TW documentation. It would be useful to others now and in to the future.

bobj

Indeed. Exemplary piece of wikitextmanshipTM (hereby coined by me!)

Here’s a more compact bit of coding for the object-type navigation:

\define close() <$action-sendmessage $message="tm-close-tiddler" param=<<currentTiddler>>/>

<$list filter="[<currentTiddler>get[object-type]]" variable=thistype>
<div style="float:right;">
   <$list filter="[all[]object-type<thistype>sort[]before<currentTiddler>]" variable="prev">
      <$button tooltip=<<prev>>>{{$:/core/images/chevron-left}}
         <<close>><$action-navigate $to=<<prev>>/>
      </$button>
   </$list>
   <$list filter="[all[]object-type<thistype>sort[]after<currentTiddler>]" variable="next">
      <$button tooltip=<<next>>>{{$:/core/images/chevron-right}}
         <<close>><$action-navigate $to=<<next>>/>
      </$button>
   </$list>
</div>
</$list>

Notes:

  • Define a <<close>> macro as an “abbreviation” for the tm-close-tiddler message.
  • Instead of using $vars with “filtered transclusion” syntax, use $list widgets with variable=...
  • The $list widgets also eliminate the need for separate $reveal widgets to omit the previous or next button when at the first or last tiddler in the sequence.

-e

2 Likes

@EricShulman why do I get the feeling that if I wait long enough you’ll provide a one word command to do all that :slight_smile:

Looking through your code, I realise that I’m a long way from your mastery of coding in TW. I also realised that many of the issues I face are because I do not understand how TW code works nor do I have the grasp of how to combine functions/operators/procedures/etc to achieve what I want. In other languages I code in, I do have that understanding and so coding in them is easier for me. I realise this is a time issue, I need to do more work in TW coding. However, the TW documentation does not really help, as I’ve noted before. The examples in the documentation are not real examples, they, for the most part, are trivial and are difficult to translate into a real scenario.

Anyway, I am learning off you all the time, so thank you again.

2 Likes