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