Long $list with truncated previews (also uses $eventcatcher)

Over here, @Mohammad, @pmario, @TiddlyTweeter, @JanJo and myself were discussing the pros and cons of showing previews when links in a long list are hovered. In addition, elsewhere, I’ve mentioned (via help provided by @saqimtiaz) that $eventcatcher is more performant where a $list might show a mountain of links. The following code demonstrates both of these ideas.

Demo:

1

Drop this code in a tiddler at tiddlywiki.com :

\define my-link-actions()
<$action-navigate $to=<<dom-to>> />
\end

<$eventcatcher selector=".my-link" $click=<<my-link-actions>> >
<div class="results">
<table class="results-table">
<$list filter="[tag[Filter Operators]]" variable=op>
<$wikify name=txt text={{{ [<op>get[text]] }}} output=html>
<tr class="result-row">
 <td class="link-td">
   <a class="my-link tc-tiddlylink tc-tiddlylink-resolves" to=<<op>>><<op>></a>
 </td>
 <td><div class="ttip"><<txt>></div></td>
</tr>
</$wikify>
</$list>
</table>
</div>
</$eventcatcher>

<style>
.result-row {
 overflow:hidden;
}
.result-row .ttip {
 display:none;
 left:50%;
 position:absolute;
 top:110vh;
 max-width:42%;
}
.result-row:hover .ttip {
 display:block;
 max-height:50%;
 max-width:46%;
 overflow:hidden;
 text-overflow:clip;
 top:125px;
}
.link-td {
 cursor:pointer;
 width:50%;
}
.results-table , .results-table td { 
 border:none;
}
.results {
 max-height:50vh;
 overflow-y:auto;
 scrollbar-width:thin;
}
</style>
5 Likes

Thank you @CodaCoder

Good approach!

displaying side by side like the vertical tabs, CSS Grid with two col, or mouse hover if not go with tooltip, is possible! Actually tabular format is an in-place preview!

Lets see what others say!

It’s the approach I said all along. CSS and… <crickets>

I have no idea what that means
:neutral_face:

Thank you! I got it.

I mean if we want to go with a solution to show something side by side (what proposed solution does), we can use different methods!
Tabular format is one solution., CSS Grid with two columns is another solution!

That’s nice. I (kind of) like it for PCs. But there is still a problem with mobile devices. …

I personally like to open tiddlers in search results with CTRL-click, which doesn’t move the focus to the newly opened tiddler.

So I can open several tiddlers and then have a look by scrolling in the story-river. Tiddlers that don’t fit will be closed if I don’t need them anymore.

This lead me to an idea of a new “button” / “function” which does a similar thing as CTRL-click on PCs as CTRL is not available on mobile devices.

If the search-result list would have a toggle-button that will enable / disable the “scroll into view” action for “opened” links, it will be possible to open several tiddlers on mobile devices, without loosing the current focus.

IMO this function would also be useful for all lists on mobile.

What do you think?

1 Like

WHUPP! You have just (re?)created one of my unpublished creations! I call it QTOC (“Quick Table of Contents”) and had intended to make it public in an interview that was to be held between Jermolene and me but then the pandemic broke out.
Here is my code for comparison:

You call it like so:
<<qtoc "filter">> e.g <<qtoc "[tag[Filter Operators]]">>


title: qtoc/macro
tags: $:/tags/Macro
text:
\define qtoc-tab()
<input type="radio" id="$(slug)$" name="qtoc-group">
<div class="qtoc-link"><$link/></div>
<label for="$(slug)$">{{$:/core/images/right-arrow}}</label>
\end

\define qtoc-content()
<div class="qcontent" style="min-height:200px">
   <$transclude mode=block/>
</div>
\end

\define qtoc(filter)
<div class="qtoc">
<$vars c=<<currentTiddler>>>
<$list filter="""$filter$""">
   <div class="qtab">
      <$vars slug={{{ [<currentTiddler>addprefix[-]addprefix<c>slugify[]addprefix[qt-]] }}}>
         <<qtoc-tab>>
         <<qtoc-content>>
      </$vars>
   </div>
</$list>
</$vars>
</div>
\end

and stylesheet

title: qtoc/stylesheet
tags: $:/tags/Stylesheet
text:
.qtoc {
  position: relative;
  clear: both;
}
.qtoc label {
  background: #f4f4f4;
  padding: 0 6px;
  outline: 1px solid #ccc;
  position:absolute;
  left:calc(30% - 22px);
  opacity:0;
}
.qtoc .qtab [type="radio"] {
  display:none
}
x.qtoc .qcontentstick {
  position: -webkit-sticky; /* Safari */
  position: static;
  top: 100px;
  background-color: green;
  border: 2px solid #4CAF50;
}
.qtoc .qcontent {
  position:absolute;
  top:-1px;
  right: 0;
  bottom: 0;
  left:30%;
  padding: 20px; padding-top:0;
  border: 1px solid #ccc;
  background: white;
  overflow: auto;
}
.qtoc .qcontent > * {
  display:none;
}
.qtoc [type="radio"]:focus ~ label {
  outline: 2px solid blue !important;
}
.qtoc [type="radio"]:checked ~ label {
  background: white;
  border-bottom: 1px solid white;
  z-index: 2;
  opacity:1;
  outline: 2px solid blue;
  outline-offset:-2px;
}
.qtoc [type="radio"]:checked ~ label ~ .qcontent {
  z-index: 1;
}
.qtoc [type="radio"]:checked ~ label ~ .qcontent > * {
  display:block;
}
.qtoc-link {
  width:30%;
  display:inline-block;
  padding-left:10px;
  text-indent:-5px;
}
.qtoc-link:hover, 
 .qtoc-link:hover + label, 
 .qtab label:hover, 
 [type="radio"]:checked ~ .qtoc-link {
  outline:1px solid silver;
  opacity:1;
}
.qtoc-link:hover ~ .qcontent,
 .qtoc label:hover ~ .qcontent {
  z-index: 2;
}
.qtoc-link:hover ~ .qcontent > *,
 .qtoc label:hover ~ .qcontent > * { 
  display:block;
}
.qtoc label svg {
  fill:gray;
  width:10px; height:10px; margin-top:-2px;
}
.qtoc label:hover .qtoc-link {
  outline:1px solid silver;
}
1 Like

I was/am very surprised to see how compact your code is. Maybe this is because of the eventcatcher?

One pretty big thing with my solution is that it works in static tiddlers! If you put it in a tiddler and export that tiddler, you will see that the static tiddler still works. (I was pretty surprised myself actually :slight_smile:

EDIT: …and so does yours!!! Good workin!

1 Like

LOL. Thanks for the kind words.

So is mine (a recreation). My resident version is heavily embedded in my system – never written to be transportable (like the vast majority of my stuff, sadly). Having made a half-promise to @Mohammad yesterday that, if I had time, I’d knock up a quick demo, this morning I had put my code where my mouth is. :sweat_smile:

It needs refining, obviously – I literally threw it together from memory as quickly as possible.

Here’s a screen grab of the original – popout/preview on the left this time:

Thanks @pmario

Certainly sounds good. My experience with TW on mobile is extremely limited, so my opinion isn’t worth a penny.

But on PC, I’m rarely working in the story river. When I am, I “deal with it” and go back to my heavily customized UI fairly quickly. Said another way, I’m probably not your target market.

That said, your approach sounds fine to me – you’ve stepped around the PC/Mobile divide admirably as far as I can see.

In memory, yes. In source, very little difference – it might even be a little larger.

What $eventcatcher is doing is, removing all the click handlers from the links and delegating them to the $eventcatcher’s div element. So the anchor elements (<a> tags) are still there, but they have no href attributes and hence no event handlers. That’s a lot of wiring thrown away for 100s (I’m guessing here) of links.

1 Like

These methos look similar to the toc internal and external macros which could benifit from some tech upgrades

Could this have being achieved previously wrapping a list of links in a navigator widget?

No, the navigator widget is about sending commands to tiddlers (rename, delete, save etc), not about event handling in the widget tree.

1 Like

Yes and no, I discovered details about the navigation mechanism, especially here https://tiddlywiki.com/#Creating%20SubStories

  • Perhaps this is using an event catcher to add selected tiddlers to the custom story.
  • I do not understand all the details yet, but this is demonstrating something very similar to the Original Topic.
  • people smarter than me on this subject can inspect the result to measure the relative “efficiency”.
  • It seems to me using the eventcatcher to catch onclick and tiddler titles is redundant given the navigator widget.

As an example on tiddlywiki.com create a tiddler “Widget Messages”

  • Note this contains an arbitrary list of tiddlers and the navigator widget effectively wraps the list of links and updates the $:/temp/DemoStoryList with any on click.
<$navigator story="$:/temp/DemoStoryList" history="$:/temp/DemoHistoryList">

<$list filter="[prefix[WidgetMessage: ]]"> containing

</$list>

</$navigator>

And a tiddler “A Story View”

<$navigator story="$:/temp/DemoStoryList" history="$:/temp/DemoHistoryList">

<$list
  filter="[list[$:/temp/DemoStoryList]]"
  history="$:/temp/DemoHistoryList"
  template={{$:/config/ui/ViewTemplate}}
  editTemplate={{$:/config/ui/EditTemplate}}
  storyview="classic"
  emptyMessage="Use search box above. Clicked search links will open here instead of in the main story.<p>No search ideas? Click this link to get started: HelloThere</p>"/>

</$navigator>

Note the same navigator settings and list details?

Clicking a link in “Widget Messages” opens that tiddler in “A Story View”. Change storyview=“pop” to only see the last tiddler.

You’re missing the point,Tones – this is your code in the dom inspector:

$eventcatcher removes all the anchor elements’ click handlers. And that image is only a small part of the dom your code generates. Removing all that wiring (which takes up the lion’s share of the time involved in displaying the list) is where the improvement comes from.

Also, the navigator doesn’t handle all (bubbling) events – nor should it; that’s not its job.

2 Likes