mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-10-11 18:41:43 +00:00
Docs only Groupedlists examples (#9954)
* Add GroupedLists examples Document grouped lists with runnable test cases over a shared bibliography sample. * Cover plain grouping, search, tabs by first character, both combined, and grouping on one field while searching another * Name the grouped field in one procedure, so the grouping changes in one line * Import it with import-compound, and list the examples by tag so a new one needs no page edit * Rewrite the opening paragraph, which described only the sidebar tabs * Replace GroupedLists code dumps with examples Turn the two sidebar tabs the page describes into runnable test cases, and tighten how the examples handle an empty result. * Give each new example its own dummy payload, and point the page at the live tabs instead of quoting core source * Carry the values through the filter from the start, so an All tab with no matches yields nothing rather than the literal All * Use the list-empty widget * use tc-tiny-gap instead of -left -right
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
created: 20150106180000000
|
||||
modified: 20241204085601176
|
||||
list: GroupedLists/Example/TypesTab GroupedLists/Example/ByField GroupedLists/Example/WithSearch GroupedLists/Example/WithTabs GroupedLists/Example/TabsWithSearch GroupedLists/Example/SearchAnotherField GroupedLists/Example/RecentTab
|
||||
modified: 20260729194941115
|
||||
tags: ListWidget Lists
|
||||
title: GroupedLists
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
The following sidebar tabs give examples of grouped lists created by nesting.
|
||||
A grouped list is made by nesting one list inside another. The outer list collects each distinct value of a field, and the inner list finds the tiddlers holding that value.
|
||||
|
||||
!! [[Types Tab|$:/core/ui/MoreSideBar/Types]]
|
||||
TiddlyWiki uses the pattern in two of its sidebar tabs. The [[Types Tab|$:/core/ui/MoreSideBar/Types]] groups tiddlers by their `type` field, and sits under ''More'' in the sidebar. The [[Recent Tab|$:/core/ui/SideBar/Recent]] groups them by day, through the <<.mlink timeline>> macro. Both are reproduced as examples below.
|
||||
|
||||
For the "Types Tab", the outer list filter as shown below selects each discrete value found in the `type` field. The inner list filter selects all the (non-system) tiddlers with that type.
|
||||
!! Interactive Examples
|
||||
|
||||
<<tw-code "$:/core/ui/MoreSideBar/Types">>
|
||||
Each example is a runnable test case carrying its own sample data. Where a field is grouped on, it is named once in <<.def groupField>>, so the grouping can be changed without touching anything else.
|
||||
|
||||
!! [[Recent Tab|$:/core/ui/SideBar/Recent]]
|
||||
<<<
|
||||
<$list filter="[tag[GroupedLists]]">
|
||||
|
||||
The list in the "Recent Tab" is generated using the <<.mlink timeline>> macro. Here, the outer list filter selects each discrete day found in the `modified` field, while the inner list filter selects all the tiddlers dated the same day in the `modified` field.
|
||||
|
||||
<<tw-code "$:/core/macros/timeline">>
|
||||
; <$link/>
|
||||
: {{!!description}}
|
||||
</$list>
|
||||
<<<
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
code-body: yes
|
||||
created: 20260728220000000
|
||||
description: Bibliography sample data shared by the GroupedLists examples
|
||||
modified: 20260729180306417
|
||||
title: GroupedLists/Bibliography
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: 3DWiki2011
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: 3D Wiki Collective
|
||||
bibtex-title: Spatial Notes in Three Dimensions
|
||||
bibtex-date: 2011
|
||||
|
||||
+
|
||||
title: 3rdWave2014
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: 3rd Wave Research Group
|
||||
bibtex-title: Note Taking After the Desktop
|
||||
bibtex-date: 2014
|
||||
|
||||
+
|
||||
title: Aronsson2002
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Aronsson, Lars
|
||||
bibtex-title: Operation of a Large Scale, General Purpose Wiki Website
|
||||
bibtex-date: 2002
|
||||
|
||||
+
|
||||
title: Atkinson2016
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Atkinson, Paul
|
||||
bibtex-title: Digital ethnographies
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Bakshi2016
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Bakshi, Divya
|
||||
bibtex-title: Hypertext and Feminisms: Voicing the Silence
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Barker2008
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Barker, Philip
|
||||
bibtex-title: Using wikis and weblogs to enhance human performance
|
||||
bibtex-date: 2008
|
||||
|
||||
+
|
||||
title: Barker2008a
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Barker, Philip
|
||||
bibtex-title: Using Wikis for Knowledge Management
|
||||
bibtex-date: 2008
|
||||
|
||||
+
|
||||
title: Bernstein2016
|
||||
bibtex-entry-type: Book
|
||||
bibtex-author: Bernstein, Mark
|
||||
bibtex-title: Getting Started With Hypertext Narrative
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Dalgaard2001
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Dalgaard, Rune
|
||||
bibtex-title: Hypertext and the Scholarly Archive: Intertexts, Paratexts and Metatexts at Work
|
||||
bibtex-date: 2001
|
||||
|
||||
+
|
||||
title: Dickinson2008
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Dickinson, Anne
|
||||
bibtex-title: Is the e-Learning Object Create Interactive Accessible e-Learning Accessible?
|
||||
bibtex-date: 2008
|
||||
|
||||
+
|
||||
title: Finnemann2016
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Finnemann, Niels Ole
|
||||
bibtex-title: Hypertext configurations: Genres in networked digital media
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Frumkin2005
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Frumkin, Jeremy
|
||||
bibtex-title: The wiki and the digital library
|
||||
bibtex-date: 2005
|
||||
|
||||
+
|
||||
title: Maier2016
|
||||
bibtex-entry-type: InCollection
|
||||
bibtex-author: Maier, Carmen Daniela
|
||||
bibtex-title: Hypertext and Hypermedia
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Morris2007
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Morris, Joseph C.
|
||||
bibtex-title: DistriWiki: a distributed peer-to-peer wiki network
|
||||
bibtex-date: 2007
|
||||
|
||||
+
|
||||
title: Ruston2004
|
||||
bibtex-entry-type: Book
|
||||
bibtex-author: Ruston, Jeremy
|
||||
bibtex-title: TiddlyWiki
|
||||
bibtex-date: 2004
|
||||
|
||||
+
|
||||
title: Rutherford2009
|
||||
bibtex-entry-type: Thesis
|
||||
bibtex-author: Rutherford, Jayne
|
||||
bibtex-title: Graphical Input for TiddlyWiki
|
||||
bibtex-date: 2009
|
||||
|
||||
+
|
||||
title: Schaffert2006
|
||||
bibtex-entry-type: InProceedings
|
||||
bibtex-author: Schaffert, Sebastian
|
||||
bibtex-title: IkeWiki: A semantic wiki for collaborative knowledge management
|
||||
bibtex-date: 2006
|
||||
|
||||
+
|
||||
title: Shang2016
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Shang, Hui-Fang
|
||||
bibtex-title: Online metacognitive strategies, hypermedia annotations, and motivation on hypertext comprehension
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Shang2016a
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Shang, Hui-Fang
|
||||
bibtex-title: Exploring demographic and motivational factors associated with hypertext reading by English as a foreign language students
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Skiba2005
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Skiba, Diane J.
|
||||
bibtex-title: Do your students wiki?
|
||||
bibtex-date: 2005
|
||||
|
||||
+
|
||||
title: Trentin2009
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Trentin, Guglielmo
|
||||
bibtex-title: Using a wiki to evaluate individual contribution to a collaborative learning project
|
||||
bibtex-date: 2009
|
||||
|
||||
+
|
||||
title: Truman2016
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Truman, Gail
|
||||
bibtex-title: Web Archiving Environmental Scan
|
||||
bibtex-date: 2016
|
||||
|
||||
+
|
||||
title: Wagner2004
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Wagner, Christian
|
||||
bibtex-title: Wiki: A technology for conversational knowledge management and group collaboration
|
||||
bibtex-date: 2004
|
||||
|
||||
+
|
||||
title: Wilson2007
|
||||
bibtex-entry-type: Article
|
||||
bibtex-author: Wilson, Tom D.
|
||||
bibtex-title: Review of TiddlyWiki 2.1.3
|
||||
bibtex-date: 2007
|
||||
@@ -0,0 +1,45 @@
|
||||
created: 20260728220100000
|
||||
description: Group tiddlers by the value of a field chosen in one place
|
||||
import-compound: [[GroupedLists/Bibliography]]
|
||||
modified: 20260729185240642
|
||||
tags: $:/tags/wiki-test-spec GroupedLists
|
||||
title: GroupedLists/Example/ByField
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
`groupField` names the field to group by. It is the only line to change when you want a different grouping.
|
||||
|
||||
Two nested lists do the work:
|
||||
|
||||
* `f.valuesAll` collects each distinct value of that field, sorted
|
||||
* `f.tiddlersFor` returns the tiddlers holding one of those values
|
||||
|
||||
This test case imports 24 bibliography tiddlers from the `GroupedLists/Bibliography` payload. They came from a ~BibTeX import, so the field is `bibtex-author` rather than `author`.
|
||||
|
||||
Barker and Shang each published twice, so their groups list two titles. Set `groupField` to `bibtex-entry-type` to regroup the same data by publication type.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- bibtex-author<value> would make the field name the operator, which cannot be a variable, so f.tiddlersFor compares via get<groupField> -->
|
||||
|
||||
<!-- No trailing whitespace after the field name: it becomes part of the name and the list silently renders nothing -->
|
||||
\procedure groupField() bibtex-author
|
||||
|
||||
\function f.valuesAll() [all[tiddlers]!is[system]has<groupField>each<groupField>get<groupField>sort[]]
|
||||
|
||||
\function f.tiddlersFor(value) [!is[system]has<groupField>] :filter[get<groupField>match<value>] +[sort[title]]
|
||||
|
||||
<$list filter="[f.valuesAll[]]" variable="_value">
|
||||
<div class="tc-menu-list-item">
|
||||
<<_value>>
|
||||
|
||||
<$list filter="[f.tiddlersFor<_value>]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<$link><$text text={{{ [<currentTiddler>get[bibtex-title]] :else[<currentTiddler>] }}}/></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
</$list>
|
||||
@@ -0,0 +1,51 @@
|
||||
title: GroupedLists/Example/RecentTab
|
||||
created: 20260729190100000
|
||||
modified: 20260729190100000
|
||||
description: Group tiddlers by day with the timeline macro, as the sidebar Recent tab does
|
||||
tags: [[$:/tags/wiki-test-spec]] GroupedLists
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
The `timeline` macro groups tiddlers by the day found in a date field. The ''Recent'' tab in the sidebar is a single call to it, which is all the Output below is.
|
||||
|
||||
The nesting happens inside the macro:
|
||||
|
||||
* the outer filter uses `eachday` to yield one tiddler per distinct day
|
||||
* the inner filter uses `sameday` to collect every tiddler falling on that day
|
||||
* `dateField` chooses which field to read, so the same macro groups by `created` just as well as by `modified`
|
||||
|
||||
The five dummy payload tiddlers below carry hand set `modified` dates. Nothing else here has a date field, so they are exactly what the timeline finds.
|
||||
|
||||
Pass `format` to change how each day is headed, and `limit` to cap how many tiddlers are considered.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<$transclude $variable="timeline" format="DDth MMM YYYY"/>
|
||||
+
|
||||
title: Alpha
|
||||
modified: 20260103120000000
|
||||
|
||||
Modified on the third, later in the day.
|
||||
+
|
||||
title: Beta
|
||||
modified: 20260103100000000
|
||||
|
||||
Modified on the third, earlier in the day.
|
||||
+
|
||||
title: Gamma
|
||||
modified: 20260102120000000
|
||||
|
||||
Modified on the second, later in the day.
|
||||
+
|
||||
title: Delta
|
||||
modified: 20260102100000000
|
||||
|
||||
Modified on the second, earlier in the day.
|
||||
+
|
||||
title: Epsilon
|
||||
modified: 20260101120000000
|
||||
|
||||
Modified on the first.
|
||||
@@ -0,0 +1,116 @@
|
||||
created: 20260728224000000
|
||||
description: Group by one field while the search box filters on another
|
||||
import-compound: [[GroupedLists/Bibliography]]
|
||||
modified: 20260729190424885
|
||||
tags: $:/tags/wiki-test-spec GroupedLists
|
||||
title: GroupedLists/Example/SearchAnotherField
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
`searchField` names the field the search box looks at, which no longer has to be the field the list groups by.
|
||||
|
||||
Three definitions carry the split:
|
||||
|
||||
* `groupField` is `bibtex-entry-type`, so the groups and the tabs are publication types
|
||||
* `searchField` is `bibtex-author`, so typing still matches people
|
||||
* `f.tiddlersMatching` narrows the tiddlers first, and the groups are derived from whatever survives
|
||||
|
||||
Because the groups are computed after the search, a whole group disappears once none of its entries match. The tab strip is still built from the unfiltered data, so the tabs themselves stay put.
|
||||
|
||||
This test case carries the same `_TabButton` and `_TabContent` payload tiddlers as the previous example.
|
||||
|
||||
Type `bar` to leave only ''InProceedings'', holding Barker's two papers. The other tabs drop to zero and show the `emptyMessage` of the list.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- Filter operator suffixes cannot be variables, so search:<searchField> is impossible.
|
||||
f.tiddlersMatching searches the extracted value as a title, which works whichever field it came from. -->
|
||||
|
||||
<!-- No trailing whitespace after the field name: it becomes part of the name and the list silently renders nothing -->
|
||||
\procedure groupField() bibtex-entry-type
|
||||
|
||||
\procedure searchField() bibtex-author
|
||||
|
||||
\procedure searchLabel() Author
|
||||
|
||||
\function f.valuesAll() [all[tiddlers]!is[system]has<groupField>each<groupField>get<groupField>sort[]]
|
||||
|
||||
\function f.tiddlersMatching() [all[tiddlers]!is[system]has<groupField>] :filter[get<searchField>search:title{$:/temp/GroupedLists/search-other}]
|
||||
|
||||
\function f.valuesFound() [f.tiddlersMatching[]each<groupField>get<groupField>sort[]]
|
||||
|
||||
\function f.letters() [f.valuesAll[]] :map[uppercase[]split[]first[]] +[unique[]sort[]]
|
||||
|
||||
\function f.valuesFor(letter) [f.valuesFound[]] :filter[uppercase[]split[]first[]match<letter>]
|
||||
|
||||
\function f.valuesShown(letter) [f.valuesFound[]] :filter[<letter>match[All]] :else[f.valuesFor<letter>]
|
||||
|
||||
\function f.tiddlersFor(value) [f.tiddlersMatching[]] :filter[get<groupField>match<value>] +[sort[title]]
|
||||
|
||||
<!-- The inline style below is only for this self-contained example. For production, define styles in a tiddler tagged $:/tags/Stylesheet instead. -->
|
||||
<style>.demo-group-filter { margin-bottom: 1em; }</style>
|
||||
|
||||
<$macrocall
|
||||
$name="tabs"
|
||||
tabsList="[[All]] [f.letters[]]"
|
||||
default="All"
|
||||
state="$:/state/GroupedLists/tab-other"
|
||||
buttonTemplate="_TabButton"
|
||||
template="_TabContent"
|
||||
/>
|
||||
+
|
||||
title: _TabButton
|
||||
code-body: yes
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<$text text=<<currentTab>>/><span class="tc-tiny-gap-left">(<$count filter="[f.valuesShown<currentTab>]"/>)</span>
|
||||
+
|
||||
title: _TabContent
|
||||
code-body: yes
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- tm-focus-selector takes the first match in the document, so .tc-search input would hit the sidebar search. -->
|
||||
|
||||
<div class="tc-search demo-group-filter">
|
||||
<label>
|
||||
<<searchLabel>>:<$edit-text
|
||||
tiddler="$:/temp/GroupedLists/search-other"
|
||||
tag="input"
|
||||
type="search"
|
||||
default=""
|
||||
placeholder={{{ [[Filter by ]addsuffix<searchLabel>] }}}
|
||||
class="tc-tiny-gap"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<%if [[$:/temp/GroupedLists/search-other]get[text]minlength[1]] %>
|
||||
<$button
|
||||
class="tc-btn-invisible"
|
||||
tooltip="Clear the filter"
|
||||
aria-label="Clear the filter"
|
||||
>
|
||||
<$action-deletetiddler $tiddler="$:/temp/GroupedLists/search-other"/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=".demo-group-filter input"/>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
<%endif%>
|
||||
</div>
|
||||
<$list filter="[f.valuesShown<currentTab>]" variable="_value">
|
||||
<$list-empty>
|
||||
//No matches//
|
||||
</$list-empty>
|
||||
<div class="tc-menu-list-item">
|
||||
<<_value>>
|
||||
|
||||
<$list filter="[f.tiddlersFor<_value>]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<$link><$text text={{{ [<currentTiddler>get[bibtex-title]] :else[<currentTiddler>] }}}/></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
</$list>
|
||||
@@ -0,0 +1,111 @@
|
||||
created: 20260728220400000
|
||||
description: Combine the tab strip with a search box inside the tab panel
|
||||
import-compound: [[GroupedLists/Bibliography]]
|
||||
modified: 20260729190424885
|
||||
tags: $:/tags/wiki-test-spec GroupedLists
|
||||
title: GroupedLists/Example/TabsWithSearch
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
`_TabContent` holds the search box as well as the list, so the search sits inside the panel and filters within the selected tab.
|
||||
|
||||
Which values each definition reads is the whole design:
|
||||
|
||||
* `f.letters` reads the //unfiltered// values, so tabs never disappear while you type and the selected tab cannot be stranded on an empty panel
|
||||
* `f.valuesShown` reads the //filtered// values, so the counts follow the search and a tab showing zero tells you not to look there
|
||||
|
||||
This test case carries the same `_TabButton` and `_TabContent` payload tiddlers as the previous example, with the search box added to the panel.
|
||||
|
||||
The input is a sibling of the list rather than a child of anything that recomputes, which is what keeps the cursor in the box while you type.
|
||||
|
||||
Type `ba` and watch the counts change. Any tab whose count falls to zero shows the `emptyMessage` of the list instead of nothing at all.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- Filter operator suffixes cannot be variables, so search:<groupField> and bibtex-author<value> are impossible.
|
||||
f.valuesFound searches the collected values as titles, f.tiddlersFor compares via get<groupField>. -->
|
||||
|
||||
<!-- No trailing whitespace after the field name: it becomes part of the name and the list silently renders nothing -->
|
||||
\procedure groupField() bibtex-author
|
||||
|
||||
\procedure groupLabel() Author
|
||||
|
||||
\function f.valuesAll() [all[tiddlers]!is[system]has<groupField>each<groupField>get<groupField>sort[]]
|
||||
|
||||
\function f.valuesFound() [f.valuesAll[]] :filter[search:title{$:/temp/GroupedLists/search}]
|
||||
|
||||
\function f.letters() [f.valuesAll[]] :map[uppercase[]split[]first[]] +[unique[]sort[]]
|
||||
|
||||
\function f.valuesFor(letter) [f.valuesFound[]] :filter[uppercase[]split[]first[]match<letter>]
|
||||
|
||||
\function f.valuesShown(letter) [f.valuesFound[]] :filter[<letter>match[All]] :else[f.valuesFor<letter>]
|
||||
|
||||
\function f.tiddlersFor(value) [!is[system]has<groupField>] :filter[get<groupField>match<value>] +[sort[title]]
|
||||
|
||||
<!-- The inline style below is only for this self-contained example. For production, define styles in a tiddler tagged $:/tags/Stylesheet instead. -->
|
||||
<style>.demo-group-filter { margin-bottom: 1em; }</style>
|
||||
|
||||
<$macrocall
|
||||
$name="tabs"
|
||||
tabsList="[[All]] [f.letters[]]"
|
||||
default="All"
|
||||
state="$:/state/GroupedLists/tab-search"
|
||||
buttonTemplate="_TabButton"
|
||||
template="_TabContent"
|
||||
/>
|
||||
+
|
||||
title: _TabButton
|
||||
code-body: yes
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<$text text=<<currentTab>>/><span class="tc-tiny-gap-left">(<$count filter="[f.valuesShown<currentTab>]"/>)</span>
|
||||
+
|
||||
title: _TabContent
|
||||
code-body: yes
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- tm-focus-selector takes the first match in the document, so .tc-search input would hit the sidebar search. -->
|
||||
|
||||
<div class="tc-search demo-group-filter">
|
||||
<label>
|
||||
<<groupLabel>>:<$edit-text
|
||||
tiddler="$:/temp/GroupedLists/search"
|
||||
tag="input"
|
||||
type="search"
|
||||
default=""
|
||||
placeholder={{{ [[Filter by ]addsuffix<groupLabel>] }}}
|
||||
class="tc-tiny-gap"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<%if [[$:/temp/GroupedLists/search]get[text]minlength[1]] %>
|
||||
<$button
|
||||
class="tc-btn-invisible"
|
||||
tooltip="Clear the filter"
|
||||
aria-label="Clear the filter"
|
||||
>
|
||||
<$action-deletetiddler $tiddler="$:/temp/GroupedLists/search"/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=".demo-group-filter input"/>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
<%endif%>
|
||||
</div>
|
||||
<$list filter="[f.valuesShown<currentTab>]" variable="_value">
|
||||
<$list-empty>
|
||||
//No matches//
|
||||
</$list-empty>
|
||||
<div class="tc-menu-list-item">
|
||||
<<_value>>
|
||||
|
||||
<$list filter="[f.tiddlersFor<_value>]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<$link><$text text={{{ [<currentTiddler>get[bibtex-title]] :else[<currentTiddler>] }}}/></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
</$list>
|
||||
@@ -0,0 +1,60 @@
|
||||
title: GroupedLists/Example/TypesTab
|
||||
created: 20260729190000000
|
||||
modified: 20260729190000000
|
||||
description: Group tiddlers by their type, as the sidebar Types tab does
|
||||
tags: [[$:/tags/wiki-test-spec]] GroupedLists
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
`$:/core/Filters/TypedTiddlers` collects one tiddler per distinct type, and the inner list then finds every tiddler sharing that type.
|
||||
|
||||
The two lists do different jobs:
|
||||
|
||||
* the outer filter ends in `each[type]`, so it yields one representative tiddler per type rather than every tiddler
|
||||
* the inner filter reads `{!!type}` from that representative, so `currentTiddler` is what carries the type from the outer list to the inner one
|
||||
|
||||
This is the code behind the ''Types'' tab in the sidebar, under ''More''. Open that tab to see it running over a real wiki.
|
||||
|
||||
The five dummy payload tiddlers below are the only ones here with a `type` field, so they are exactly what the list finds.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<$list filter={{$:/core/Filters/TypedTiddlers!!filter}}>
|
||||
<div class="tc-menu-list-item">
|
||||
<$view field="type"/>
|
||||
|
||||
<$list filter="[type{!!type}!is[system]sort[title]]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<$link to={{!!title}}><$view field="title"/></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
</$list>
|
||||
+
|
||||
title: Alpha
|
||||
type: image/svg+xml
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><circle cx="8" cy="8" r="7"/></svg>
|
||||
+
|
||||
title: Beta
|
||||
type: image/svg+xml
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect x="1" y="1" width="14" height="14"/></svg>
|
||||
+
|
||||
title: Gamma
|
||||
type: text/plain
|
||||
|
||||
A plain text sample.
|
||||
+
|
||||
title: Delta
|
||||
type: text/plain
|
||||
|
||||
Another plain text sample.
|
||||
+
|
||||
title: Epsilon
|
||||
type: application/json
|
||||
|
||||
{"sample": true}
|
||||
@@ -0,0 +1,82 @@
|
||||
created: 20260728220200000
|
||||
description: Narrow a grouped list with a search box
|
||||
import-compound: [[GroupedLists/Bibliography]]
|
||||
modified: 20260729185240642
|
||||
tags: $:/tags/wiki-test-spec GroupedLists
|
||||
title: GroupedLists/Example/WithSearch
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
`search:title` filters the values collected by `f.valuesAll`, so the grouped list narrows while you type without the tiddlers themselves being searched.
|
||||
|
||||
Two definitions are added to the plain grouped list:
|
||||
|
||||
* `groupLabel` is the human readable name shown beside the input
|
||||
* `f.valuesFound` applies the search to the collected values
|
||||
|
||||
An empty box is a no operation, so the whole list comes back. The clear button appears only once there is something to clear, and puts the cursor back in the input.
|
||||
|
||||
Type `ann` to match Dickinson and Finnemann, `wi` to match several at once, or `zzz` to fall through to the `emptyMessage` of the outer list.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- Filter operator suffixes cannot be variables, so search:<groupField> and bibtex-author<value> are impossible.
|
||||
f.valuesFound searches the collected values as titles, f.tiddlersFor compares via get<groupField>. -->
|
||||
|
||||
<!-- tm-focus-selector takes the first match in the document, so .tc-search input would hit the sidebar search. -->
|
||||
|
||||
<!-- No trailing whitespace after the field name: it becomes part of the name and the list silently renders nothing -->
|
||||
\procedure groupField() bibtex-author
|
||||
|
||||
\procedure groupLabel() Author
|
||||
|
||||
\function f.valuesAll() [all[tiddlers]!is[system]has<groupField>each<groupField>get<groupField>sort[]]
|
||||
|
||||
\function f.valuesFound() [f.valuesAll[]] :filter[search:title{$:/temp/GroupedLists/search}]
|
||||
|
||||
\function f.tiddlersFor(value) [!is[system]has<groupField>] :filter[get<groupField>match<value>] +[sort[title]]
|
||||
|
||||
<!-- The inline style below is only for this self-contained example. For production, define styles in a tiddler tagged $:/tags/Stylesheet instead. -->
|
||||
<style>.demo-group-filter { margin-bottom: 1em; }</style>
|
||||
|
||||
<div class="tc-search demo-group-filter">
|
||||
<label>
|
||||
<<groupLabel>>:<$edit-text
|
||||
tiddler="$:/temp/GroupedLists/search"
|
||||
tag="input"
|
||||
type="search"
|
||||
default=""
|
||||
placeholder={{{ [[Filter by ]addsuffix<groupLabel>] }}}
|
||||
class="tc-tiny-gap"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<%if [[$:/temp/GroupedLists/search]get[text]minlength[1]] %>
|
||||
<$button
|
||||
class="tc-btn-invisible"
|
||||
tooltip="Clear the filter"
|
||||
aria-label="Clear the filter"
|
||||
>
|
||||
<$action-deletetiddler $tiddler="$:/temp/GroupedLists/search"/>
|
||||
<$action-sendmessage $message="tm-focus-selector" $param=".demo-group-filter input"/>
|
||||
{{$:/core/images/close-button}}
|
||||
</$button>
|
||||
<%endif%>
|
||||
</div>
|
||||
<$list filter="[f.valuesFound[]]" variable="_value">
|
||||
<$list-empty>
|
||||
//No matches//
|
||||
</$list-empty>
|
||||
<div class="tc-menu-list-item">
|
||||
<<_value>>
|
||||
|
||||
<$list filter="[f.tiddlersFor<_value>]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<$link><$text text={{{ [<currentTiddler>get[bibtex-title]] :else[<currentTiddler>] }}}/></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
</$list>
|
||||
@@ -0,0 +1,76 @@
|
||||
created: 20260728220300000
|
||||
description: Bucket the groups into tabs by first character, with a count per tab
|
||||
import-compound: [[GroupedLists/Bibliography]]
|
||||
modified: 20260729190424885
|
||||
tags: $:/tags/wiki-test-spec GroupedLists
|
||||
title: GroupedLists/Example/WithTabs
|
||||
type: text/vnd.tiddlywiki-multiple
|
||||
|
||||
title: Narrative
|
||||
|
||||
The `tabs` macro takes its tab list from a filter, so here the tabs come out of the data: one per distinct first character, plus an ''All'' tab.
|
||||
|
||||
Three definitions feed it:
|
||||
|
||||
* `f.letters` collects the distinct first characters
|
||||
* `f.valuesFor` selects the groups filed under one character
|
||||
* `f.valuesShown` returns everything for ''All'', one character otherwise
|
||||
|
||||
This test case carries two payload tiddlers, `_TabButton` and `_TabContent`, because the `tabs` macro transcludes its caption and its panel by tiddler title and cannot take inline wikitext.
|
||||
|
||||
Matching is case insensitive, so `de Vries` and `De Vries` would share a tab. A character that is not a letter gets its own tab, which is why the sample data produces a `3` tab. Each caption carries the number of groups behind it, so no tab is a dead end.
|
||||
+
|
||||
title: Output
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<!-- bibtex-author<value> would make the field name the operator, which cannot be a variable, so f.tiddlersFor compares via get<groupField> -->
|
||||
|
||||
<!-- No trailing whitespace after the field name: it becomes part of the name and the list silently renders nothing -->
|
||||
\procedure groupField() bibtex-author
|
||||
|
||||
\function f.valuesAll() [all[tiddlers]!is[system]has<groupField>each<groupField>get<groupField>sort[]]
|
||||
|
||||
\function f.letters() [f.valuesAll[]] :map[uppercase[]split[]first[]] +[unique[]sort[]]
|
||||
|
||||
\function f.valuesFor(letter) [f.valuesAll[]] :filter[uppercase[]split[]first[]match<letter>]
|
||||
|
||||
\function f.valuesShown(letter) [f.valuesAll[]] :filter[<letter>match[All]] :else[f.valuesFor<letter>]
|
||||
|
||||
\function f.tiddlersFor(value) [!is[system]has<groupField>] :filter[get<groupField>match<value>] +[sort[title]]
|
||||
|
||||
<$macrocall
|
||||
$name="tabs"
|
||||
tabsList="[[All]] [f.letters[]]"
|
||||
default="All"
|
||||
state="$:/state/GroupedLists/tab"
|
||||
buttonTemplate="_TabButton"
|
||||
template="_TabContent"
|
||||
/>
|
||||
+
|
||||
title: _TabButton
|
||||
code-body: yes
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<$text text=<<currentTab>>/><span class="tc-tiny-gap-left">(<$count filter="[f.valuesShown<currentTab>]"/>)</span>
|
||||
+
|
||||
title: _TabContent
|
||||
code-body: yes
|
||||
|
||||
\whitespace trim
|
||||
|
||||
<$list filter="[f.valuesShown<currentTab>]" variable="_value">
|
||||
<$list-empty>
|
||||
//No matches//
|
||||
</$list-empty>
|
||||
<div class="tc-menu-list-item">
|
||||
<<_value>>
|
||||
|
||||
<$list filter="[f.tiddlersFor<_value>]">
|
||||
<div class="tc-menu-list-subitem">
|
||||
<$link><$text text={{{ [<currentTiddler>get[bibtex-title]] :else[<currentTiddler>] }}}/></$link>
|
||||
</div>
|
||||
</$list>
|
||||
</div>
|
||||
</$list>
|
||||
Reference in New Issue
Block a user