action-navigator doesn't work with macros

99 views
Skip to first unread message

kebi

unread,
Sep 16, 2020, 7:47:55 PM9/16/20
to TiddlyWiki
Hello guys,

I'm trying to create a shortcut to move between open tiddlers in the story view and by far this is my code:

\define next-tiddler()
<$list filter="[enlist{$:/StoryList!!list}after<currentTiddler>]">
{{!!title}}
</$list>
\end

<$navigator story="$:/
StoryList" history="$:/HistoryList">
<<next-tiddler>>
<$action-navigate $to=<<next-tiddler>> /
>
</$navigator>

The problem is that even though <<next-tiddler>> is working correctly by itself, it doesn't work when put inside the action-navigate widget.
When I try to press the keyboard shortcut to trigger the code a new tiddler named "<$list filter="[enlist{$:/StoryList!!list}after<currentTiddler>]"> {{!!title}} </$list>" is generated.

I suppose you can't use macros inside the action-navigate widget, is this correct?

Thanks in advance.

Eric Shulman

unread,
Sep 16, 2020, 10:06:46 PM9/16/20
to TiddlyWiki
The problem originates from the fact that macro output is not automatically "wikified", and it is up to the calling context to determine what to do with the macro output.  In your example, the first "<<next-tiddler>>" occurs directly in the wikitext, which results in the macro output being parsed and rendered right there.  However, the second use of <<next-tiddler>> is as a widget parameter, which does *NOT* parse the macro output, and just passes it to the widget for processing, "as-is".

One way around this is to use the <$wikify> widget, which explicitly performs a "wikification" of it's text parameter.  Thus:
<$button>
   {{$:/core/images/chevron-right}}
   <$wikify name="next" text=<
<next-tiddler>>>
      <$action-navigate to=<
<next>> />
   </$wikify>
</$button>
Note that $action-navigate needs to be contained inside a button to trigger it, and does not need the $navigator widget.

HOWEVER... for your specific use-case, there is no need to use a macro or wikify widget at all!  Instead, you can use a "filtered transclusion" to specify the $action-navigate "to" parameter value, like this:
<$button>
   {{$:/core/images/chevron-right}}
   <$action-navigate to={{{ [enlist{$:/StoryList!!list}after
<currentTiddler>] }}} />
</$button>
You could also make the button a little bit more clever and have it "wrap around" when you reach the end of the story.  Something like this:
<$button>
   {{$:/core/images/chevron-right}}
   <$action-navigate to={{{ [enlist{$:/StoryList!!list}after
<currentTiddler>] ~[enlist{$:/StoryList!!list}first[]] }}} />
</$button>
The "~[...]" filter expression is only used when the first filter expression doesn't yield a value... i.e., when there is no "after", it will use "first".

BUT... there appears to be another problem...

Upon testing this solution at http://TiddlyWiki.com, I found that the $action-navigate doesn't seem to scroll the story the way you might expect: it only scrolls far enough to leave the button you pressed visible, so if the tiddler is longer than the window height, the next tiddler doesn't actually come fully into view.

An alternative solution that bypasses the $action-navigate widget is to use the "to" parameter of the <$button> widget instead, like this:
<$button to={{{ [enlist{$:/StoryList!!list}after<currentTiddler>] ~[enlist{$:/StoryList!!list}first[]] }}}>
   {{$:/core/images/chevron-right}}
</$button>
This button DOES successfully scroll all the way to the next tiddler.  (YAY!)

Of course, you probably also want a "previous tiddler" button as well.  The code for this is similar to the above, but uses the "before" and "last" filter operators instead.  Thus, the following code shows both buttons:
\whitespace trim
<$button class="tc-btn-invisible" tooltip="previous tiddler" to={{{ [enlist{$:/StoryList!!list}before<currentTiddler>] ~[enlist{$:/StoryList!!list}last[]] }}}>
   {{$:/
core/images/chevron-left}}
</$button>
<$button class="tc-btn-invisible" tooltip="next tiddler" to={{{ [enlist{$:/StoryList!!list}after<currentTiddler>] ~[enlist{$:/StoryList!!list}first[]] }}}>
   {{$:/
core/images/chevron-right}}
</$button>
Note: I also added class="tc-btn-invisible" and a tooltip="..." to make the buttons show just their images without the surrounding button "box".

Lastly, I assume you want these buttons to appear in the tiddler toolbar (upper right corner of each tiddler) for easy access.
To do this, just place the above code into a tiddler (e.g., "GotoTiddler") and then tag that tiddler with "$:/tags/ViewToolbar".

Give it a try and let me know how it goes...

enjoy,
-e

kebi

unread,
Sep 16, 2020, 11:33:14 PM9/16/20
to TiddlyWiki
Eric thanks so much for the examples, really helpful!

The last example does exactly what I wanted!

I guess there is no way for the moment to trigger those buttons with keyboard shortcuts, am I right?
Setting them to the left/right arrow keys would make the navigation more pleasant.

Saq Imtiaz

unread,
Sep 17, 2020, 4:41:37 AM9/17/20
to TiddlyWiki
I think Eric missed the part where you mentioned creating keyboard shortcuts, which does involve using the Navigator widget. For it to work you also need to know what the "current" tiddler is, the currentTiddler variable is not defined in keyboard shortcuts since they are global.

There is an existing plugin that might meet your needs:

kebi

unread,
Sep 17, 2020, 7:44:47 AM9/17/20
to TiddlyWiki
Thanks Saq, it is exactly what I was searching for!
Reply all
Reply to author
Forward
0 new messages