In TiddlyWiki, I have often wanted to take programmatic control of the HTML <details> element. With the advent of custom widgets since 5.3.x, I’ve been thinking about trying to do that. This then, is my first pancake – $details.2
\widget $details.2(hdr-text:"Untitled", class:"")
\procedure actions()
<$let the-state={{{ [<state>get[text]] }}}>
<<logger actions self>>
<$if value=<<the-state>> match=open>
<$action-setfield $tiddler=<<state>> $value=closed/>
</$if><$else>
<$action-setfield $tiddler=<<state>> $value=open/>
</$else>
</$let>
\end actions
<$qualify name=state title={{{ [[$:/state/disclosure/details.2/]addsuffix<hdr-text>] }}}> <<logger 1 2>>
<$eventcatcher selector=".bk-details-hdr[data-state=closed], .bk-details-hdr[data-state=open]" $click=<<actions>> stopPropogation=always>
<div class={{{ [<class>addsuffix[ bk-details other-class]] }}}>
<$reveal state=<<state>> type=match text="closed" default="closed">
<div class="bk-details-hdr" data-state=closed><<hdr-text>></div>
</$reveal>
<$reveal state=<<state>> type=match text="open">
<div class="bk-details-hdr open" data-state=open><<hdr-text>></div>
<div class="bk-details-content">
<$slot $name="ts-raw"/>
</div>
</$reveal>
</div>
</$eventcatcher>
</$qualify>
<style>
.bk-details-hdr {
display: list-item;
}
.bk-details-hdr[data-state=closed] {
list-style-type: disclosure-closed;
}
.bk-details-hdr[data-state=open]{
list-style-type: disclosure-open;
}
</style>
\end
Call it with…
<$details.2 hdr-text="The header" class="d1">
This is the content
</$details.2>
<$details.2 hdr-text="Another header" class="d2">
This is some other content
</$details.2>
You may notice…
-
It’s completely self-contained. Everything it needs is buried inside the $details.2 widget, even its basic styling (you can, of course, modify the names to suit your own wiki’s namespacing).
-
It uses $eventcatcher to handle click events.
-
It uses all 5.3-newness – \widget and \procedure
I used the condition plugin too which some may want to rewrite to use $reveal.
Now, about that mysterious not-a-bug in the title…
DO NOT EVER write an $eventcatcher block starting like this… 
<$eventcatcher $selector=".bk-details-hdr[data-state=closed], .bk-details-hdr[data-state=open]" $click=<<actions>> blah blah blah>
The eagle-eyed (@saqimtiaz ?) will have spotted the problem already. The reason I bring this up is, even though that’s a really silly (and once you’ve seen it, quite obvious) typo, the thing actually worked – it actually trapped clicks! Except …
– there were no dom-* variables passed into the event handler.
That’s an hour of my life I won’t get back! 
@saqimtiaz Comments?
For those struggling to see the problem: $selector → selector
3 Likes
@CodaCoder I had a go at using custom widgets to handle the details tag earlier but never polished it enough to share. It is interesting to see how you have addressed this, although I do not follow all of the reasoning (yet).
- My solution also allows a tiddler name or variable to be give as the contents of the details widget
- I do not use any third party solutions
- I only use a class for apperance not visibility.
I can share here or wait untilI I publish.
Of course…
<$details.2 hdr-text={{!!my-field}}>
{{some-tiddler}}
</$details.2>
<$.details content="this info"/>
<$.details tiddler=some-tiddler/>
<$.details>
{{some-tiddler}}
/>
All additional parameters such as class and style are passed through to the html details tag, including open
<$.details content="this info" open/>
Of course this only sets the initial state. But the use of a state tiddler will b e back in soon.
Here is my work in progress;
\widget $.details()
<$parameters content tiddler summary="Details" hr-details-class="hr-details" $params=params >
<$genesis $type="details"
$names="[<params>jsonindexes[]]"
$values="[<params>jsonindexes[]] :map[<params>jsonget<currentTiddler>]"
>
<summary><<summary>></summary>
<$transclude $variable=content $mode=block/>
<$slot $name="ts-raw"/>
<$transclude tiddler=<<tiddler>> mode=block/>
<$button tag=hr tooltip={{{ [[Bottom of ]addsuffix<summary>] }}} class=<<hr-details-class>>/>
</$genesis>
</$parameters>
\end $.details
Perhaps I wasn’t clear in my OP…
My “issues” with the HTML <details> element…
-
open is a boolean attribute. This means it does not support a value. For example, if you were to use open=false the browser would (damn well should) OPEN the details element. The mere presence of open means open (disclose) the content. Its absence means “closed”.
-
I want other things to happen when the header is clicked, right-clicked, shift-clicked etc, etc. Admittedly, I could just wrap <details> in $eventcatcher but if I’m going to do that, then why not use spans and divs, or anything to create the structure? Why be tied to the browser’s idea of what I “need”? Which is what I’ve done. And now I don’t need that pesky boolean attribute to contend with.
2.1. I’ve never managed yet to handle boolean attributes in TW. Perhaps there is a way, but I don’t know how.
- The formal structure displayed in this one example is merely a design choice. I could easily have tied together a header and content section from without the hosting outer div. The
<<tabs>> macro makes the same choice – notionally speaking, multiple <summary> (actually <button>) elements sitting side by side (or head to toe).
I always wanted a tabs macro that didn’t need a set of tiddlers to provide the tab content. Now I have what I need (with a little more CSS).
Anyway, it’s all good fun. I’m loving 5.3 
You were clear;
- The state tiddler was in my code and I removed it durring devlopment
1.2 I designed it so the passive version “also” works
1.3 being able to start it open or closed suits 90% of my use cases, I like it to be open or closed on my return, as set, but I understand the need.
- Sure, I did not design for that, but can of course
- Not sure I follow, but will experiment
Cant you point me to if else solution please, so I can test your example?
I love 5.3.x as well
, and love sharing my learings 
Sure: http://chronicles.wiki/TiddlyWikiFormula/#%24%3A%2Fplugins%2Febalster%2Fcondition
Ignore the wording in the link - it’ll take you to the if-else plugin (he calls it the condition plugin). To be clear, you don’t need to install the Formulas plugin.
But really, it’s easy to convert the above to $reveal… better yet, why not wait for the <%if [<filter>] %> shortcut syntax to appear?
Re point 3. I was just making the case that tabs, details and details.2 follow a similar pattern. But details.2 may not stay that way. We’ll see…