How do I make toc category obey "empty" after exclusion? Also, is there a way to sort by title only if no caption exists?

183 views
Skip to first unread message

S H Chang

unread,
Sep 11, 2018, 6:29:04 PM9/11/18
to tiddl...@googlegroups.com
Hello!

I have been tweaking my table of contents. Appended the auto-collapse macro and got it to work, and my toc macro looks something like this:

<div class="tc-table-of-contents">
<
<toc-selective-single-expandable "Root" "sort[title]" exclude:"-[tag[Log]]-[field:visibility[hidden]]">>
</div>

I'm trying to get the selective feature to work, but I'm not sure if it's possible with the auto-collapse. Usually, under toc-selective-expandable, when a category has nothing nested beneath it, the arrow would be hidden, right? How could I get the arrow to hide if the category is technically empty after excluding all tiddlers tagged Log or containing the custom field visibility: hidden?

Forgive me, I'm still figuring Tiddlywiki out, so perhaps I'm asking a really easy question... I *think* I should be tweaking this line here (found in toc-unlinked-selective-expandable-body, which I copied and modified to toc-unlinked-selective-single-expandable-body):

<$list filter="[all[current]tagging[]limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>">
        <$reveal type="nomatch" state=<
<toc-state>> text=<<currentTiddler>>>

I've tried adding

!tag[Log]!field:visbility[hidden]

to the filter tag but it didn't work... and that's kinda all the ideas I have. Would really appreciate some pointers.

Many thanks in advance!!

EDIT: Oh I forgot about my second question. Is it possible to sort the toc by caption if it exists, then title? Or should I just use the list field? Thanks!!

EDIT 2: Hmmm I think I should include the entire code. Here's the selective-single-expandable macro I'm using:

\define toc-selective-single-expandable(tag,sort:"",itemClassFilter,exclude,path)
<$vars tag="""$tag$""" sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" excluded="""$exclude$ -[[$tag$]]""" path="""$path$/$tag$""">
 
<ol class="tc-toc toc-selective-expandable">
   
<$list filter="""[all[shadows+tiddlers]tag[$tag$]!has[draft.of]$sort$] -[[$tag$]] $exclude$""">
     
<$list filter="[all[current]toc-link[no]]" variable="ignore" emptyMessage=<<toc-unlinked-selective-single-expandable-body tag:"""$(tag)$""" sort:"""$(sort)$""" itemClassFilter:"""$(itemClassFilter)$""" exclude:"""$(excluded)$""" path:"""$(path)$""">>>
       
<$macrocall $name=toc-unlinked-selective-single-expandable-body tag="""$tag$""" sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" exclude=<<excluded>> path=<<path>> >
     
</$list>
    </
$list>
 
</ol>
</
$vars>
\end

\define toc-linked-selective-single-expandable-body(tag,sort:"",itemClassFilter,exclude,path)
<!-- helper function -->
<$set name="toc-state" value=<<qualify """$:/state/toc/$tag$""">>>
 
<$set name="toc-item-class" filter="""$itemClassFilter$""" emptyValue="toc-item" value="toc-item-selected">
   
<li class=<<toc-item-class>>>
   
<$link>
     
<$reveal type="nomatch" state=<<toc-state>> text=<<currentTiddler>>>
       
<$button set=<<toc-state>> setTo=<<currentTiddler>> class="tc-btn-invisible tc-popup-keep">
         
{{$:/core/images/right-arrow}}
       
</$button>
      </
$reveal>
     
<$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
       
<$button set=<<toc-state>> setTo="x-all-close" class="tc-btn-invisible tc-popup-keep">
         
{{$:/core/images/down-arrow}}
       
</$button>
      </
$reveal>
     
<<toc-caption>>
   
</$link>
    <$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
      <$macrocall $name="toc-selective-single-expandable" tag=<<currentTiddler>> sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" exclude="""$exclude$""" path="""$path$"""/
>
   
</$reveal>
    </
li>
 
</$set>
</
$set>
\end

\define toc-unlinked-selective-single-expandable-body(tag,sort:"",itemClassFilter:" ",exclude,path)
<$set name="toc-state" value=<<qualify """$:/state/toc/$tag$""">>>
 
<$set name="toc-item-class" filter="""$itemClassFilter$""" emptyValue="toc-item" value="toc-item-selected">
   
<li class=<<toc-item-class>>>
     
<$list filter="[all[current]tagging[]limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>">
       
<$reveal type="nomatch" state=<<toc-state>> text=<<currentTiddler>>>
         
<$button set=<<toc-state>> setTo=<<currentTiddler>> class="tc-btn-invisible tc-popup-keep">
           
{{$:/core/images/right-arrow}}
           
<<toc-caption>>
         
</$button>
        </
$reveal>
       
<$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
         
<$button set=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
           
{{$:/core/images/down-arrow}}
           
<<toc-caption>>
         
</$button>
        </
$reveal>
     
</$list>
      <$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
        <$macrocall $name="""toc-selective-single-expandable""" tag=<<currentTiddler>> sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" exclude="""$exclude$""" path="""$path$"""/
>
     
</$reveal>
    </
li>
 
</$set>
</
$set>
\end



S H Chang

unread,
Sep 11, 2018, 9:31:21 PM9/11/18
to TiddlyWiki
I should have scrutinised my code before posting here. There was a mistake in <<toc-linked-selective-single-expandable-body>>; it didn't have the list for "empty" children. I've also realised that it should be !tag[Log]!visibility[hidden] instead. I've added that to the macro so now it looks like this:

\define toc-linked-selective-single-expandable-body(tag,sort:"",itemClassFilter:" ",exclude,path)

<$set name="toc-state" value=<<qualify """$:/state/toc/$tag$""">>>
 
<$set name="toc-item-class" filter="""$itemClassFilter$""" emptyValue="toc-item" value="toc-item-selected" >
   
<li class=<<toc-item-class>>>

     
<$link>
         
<$list filter="[all[current]tagging[]!visibility[hidden]!tag[Log]limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>">

         
<$reveal type="nomatch" state=<<toc-state>> text=<<currentTiddler>>>
           
<$button set=<<toc-state>> setTo=<<currentTiddler>> class="tc-btn-invisible tc-popup-keep">
             
{{$:/core/images/right-arrow}}
           
</$button>
          </
$reveal>
         
<$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
           
<$button set=<<toc-state>> setTo="x-all-close" class="tc-btn-invisible tc-popup-keep">
             
{{$:/core/images/down-arrow}}
           
</$button>
          </
$reveal>

       
</$list>
        <<toc-caption>>
      </
$link>

     
<$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
       
<$macrocall $name="toc-selective-single-expandable" tag=<<currentTiddler>> sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" exclude="""$exclude$""" path="""$path$"""/>
     
</$reveal>
    </
li>
 
</$set>
</
$set>
\end

\define toc-unlinked-selective-single-expandable-body(tag,sort:"",itemClassFilter:" ",exclude,path)
<$set name="toc-state" value=<<qualify """$:/state/toc/$tag$""">>>
 
<$set name="toc-item-class" filter="""$itemClassFilter$""" emptyValue="toc-item" value="toc-item-selected">
   
<li class=<<toc-item-class>>>

     
<$list filter="[all[current]tagging[]!visibility[hidden]!tag[Log]limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>">

       
<$reveal type="nomatch" state=<<toc-state>> text=<<currentTiddler>>>
         
<$button set=<<toc-state>> setTo=<<currentTiddler>> class="tc-btn-invisible tc-popup-keep">
           
{{$:/core/images/right-arrow}}
           
<<toc-caption>>
         
</$button>
        </
$reveal>
       
<$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
         
<$button set=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
           
{{$:/core/images/down-arrow}}
           
<<toc-caption>>
         
</$button>
        </
$reveal>
     
</$list>
      <$reveal type="match" state=<<toc-state>> text=<<currentTiddler>>>
        <$macrocall $name="""toc-selective-single-expandable""" tag=<<currentTiddler>> sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" exclude="""$exclude$""" path="""$path$"""/
>
     
</$reveal>
    </
li>
 
</$set>
</
$set>
\end

\define toc-selective-single-expandable-empty-message()
<<toc-linked-selective-single-expandable-body tag:"""$(tag)$""" sort:"""$(sort)$""" itemClassFilter:"""$(itemClassFilter)$""" exclude:"""$(excluded)$""" path:"""$(path)$""">>
\end


\define toc-selective-single-expandable(tag,sort:"",itemClassFilter,exclude,path)
<$vars tag="""$tag$""" sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" excluded="""$exclude$ -[[$tag$]]""" path="""$path$/$tag$""">
 
<ol class="tc-toc toc-selective-expandable">
   
<$list filter="""[all[shadows+tiddlers]tag[$tag$]!has[draft.of]$sort$] -[[$tag$]] $exclude$""">

     
<$list filter="[all[current]toc-link[no]]" variable="ignore" emptyMessage=<<toc-selective-single-expandable-empty-message>> >
       
<$macrocall $name=toc-unlinked-selective-expandable-body tag="""$tag$""" sort="""$sort$""" itemClassFilter="""$itemClassFilter$""" exclude=<<excluded>> path=<<path>> >

     
</$list>
    </
$list>
 
</ol>
</
$vars>
\end

Hopefully it might help someone out in future.

As for the second question I have, I suppose it's not possible. What I had in mind when I posted was that the toc would sort alphabetically, but it would use the caption's value if there were one, else the title. I've decided to just use the list field for all the parents.

Mark S.

unread,
Sep 12, 2018, 1:18:12 PM9/12/18
to TiddlyWiki
It sounds like you have things mostly sorted out.

A filter like this might allow you to sort by caption or title (whichever is present):

[has[caption]get[caption]] [!has[caption]get[title]] +[sort[]]

Just remember, that if you use caption then there might be more than one tiddler that uses that caption and you can't form a standard link based on the caption name.

Good luck!
-- Mark

TonyM

unread,
Sep 12, 2018, 8:48:01 PM9/12/18
to TiddlyWiki
Nice Filter!

TonyM

unread,
Sep 12, 2018, 9:29:24 PM9/12/18
to TiddlyWiki
ps In my own filter I needed 

"[all[current]has[caption]get[caption]] [all[current]!has[caption]get[title]] +[sort[]]"


Regards
Tony

S H Chang

unread,
Sep 14, 2018, 6:46:20 AM9/14/18
to TiddlyWiki
Thank you Mark and Tony for the filter!

Mark made a really good point about having the same caption for more than one tiddler which I've forgotten about. I will keep that in mind.
Message has been deleted

The Islander

unread,
Mar 27, 2020, 12:56:27 PM3/27/20
to tiddl...@googlegroups.com
The question is where do we put this filter?
"[all[current]has[caption]get[caption]] [all[current]!has[caption]get[title]] +[sort[]]"



You can't put it in the toc macro because it complains Filter Expression Error.

You can't do something like this:
<$list filter="[all[current]has[caption]get[caption]] [all[current]!has[caption]get[title]] +[reverse[]]">
<div class="tc-table-of-contents">
<<toc-selective-expandable "TableOfContents">>
</div>
</$list>

because it doesn't do any sort.

So where would a filter like this go?

Thanks!

Mark S.

unread,
Mar 27, 2020, 1:40:08 PM3/27/20
to TiddlyWiki
Here's a toc clause using "HelloThere" as a root that may do what you want:

<<toc "HelloThere" "has[caption]get[caption]][tag[HelloThere]!has[caption]get[title]]+[sort[]">>

Notice that the "sort" clause has no opening or ending [ or ] respectively. Note that the tag[HelloThere] had to be repeated for the sub-clause. The "all[current]" would have used the name of the original tiddler all the way down, which isn't what you want.

The TOC above seems to work, but it will try to link to a tiddler with the caption as title. Since that tiddler probably doesn't exist, the link will go to a non-existent tiddler.

To get a more robust solution, you will need to either make a copy of the original TOC macro and hack it, or write your own recursive TOC style macro. You might search the forum for TOC and "recursive" since it's likely that someone, possibly me, has already written such a thing.

Or better yet, take a look at:


While there, check if Mohammad has posted any other recursive solutions.

HTH
Reply all
Reply to author
Forward
0 new messages