Conditionally appending a TOC of Sub tiddlers to a Tiddler (Or how to write Javascript Macros)

98 views
Skip to first unread message

registrierungs genervter

unread,
Apr 4, 2019, 2:56:03 PM4/4/19
to TiddlyWiki
I would like to add a TOC of Sub Tiddlers (Tiddlers tagged with this Tiddler) at the end of each tiddler.

I would like to do this automatically, but only if there are Sub Tiddlers.

Currently im doing it manually:

I have defined a macro t in a Tiddler tagged with '$:/tags/Macro':

\whitespace trim
\define t()
<hr>
Sub-Tiddlers:
<div class="tc-table-of-contents">
<$macrocall $name="toc-selective-expandable" tag=<<currentTiddler>> sort="!tag[Ignore in TOCs]sort[title]"/>
</div>
\end

And then i add <<t>> at the end of each Tiddler which has Sub Tiddlers.

I would like to do this by creating a Template Tiddler Sub Tiddlers, which contains a call to the <<t>> macro, and adding that Template Tiddler to the list field of $:/tags/ViewTemplate.

But this way the hr and the text 'Sub-Tiddlers:' always gets included, even if the result of the call to toc-selective-expandable is empty. Which i dont want.

So either

  • ideally i would like to include Sub Tiddler only if there are Sub Tiddlers. But i have no idea how to achieve this.
  • or i convert <<t>> to a javascript macro (because, if i am not wrong, if/else is not possible in normal macros like the above one).
    Then my problem for now is, how would i call the toc-selective-expandable macro from within Javascript and how would i figure out that its result is empty?
    Or, where in the code base is this macro defined?
Any hints appreciated.

S. S.

unread,
Apr 4, 2019, 5:50:55 PM4/4/19
to TiddlyWiki
Hello r.g.

The tagging operator seems to be just made for you!
Since you just need to have a list of 1, you limit the filter's output.

So you might try this in your Sub Tiddlers template:

<$list filter="[all[current]tagging[]limit[1]]">

<
<t>>
</$list>

If the list is empty, meaning there are no tiddlers tagged with the title of the current tiddler, the <<t>> macro wont show up.

Cheers.

registrierungs genervter

unread,
Apr 5, 2019, 1:16:56 AM4/5/19
to TiddlyWiki
Great! This did the trick - with a small modification. I had to set the variable parameter of the list widget to another value:

<$list filter="[all[current]tagging[]limit[1]]" variable="currentTiddlerInTheList">
<
<t>>
</$list>

This needs to be done because the default name of the variable parameter is "currentTiddler". My <<t>> macro also uses that name, expecting it to point to the tiddler where it is used. But the list widget invocation changes it to the first tiddler tagged with the current tiddler. If i set the variable to another value, then currentTiddler in the <<t>> macro will stay unchanged and it works.

Thanks for pointing me in the right direction.

---

I didnt fully understand how the list widget works. It executes its content (as a template) for each tiddler in its result list. Also, interesting that

<$list>
</$list>

and

<$list></$list>

results in two different things. In the first case it uses the linebreak as the template (which results in nothing being shown), in the second it uses a default template (which is a link pointing to the tiddler).

---

In my opinion <$for-each>...</$for-each> would be a better name for the list widget, because list is an ambigous name - are we talking about the noun a list or about the action to list something. but thats another topic.

TonyM

unread,
Apr 5, 2019, 3:27:26 AM4/5/19
to TiddlyWiki

registrierungs genervter

Give it time and I think you may not think <$for-each>...</$for-each> would be a better name for the list widget

The filters that drive the ListWidget, SetWidget and Filtered Transclusions do a great deal including having their own each[]  operators within. There is a very good reason not to call if "for each" because, because there is no single thing that you are listing "for each". In common code you may say "for each tiddler" or "for each user-field" but in filters you can combine these, including retrieving values.

You can write filters that duplicate a for-each structure but these are only a subset of what can be achieved.

List is well kept ambiguous if you ask me.

Tony

Jed Carty

unread,
Apr 5, 2019, 3:36:09 AM4/5/19
to TiddlyWiki
One thing to remember is that what the list does isn't a loop in the normal programming sense. I think it is more accurately described as list comprehension like in python, something like

output = [<template> for item in list]

rather than

forEach item in list do
  <template>

for the most part it wikitext sequential operations on data are done using recursion.

TonyM

unread,
Apr 5, 2019, 3:44:21 AM4/5/19
to TiddlyWiki

And add to the above a filter can be of the form

"FilterList1 ~FilterList2 ~FilterList3"

That is if the first list has no members the second will be used else the third. In this case the "for each" changes with each filter.

and much more.
Reply all
Reply to author
Forward
0 new messages