[issue] Quirk in notes database solution I am developing

Now Published here Tips and commentary - Notes on tiddlers stored in a data tiddler

I had an idea for a simple solution that is simple, very useful and demonstrates a few code patterns, however it has three problems;

  • Despite the button being at the top, clicking in the edit field is triggering a close
  • For viewing the text the transclude widget is not processing the newlines \n found in the content retrieved from the data tiddler
  • I need to see if Relink can handled the rename of titles in data tiddlers?

All three of these problems will shed light on issues the code patterns may give rise to.

  • It exposes the possibility of storing multiline fields in data tiddlers whilst using the $index parameter on the editWidget.
  • Later I may test using an editor with a toolbar for the same
\function notes.popup.tiddler() [<qualify $:/temp/edit-notes>]
\define note.database() $:/note.database
\procedure view/edit.notes()
<$button popup=<<notes.popup.tiddler>> tooltip="view/edit.notes for this tiddler" tag=div>
<%if [<notes.popup.tiddler>has[title]] %>
   <button>View Notes</button>
<%else%>
   <button>Edit Notes</button>
<%endif%>
</$button>
<hr>
<div>
<%if [<notes.popup.tiddler>has[title]] %>
   <$edit tiddler=<<note.database>> index=<<currentTiddler>> class="tc-edit-texteditor"/>
<%else%>
   <div>
   <$transclude $tiddler=<<note.database>> $index=<<currentTiddler>> mode=block/>
   </div>
<%endif%>
</div>
\end view/edit.notes

<<view/edit.notes>>
  • Paste this into a tiddler to test.

Once this is fixed

  • I need to see if we can use Quotes " " inside the notes as this is what delimits the value in the data tiddler.
  • [edited] I note that Quotes are delimited with \"

To prevent the popup from being closed, the $edit widget needs to use

class="tc-edit-texteditor tc-popup-handle"

To view the content with newlines intact, change this:

<div>
<$transclude $tiddler=<<note.database>> $index=<<currentTiddler>> mode=block/>
</div>

to this

<div style="white-space:pre;"><$transclude tiddler=<<note.database>> index=<<currentTiddler>>/></div>

-e

2 Likes

No, it doesn’t currently rename titles in data tiddler text (or data tiddler indexes, for that matter). You can test this on the Relink demo site by making a new tiddler with type: application/x-tiddler-dictionary and text content

Frodo: a hobbit
Sam: [[Frodo]]'s gardener

Then use any of the demo buttons further down the page and note that [[Frodo]] does not change.

1 Like

it looks like it does not, however there are opportunities to configure more settings and fields.

I may ask the plugin author :cowboy_hat_face: thanks

thanks @EricShulman and @etardiff

1 Like

ie style="white-space:pre;"

@EricShulman this does fix the new lines, but also forgoes the use of the transclude to wikify the text.

I wonder if instead I need decode the escape sequences differently?

Actually, I seem to be experiencing the fragility of some aspects of TiddlyWiki here.

<%if [<notes.popup.tiddler>has[title]] %>
   <$edit tiddler=<<note.database>> index=<<currentTiddler>> class="tc-edit-texteditor tc-popup-handle" />
<% elseif [<note.database>getindex<currentTiddler>!is[blank]] %>
   <fieldset style="padding: .5em; white-space:pre;"><<condition>></fieldset>
<%endif%>

This is what I have for the view/edit component now

  • No wiki text except [[links]]
  • I am using the fieldset to get the boarder so it looks like a version of the edit box, and put white-space:pre; on that. Note reuse of the getindex through the condition variable.
    • However if you hand delete the text its easy for an invisible \n to remain and thus !is[blank] fails.

You have a typo here. Try one of the following instead:

<$transclude $tiddler=<<note.database>> $index=<<currentTiddler>> $mode=block />

OR

<$transclude tiddler=<<note.database>> index=<<currentTiddler>> mode=block />

It’s important not to mix modern and legacy attributes (like $mode and mode, respectively) within a single $transclude because the presence of a single modern attribute will switch the entire thing into modern mode. In modern mode, any attributes that don’t start with $ are treated as parameters, not widget attributes — so in your original code mode=block is just setting the value of the (nonexistent) “mode” parameter, not switching the parsing mode. And since you have several lines of code in a row, it defaults to using the inline parser.

3 Likes

This is NOT true!.. the white-space:pre only affects the display of the newlines… the $transclude still wikifies the content. Try entering this content:

This is text
HelloThere
<$list filter="[range[5]]"><<currentTiddler>><br></$list>
and more text here

and you will see that HelloThere is a link, and the $list widget output (numbers 1 to 5) is displayed.

That was SOOO hard to see the mixed modern and old format. Thanks for spotting the errant $.

@EricShulman’s tc-popup-handle allows the edit to stay open now, I can dump the white-space:pre; the : and other line based wiktext were failing, but the transclusion was still broken then

The transclude modern/traditional errors means it now wikifies correctly. including \n it appears.

The view edit section now looks like this;

<%if [<notes.popup.tiddler>has[title]] %>
   <$edit tiddler=<<note.database>> index=<<currentTiddler>> class="tc-edit-texteditor tc-popup-handle" />
<% elseif [<note.database>getindex<currentTiddler>!is[blank]] %>
   <fieldset style="padding: .5em; ">
      <$transclude tiddler=<<note.database>> index=<<currentTiddler>> mode=block />
   </fieldset>
<%endif%>

All that remains;

  • Just need to address some unwanted space above and below the rendered text because the transclusion is wrapped in a <p></p> that is not in the data tiddler.
    • This appears to be an opinionated include?
  • Give the user an easy way to hide the display of notes if desired.
1 Like

Glad you got it working!

Incidentally, I’d started responding to your OP and scrapped it when I saw Eric was answering, but I did want to ask about this part of your code…

<$button popup=<<notes.popup.tiddler>> tooltip="view/edit.notes for this tiddler" tag=div>
<%if [<notes.popup.tiddler>has[title]] %>
   <button>View Notes</button>
<%else%>
   <button>Edit Notes</button>
<%endif%>
</$button>

Is there a reason why you’re using HTML buttons inside a $button widget with the <div> tag? IMO, it’d be easier and more semantic to make a single button with variable content. I might do something like this:

\function button.label() [<notes.popup.tiddler>has[title]then[View]] ~Edit

<$button popup=<<notes.popup.tiddler>> tooltip="view/edit.notes for this tiddler">
	<<button.label>> Notes
</$button>

It was just to illustrate an idea, that <button>name</button> only generates a look alike button.

  • The div was just to hide the proper button, if not used this method would look like this;
    2025-11-05_16-25-04

If you look closer, this is one button widget that displays according to the state of the popup, which is the existence of a temp field. Notice how the button does nothing else at all?

  • I believe this may be the easiest way to toggle a condition.

I was not planning to create a “canonical solution” but something to talk about and share comments on the code used. However perhaps this is not the best way to demonstrate the uses of a simple html button <button>name</button> because of the ambiguity and a standard way will suffice.

it now reads without the tag-div and

<%if [<notes.popup.tiddler>has[title]] %>
   View Notes
<%else%>
   Edit Notes
<%endif%>

The other tag div was to introduce other class/styles but I will remove that too.

Final result? possibly not, its designed to be talked about

\procedure view/edit-notes()
   \function notes.popup.tiddler() [<qualify $:/temp/edit-notes>]
   \define note.database() $:/note.database
   <$button popup=<<notes.popup.tiddler>> tooltip="view/edit.notes for this tiddler">
      <%if [<notes.popup.tiddler>has[title]] %>View Notes<%else%>Edit Notes<%endif%>
   </$button>
   <%if [<notes.popup.tiddler>has[title]] %>
      <$edit tiddler=<<note.database>> index=<<currentTiddler>> class="tc-edit-texteditor tc-popup-handle" />
   <% elseif [<note.database>getindex<currentTiddler>!is[blank]] %>
      <fieldset style="padding: .5em; "><$transclude tiddler=<<note.database>> index=<<currentTiddler>> mode="block" /></fieldset>
   <%endif%>
\end view/edit-notes

<<view/edit-notes>>

Thanks for highlighting this was obscure.

Yes, I followed that. I was just trying to figure out why you’d want to make a button, hide it, and then fill it with pseudo-button(s).

Just to show something which I subsequently did not do. Build more inside the popup button. I think it is better to demonstrate the minimalist toggle example. It can be used for many things and be present anywhere you can place it with the content it unfolds also places where you want.

  • It could trigger an action, delete an entry by responding to the modifier keys, that may be a good way to demonstrate %if used like a case statement.

If you can see a way to include any other smarts without complicating it too much let me know.

I think it’s very reasonable to use it for conditional content display, since that’s more or less what popup is designed to do. I’ve always used it with $reveal, myself, as suggested by the docs, but it’s nice to see that it can be used with <%if%> as well in situations where you don’t want an actual popup.

Could you expand a little more on that? I’m having trouble envisioning how action widgets could be triggered by the popup attribute alone, or how this would be more efficient than simply using a standard actions attribute. I suppose you could include a conditional that referenced the current popup state in an actions string or procedure…?

Generally, though, I’d be wary of tying action execution to something as transient as a popup. Eric’s solution is perfect for conditional display if the only thing you want to do is toggle the textarea — and I could see this being very useful for inline field editing, for instance. But even with the tc-popup-handle class in place, clicking anywhere else on the page will still delete the state tiddler; it’d be easy to do so entirely by accident. So I think you wouldn’t want to attach any actions that couldn’t be easily reversed — and you’d want to be very careful to ensure that they wouldn’t be triggered inadvertantly.

No, same as you, I would be using the actions parameter on the button using the popup. The main idea was inside an action procedure, using %if nested to be a case statement to handle different modifier keys. This is just a demo to start a conversation.

well i tested it! , ( nice idea btw ),
and tried to read through and understand what dose what
and my internal parser failed/bailed at line one
with error :WTF

\function notes.popup.tiddler() [<qualify $:/temp/edit-notes>]

im flummoxed by this filter ? operator ??? [<var>]

<qualify $:/temp/edit-notes>

or is it a macro with an unquoted argument
in a filter ?
( if so no tw5-com docs examples i could find with this syntax seamed to exists)

** fly’s into the air and
disappears into the the gorge of <eternal ?> {!!syntactic} $peril

You can wait until the official annotated release but consider this “exhibition code” intended to be read and cause questions.

Got Ya! :clap:

We can include variables and macros/procedures in filters. Of course their output needs to be suitable for what comes next in the filter. This example is using the qualify macro to generate a title and does exactly that.

  • It shows how macros/procedures/functions and variables are all a different side of the same coin.

They should be on the same line

( eddied it )
small screens :face_with_symbols_over_mouth: :grimacing:

my tw comprehension/frustration
might be directly correlated to screen size
tbh

I do like the idea and the code is compact but imo very hard to extend.

I personally would want much more flexibility for every element.

  • Button and button-actions
    • eg: OK and Cancel … (todo)
    • Cancel should restore the “old” note (todo)
  • The button may have images instead of text (todo)
  • The button may be somewhere else in the UI
  • The note itself
    • styling using classes
  • Keyboard shortcuts
    • eg: CTRL-Enter in the note saves the note (todo)

… and so on

I did separate the different areas into their own procedures, to be able to implement the above ideas more easily.

The following tiddler is a TestCase tiddler

have fun!

toggle-note-testcase.json (1.5 KB)

title: toggle-note-testcase
tags: $:/tags/wiki-test-spec
type: text/vnd.tiddlywiki-multiple
description: Toggle Note Input

with the following content

title: Narrative

* Show an Edit Notes / View Notes toggle button
* Notes are written to a $:/note.database tiddler

+
title: Output

\whitespace trim

\define note-database() $:/note.database
\function state() [<qualify $:/temp/edit-notes>]

\procedure toggle-actions()
<%if [<state>is[tiddler]]%>
  <$action-deletetiddler $tiddler=<<state>>/>
<%else%>
  <$action-setfield $tiddler=<<state>> text=edit/>
<%endif%>
\end

\procedure toggle-button()
<$button actions=<<toggle-actions>> tooltip="view/edit notes for this tiddler">
  <%if [<state>is[tiddler]] %>
    View Notes
  <%else%>
    Edit Notes
  <%endif%>
</$button>
\end

\procedure note()
<<toggle-button>>
<%if [<state>is[tiddler]] %>
  <$edit tiddler=<<note-database>> focus=yesX index=<<currentTiddler>> class="tc-edit-texteditor c-edit" />
<% else%>
  <fieldset class="c-note">
    <$transclude tiddler=<<note-database>> index=<<currentTiddler>> mode="block" />
  </fieldset>
<%endif%>
\end

<<note>>
+
title: $:/note/styles
tags: $:/tags/Stylesheet

.c-note {
  padding: 0 0.5em 0 0.5em;
}
.tc-tiddler-frame textarea.tc-edit-texteditor.c-edit {
  padding: 14px .5em;
}
+
title: $:/note.database
type: application/json

{
    "Output": "some text"
}

Mario, I for shadowed the additional features but was planning to use it to describe the parts.

I will review in my morning :nerd_face:

1 Like