How to add a close button to remove each tiddler from select widget

<$select tiddler='$:/HistoryList' field="current-tiddler" >
<$list filter='[list[$:/StoryList]]'>
<option><$view field='title'/></option>
</$list>
</$select>

I use the abovegiven select widget in my topbar to list the tiddlers in the storyriver.
Now I was thinking whether I can add a close button to the side of each listed tiddlers in the select widget. That close button should be able to remove that tiddler from the list field of $:/StoryList. Is this possible.

As far as I understand, the selectwidget is a bit funny in that it combines a tiddlywidget with the option html elements. The latter is unlikely to permit much flexibility in what can be inside it.

Instead, you probably need to create your own selectwidget. I would start by using an edittextwidget and a revealwidget and inside the revealwidget use the listwidget showing each title along with a buttonwidget that probably uses a listops to remove titles from the storylist.

Will it be possible by modifying this solution by @EricShulman

That is still a selectwidget with option elements inside so I’d say that it is still a problem to insert a button for the options.

I would do something like this. Sorry for not giving a complete answer but I’m busy with other stuff. You also seem to want to style the list so I threw in a div:

<$reveal type="popup" state=<<popid>>>
   <div class="shortlist">
      <$list filter="[enlist<items>]">
         <$button set="!!test" setTo=<<currentTiddler>> >
              <<currentTiddler>>
         </$button>
         <$button>
             <$actions-setfield ...probablySomeListopActions.... />
              X
         </$button>
      </$list>
   </div>
</$reveal>

Here is the final code which is working for me. It also has some extra code needed for it to work seamlessly in my custom layout

\function storylist-popid()
[[$:/state/field-pop/]addsuffix{!!title}addsuffix[/]addsuffix<current-field-name>]
\end storylist-popid

\procedure navigate-storylist-tiddler()
<$let
currentTiddler={{$:/HistoryList!!current-tiddler}}
>
<% if [{$:/arsheth/cards-ui/cards/max-width}match{$:/arsheth/cards-ui/card-1/width}] %>
<$action-setfield $tiddler=<<currentTiddler>> class="card-1" $timestamp="no"/>
<$action-navigate $to=<<currentTiddler>>/>
<% elseif [{$:/arsheth/cards-ui/cards/max-width}match{$:/arsheth/cards-ui/card-3/width}] %>
<$action-setfield $tiddler=<<currentTiddler>> class="card-3" $timestamp="no"/>
<$action-navigate $to=<<currentTiddler>>/>
<% elseif [{$:/arsheth/cards-ui/cards/max-width}match{$:/arsheth/cards-ui/card-4/width}] %>
<$action-setfield $tiddler=<<currentTiddler>> class="card-4" $timestamp="no"/>
<$action-navigate $to=<<currentTiddler>>/>
<% elseif [{$:/arsheth/cards-ui/cards/max-width}match{$:/arsheth/cards-ui/card-5/width}] %>
<$action-setfield $tiddler=<<currentTiddler>> class="card-5" $timestamp="no"/>
<$action-navigate $to=<<currentTiddler>>/>
<% else %>

<% endif %>
</$let>
\end

<style> .short-storylist { width:30vw; max-width:50vw; overflow:hidden; text-overflow:ellipsis; background-color:<<color page-background>>;} </style>
<$navigator story="$:/StoryList" history="$:/HistoryList">
<div style="position:relative;">
<$button popup=<<storylist-popid>>>   <$list filter="[[$:/HistoryList]get[current-tiddler]!is[blank]]" emptyMessage="no-focussed-tiddlers"><$view tiddler="$:/HistoryList" field="current-tiddler"/>    </$list></$button>
<$reveal type="popup" state=<<storylist-popid>> class="tc-drop-down short-storylist" position="below" animate="yes" retain="yes" style="min-width:auto;">   
   <$list filter="[list[$:/StoryList]]" variable="storylist-item">
<span style="float:left;">
      <$button class="tc-btn-invisible" set="$:/HistoryList!!current-tiddler" setTo=<<storylist-item>> actions=<<navigate-storylist-tiddler>>>
         <$text text=<<storylist-item>>/>  
       </$button>
         </span>
<span style="float:right;">
<$button class="tc-btn-invisible" actions="""<$action-listops $tiddler="$:/StoryList" $field="list" $subfilter="-[<storylist-item>]"/>"""> x </$button>
         </span>
<br>
   </$list>
</$reveal>
</div>
</$navigator>

1 Like

Have you tried the multiple option on the select widget, you can check/uncheck selected tiddlers but it is not a dropdown/popup, But perhaps you could wrap the whole selection with a click to open or place it in a MODAL?

@TW_Tones that’s is an interesting option…I will have to experiment and find out

Adding functional content to the <option> elements of a $select widget is tricky, because HTML doesn’t allow other elements (such as a “close” button) to be rendered within the <option> elements.

However, it IS possible to FAKE that functional content…

Give this a try:

\define myStoryList()
\define close() <$action-sendmessage $message="tm-close-tiddler" $param={{{ [[$:/HistoryList]get[current-tiddler]] }}}/>
\define click() <$list filter="[<tv-selectednode-width>subtract<event-fromselected-posx>compare:integer:lteq[20]]"><<close>></$list>
<style>.myStoryList option::after { float:right; margin-left:1em; content:"&#x274C;"; }</style>
<$eventcatcher selector="option" $click="<<click>>">
<$let popid=<<qualify "$:/state/popup/myStoryList">>>
<$button class="tc-btn-invisible" popup=<<popid>>>select a title...</$button>
<$reveal type="popup" state=<<popid>> style="width:max-content;">
	<$select tiddler="$:/HistoryList" field="current-tiddler" focus="yes"
		size={{{ [list[$:/StoryList]count[]min[10]max[2]] }}} class="myStoryList">
		<$list filter="[list[$:/StoryList]]"><option><$view field='title'/></option></$list>
	</$select>
</$reveal>
\end

<<myStoryList>>

Notes:

  • First, we define some convenient “abbreviations” that make the code easier to read:
    • close() will be used to perform the “close current tiddler” action
    • click() is used with $eventcatcher to handle clicks on the $select widget’s option elements. Note how the <<close>> action is only performed if the click occurs within the rightmost 20 pixels of the option element. You may need to adjust this value to match the font size of your rendered $select list.
  • The <style> CSS adds an :x: at the right edge of each option element. Note the use of .myStoryList to limit this CSS rule so it is applied only to the $select list that has that class and won’t affect any other $select lists.
  • Next, add an $eventcatcher to catch the clicks on the $select widget’s list options and invoke the <<click>> handler. This will occur after the normal $select widget handling that assigns the selected option value to $HistoryList!!current-tiddler.
  • In order for this all to work, the $select widget has to have a size greater than 1 (i.e., a listbox, not a standard browser-based droplist). To make the listbox appear AS IF it was a droplist, we use a $button/$reveal popup combination. So, we start by defining a suitably qualified popid value to use with the $button and $reveal widgets.
  • Then, render the $button to trigger the popup, followed by the $reveal containing the popup contents.
    • The $reveal uses style="width:max-content;" to ensure that the popup leaves room for the “fake close button”.
  • Finally, render the $select widget inside the popup:
    • Set the size of the $select widget to a maximum of 10 items, and a minimum of 2 items. If there are more than 10 items, the $select widget will automatically get a scrollbar.
    • Add the myStoryList class so the CSS rule we previously defined can be applied to the option elements to add the red X “fake button”.
    • Add focus="yes" to allow immediate keyboard navigation as soon as the $select widget is rendered.

Let me know how it goes…

enjoy,
-e

2 Likes

Starting from Eric’s idea. You can try the following code:

The dropdown reuses the code from the Open-sidebar and formats it like a dropdown using some CSS.

The Open sidebar will also allow you to drag and drop sort if you want

title: myStoryList-dropdown

\whitespace trim
\procedure myStoryList()
<$let popid=<<qualify "$:/state/popup/myStoryList">>>
  <$button class="tc-btn" popup=<<popid>>>select a title...</$button>
  <$reveal type="popup" state=<<popid>> class="my-select tc-popup-keep tc-drop-down">
    {{$:/core/ui/SideBar/Open}}
  </$reveal>
</$let>
\end

<<myStoryList>>
title: myStoryList-styles
tags: $:/tags/Stylesheet

.my-select.tc-drop-down .tc-btn-mini {
  display: inline;
  width: initial;
}
.my-select.tc-drop-down a {
  display: inline-block;
  width: 85%;
}

have fun!
-mario

myStoryList-open-sidebar.json (755 Bytes)

Thank you @EricShulman and @pmario for sharing your solutions for the query in the OP. I am in the midst of a small journey. So I didn’t get time to test any of your suggestions. I will be back home only after one week. I will give my feedback after reaching back home (since I don’t have a laptop in my possession to test those) Thank you once again for your help

@EricShulman and @pmario Thanks to both of you. Both solutions are good and pmario 's suggestion to use sidebar open code gives the drag and drop functionality also.

But now the idea which I have in my mind is to little complex. I need a pop up which shows both the currently open tiddlers in the storyriver and also the recently closed tiddlers in storyriver. I will open another thread for it. Thanks for your help.

Give this a try: TiddlyTools/History

It defines a tiddler toolbar button that uses a combination of the $:/HistoryList, $:/StoryList, and $:/DefaultTiddlers to display a popup containing a list of “viewed” tiddlers.

It also includes a “delete” button that resets the $:/HistoryList and $:/StoryList to contain only the current tiddler, and a “details” button that shows the current contents of the $:/StoryList!!list, the $:/DefaultTiddlers filter and the accumulated $:/HistoryList text and current-tiddler field values.

-e

1 Like

I will check into this

Meanwhile this is the code I was trying. But there is some issue with appending to list field in this code


\function storylist-popid()
[[$:/state/field-pop/]addsuffix{!!title}]
\end storylist-popid

\procedure recently-closed-state() 
$:/state/recently-closed
\end

\function append-storylist() 
[list[$:/StoryList]append<recently-closed-item>]
\end

\function append-recently-closed() 
[list[$:/state/recently-closed]append<storylist-item>]
\end


\procedure close-actions() 
<$action-listops $tiddler="$:/state/recently-closed" $field="list" $subfilter="+[<storylist-item>]"/>
<$action-listops $tiddler="$:/StoryList" $field="list" $subfilter="-[<storylist-item>]"/>
\end

\procedure reopen-actions() 
<$action-listops $tiddler="$:/state/recently-closed" $field="list" $subfilter="-[<recently-closed-item>]"/>
<$action-listops $tiddler="$:/StoryList" $field="list" $subfilter="+[<recently-closed-item>]"/>
\end

\procedure navigate-storylist-tiddler()
<$let
currentTiddler={{$:/HistoryList!!current-tiddler}}
>
<$action-navigate $to=<<currentTiddler>>/>
</$let>
\end

<style> .short-storylist { min-width:auto; width:auto!important; max-width:80vw!important; overflow:hidden; text-overflow:ellipsis; background-color:<<color page-background>>;} </style>
<$navigator story="$:/StoryList" history="$:/HistoryList">
<div style="position:relative;">
<$button popup=<<storylist-popid>>>   <$list filter="[[$:/HistoryList]get[current-tiddler]!is[blank]]" emptyMessage="no-focussed-tiddlers"><$view tiddler="$:/HistoryList" field="current-tiddler"/>    </$list></$button>
<$reveal type="popup" state=<<storylist-popid>> class="tc-drop-down tc-popup-keep short-storylist" position="below" animate="yes" retain="yes" style="min-width:auto;">   
<$list filter="[list[$:/StoryList]]" variable="storylist-item">
<span style="float:left;">
<$button class="tc-btn-invisible" set="$:/HistoryList!!current-tiddler" setTo=<<storylist-item>> actions=<<navigate-storylist-tiddler>> >
<$view tiddler=<<storylist-item>> field="title"/>  
</$button>
</span>
<span style="float:right;">
<$button class="tc-btn-invisible" actions=<<close-actions>> > x </$button>
</span>
<br>
</$list>
<br>

recently-closed-tiddlers <$button class="tc-btn-invisible" actions="""<$action-navigate $to={{$:/HistoryList!!current-tiddler}} />""">go</$button>

<$list filter="[list[$:/state/recently-closed]]" variable="recently-closed-item">
<span style="float:left;">
<$view tiddler=<<recently-closed-item>> field="title"/>  
</span>
<span style="float:right;">
<$button class="tc-btn-invisible" actions=<<reopen-actions>>>reopen </$button>
</span>
<br>
</$list>
</$reveal>
</div>
</$navigator>

Is there any way to append and remove item to the list field of a tiddler one by one ?
That is when I close a tiddler from the storyriver using a custom button in the dropdown, it should be added to the list field of a tiddler called $:/state/recently-closed and simultaneosly removed from the list field of $:/StoryList.
Also when I reopen a tiddler in the recently closed list from the dropdown using a custom button, it should be added to the list field of $:/StoryList and simultaneosly removed from the list field of $:/state/recently-closed. That’s what i tried using the above given code. But it had some issues.

This code is working when I removed the + sign from <$action-listops $tiddler="$:/state/recently-closed" $field="list" $subfilter="+[<storylist-item>]"/>