Configuring TW's Editor

Over the past few weeks, I have been pondering how to provide an editing environment for my guns TW. I have played around with providing a bespoke form for each tiddler type and this works. My concern though is over the medium term, things will change and I may not be around to provide the technical support needed to effect such change.

So I fall back on TW’s inbuilt editor.

I like this approach in that the editor is tiddler independent, any tiddler can be edited with it, and the fact that the TW development team essentially provide support through new TW versions, etc.

The downside, for me at any rate, is that I can not see how I can have the conclusion of an editing session invoke TW script to verify stuff, propagate new values through to other tiddlers, etc. I can do that in a bespoke setting by having an ‘UPDATE’ button to terminate the session and call appropriate script as needed.

Whilst reading the documentation, I came across the tiddler ’Customizing EditTemplate field rendering’. This implies that I can have control over how the default editor displays and hence manipulates any field. What is unclear to me though is whether, if I specify a specific display for a field, that display replaces the equivalent display through the normal editor or does this provide a replacement for the whole editor display itself?

The reason I ask is because many of my tiddlers have numerous fields as well as lots of formatted text in the TEXT field and I don’t want to have to replace the text field editing facility but I also do not want my uses to have to choose between one or many editors cause they’ll stuff it up for sure.

And then, is there any way to intercept a session termination event so as to allow me to propagate new values through my TW or a session cancel event to quit the editor without making any changes?

Has anyone done any of this and if so can they provide some advice?

bobj

I am not clear on the events you wish to trigger, and what these values are you wish to propergate.

We tend to update the tiddler, save the change to the tiddler store, then tiddlers changes are propagated throughout that which is affected and displayed.

We then save these changes to the underlying html or node wiki.

Perhaps one thing you may be looking for, consider the done button, this is how you end the editing session for each tiddler, you can use its selection to trigger a script/set of actions to run your field validation and update etc…

However I would be inclined except for the text field ,to create a set of custom edit-text editors for each Field that forces only particular values, or validates and makes other changes (avoid) in the wiki when you finish editing the field.

  • This opens up a broad set of validation possibilities, which I wont expand on until needed.

@TW_Tones , thanks for your reply. It raises some questions in my mind.

  1. you say, “We tend to update the tiddler, save the change to the tiddler store, then tiddlers changes are propagated throughout that which is affected and displayed.”. This is what I am trying to ensure but in my case, I have a gun titled SA_12345, of gun type GT-123, located in Elizabeth. The caption of the gun tiddler is ‘South Australia: Elizabeth - a bloody big gun’, where ‘a bloody big gun’ comes from the nomenclature field of gun type GT-123. This is done through the Add a Gun script that transcludes the nomenclature field from the gun type when creating the caption of the gun tiddler. So when I change the nomenclature field to ‘a very noisy gun’, at what stage is the caption field of the gun updated to reflect that change? I can do it with an ‘Update’ button on a bespoke editor form but I can not see how I can achieve that using the TW editor. Remember also, many guns might need to be similarly updated, ie. all guns of that type.
  2. you also say “Perhaps one thing you may be looking for, consider the done button, this is how you end the editing session for each tiddler, you can use its selection to trigger a script/set of actions to run your field validation and update etc…”. How and where is the ‘done’ button or do you mean the √ button? If the √ button, how can I determine it has been ticked and then invoke a macro to propagate the updates?
  3. And what about the text field? Apart from duplicating the functionality of the TW editor, how can I expect the user to edit and format the text field with all the power of the TW formatting facility? Otherwise, I need a minimum of 2 editors, a bespoke one for the fields, and the TW editor for the text field. And we both know some bugger will stuff it up and edit fields using the TW editor cause they can and get things out of sync, and I cant force them to use the bespoke editor. Or is there a way through which I can force the use of a bespoke editor?
  4. It would be great if there could be a run-time transclusion on the caption field so that the transclusion is performed when accessed and not at create time. This however would need to be actioned even if the tiddler caption is displayed in a search result list, cause SA_123435 means nothing to the user but South Australia: Elizabeth - a bloody big gun is meaningful (which is why I use the caption field to provide meaningful names for gun tiddlers)

bobj

I thought I would ask our friendly ChatGPT for its suggestions and it came back with :

1. Override the button’s action (most common)

Default buttons in TiddlyWiki are usually implemented as widgets (like $button) with an actions attribute.

You can override or shadow the original button by redefining the same UI element (often via a shadow tiddler).

Example:

\define my-save-action()
<$action-log message="Save button clicked"/>
<$action-sendmessage $message="tm-save-wiki"/>
\end

<$button actions=<<my-save-action>>>
Save
</$button>

This lets you inject your own logic before/after the original action.


2. Intercept messages (cleaner “hook” approach)

Most core buttons don’t directly execute logic—they send messages like:

  • tm-save-wiki

  • tm-new-tiddler

  • tm-delete-tiddler

You can listen for or reroute these messages using widgets like $action-sendmessage, $messagecatcher, or custom widgets.

Example idea:

<$messagecatcher $tm-save-wiki=<<handle-save>>>

Then define handle-save to run your custom logic.

:warning: Caveat: TiddlyWiki doesn’t have a full event interception system like a browser framework, so this is more like rerouting than true interception.


3. Override core shadow tiddlers

Many default buttons live in shadow tiddlers such as:

  • $:/core/ui/Buttons/save

  • $:/core/ui/Buttons/new-tiddler

You can create a tiddler with the same title to override it.

Steps:

  1. Create a new tiddler with the same name

  2. Modify its content (add your logic)

  3. The core version is shadowed

This is the closest thing to “intercepting” a default button globally.


4. Use JavaScript modules (advanced)

If you want true interception (e.g., prevent action conditionally), you can write a startup or widget module in JavaScript:

  • Hook into message handling

  • Override widget behavior

  • Extend the event system

This is powerful but more complex and less portable.


I’ve tried ChatGPT before with little luck but am wondering, are any of these suggestions valid/recommended?

bobj

The second option in ChatGPT’s reply has led me to messagecatcher and eventcatcher widgets. If I understand their writeups correctly, either would enable me to detect a tm-save-tiddler message, which I believe is raised by the close editor event (clicking the √ button), and trigger a macro call in which I do my propagation.

If this is correct, where does the script to invoke the catcher widget actually reside? Is it on the shadow edit tiddler or one of my own tiddlers inserted into the edittemplate hierarchy?

bobj

I have a possible solution, the haschanged operator.

I have created a tiddler that has

<<list-links "[title[Test Data]haschanged[yes]]" >>

and when I edit the test data tiddler, its title appears in the testchanged tiddler. So this is one way of detecting that a tiddler has been changed, but using a $list widget rather than list-links.

This TW script could be included on all tiddler types for which such detection is required through its viewtemplate code thus triggering the propagation when the edit completes.

Anyway, onwards and upwards.

bobj

I have answers for most of these questions, however I am still a little unsure about the changes you are trying to action. Do you want to discuss over a quick zoom session. I don’t have a camera with me so just audio and screen share.

What I call the done button is the tick on the tiddler after editing and defined in $:/core/ui/Buttons/save

happy to zoom with you. when?

bobj

I only have 25mins available if you want to connect ASAP

@TW_Tones thank you very much for your time to open the door into TW field handling and especially the capability of putting transclusion script into the value of a field to have that transclusion actioned at render time. This is what I was missing!

Also your pointer to $:/core/ui/Buttons/save is greatly appreciated.

I wish all of this could be written up for everyone though.

bobj

See the following to get started;

If I can find other references I will share

Only the 1 field will be changed - globally.

There also is a example how to create new edit button. So you should be able to create an update button as you do now. See Created a temporary bold button

It’s also possible to create completely new Cancel and Done buttons, for edit templates if you need to. There you can do what ever you want. No need to intercept anything.

But it depends on what you really want to do. IMO you need to be more specific, what you do now and where, so we can see it.

@TW_Tones following on from our discussion yesterday regarding using transclusion in field values to propagate the gun type common name value, I have tried the following

The result is the CommonName field getting its content from the GUNTYPE field ‘common’ and the caption field trying to transclude the transclusion so as to get its value also from the GUNTYPE common value via the CommonName field.

As you can see, underneath the image we see the transcluded values for the two fields but the caption field at the title area of the tiddler is not performing the second transclusion.

I have also tried setting the caption field to the value {{{ [{!!CommonName}] }}}

but as you can see from below that also doesn’t perform the second transclusion on the caption field display as the tiddler ‘title’, instead displaying the content of the caption field, namely {{{ [{!!CommonName}] }}}

so it would appear that the title area of the displayed tiddler does not necessarily adhere to general field rendering. I can understand that from the title field itself as it is the system wide tiddler id, but the caption field only serves to provide a more meaningful label to the display. There may and probably are, other limitations to the use of the caption field that I have not come across yet, such as displaying the caption in the resultant list after a $list process.

One way round this may be to display the caption field underneath the title area of the display through the viewtemplate, just as we might display any of the tiddler’s fields. But then what do we display in the title area that is more meaningful than MGA2010507_LandingPage?

So one step forward, and three sideways

bobj

My guess is that to get the caption displayed in place of the usual tiddler title, you have used some syntax like this:

<$view field="caption"><$view field="title"/></$view>

in which the $view widget’s “fallback” handling is invoked to show <$view field="title"/> if the caption field is missing or empty. If this is the case, then your problem arises because the $view widget defaults to showing field content as plain text (i.e, equivalent to <$text text={{!!caption}}/>).

To address this, you can replace the outer $view widget with a $transclude widget which fully renders (“wikifys”) field contents and, like the $view widget, also includes fallback handling when the indicated field is missing or empty.

Try this:

<$transclude field="caption"><$view field="title"/></$transclude>

Let me know how it goes…

-e

I second @EricShulman view. Caption as title is not standard so that implementation was unknown to me. normally caption is wikified in lists.

@EricShulman , I have not used any bespoke script to get the caption displayed. The tiddler display is just using the default display mechanism, which, as I am sure you are aware, displays the caption field if one exists else the title field.

So, to do what you suggest, I presume I need to edit the relevant shadow tiddler?

It sounds though that I need to revisit the architecture and rethink title/caption, etc.

bobj

Actually its not the default behaviour. See tiddlywiki.com. The caption only gets used in some lists such as the TOC and list-links*.

Have you modified $:/core/ui/ViewTemplate/title

Or the settings > info > advanced > cascades > View template Title ?

@TW_Tones I have not altered anything like that. I have only used a viewtemplate to format the display of user fields.


<$let
    parentID={{!!ID}}
    parentLongitude={{!!Longitude}}
    parentLatitude={{!!Latitude}}
    parentState={{!!State}}
    parentTown={{!!Town}}
    parentGunType={{!!GunType}} 
    parentDateofManufacture={{!!DateofManufacture}}
    parentManufacturer={{!!Manufacturer}}
    parentSerialNumber={{!!SerialNumber}}
    parentCalibre={{!!Calibre}}
    parentWeightofProjectile={{!!WeightofProjectile}}
    parentRange={{!!Range}}
    parentLocation={{!!Location}}
>

<$list  filter="[<currentTab>caption[Original]]" >
<$transclude tiddler=<<currentTab>> $field="text" $mode="block" />
</$list>


<$list  filter="[<currentTab>caption[Why]]" >
<%if [{$:/TLS/State/EditMode!!editMode}match[true]] %>
<$button>
<$action-setfield $tiddler={{{ [<currentTab>] }}} $field="text" $value="Now click the pencil icon {{$:/core/images/edit-button}} (top right hand of this record) and edit this record to add 'why' information below. 

Remember to delete this text first.

!!Why is this gun important

!!Why is this gun in its location
" />
<$action-navigate $to= {{{ [<currentTiddler>] }}} />
Edit
</$button>
<%endif%>
<$transclude tiddler=<<currentTab>> $field="text" $mode="block" />
</$list>


<$list  filter="[<currentTab>caption[History]]" >
<%if [{$:/TLS/State/EditMode!!editMode}match[true]] %>
  <$button>
     <$reveal type="match" state=<<currentTab>> text="" >
          <$action-setfield $tiddler={{{ [<currentTab>] }}} $field="text" $value="Now click the pencil icon {{$:/core/images/edit-button}} (top right hand of this record) and edit this record to add this gun's history' information below. 

Remember to delete this text first.

" />
     </$reveal>
     <$action-navigate $to= {{{ [<currentTiddler>] }}} />
Edit
     </$button>
<%endif%>
<$transclude tiddler=<<currentTab>> $field="text" $mode="block" />
</$list>

<$list  filter="[<currentTab>caption[Local History]]" >
<%if [{$:/TLS/State/EditMode!!editMode}match[true]] %>
  <$button>
     <$reveal type="match" state=<<currentTab>> text="" >
          <$action-setfield $tiddler={{{ [<currentTab>] }}} $field="text" $value="Now click the pencil icon {{$:/core/images/edit-button}} (top right hand of this record) and edit this record to add this gun's local history' information below. 

Remember to delete this text first.

" />
     </$reveal>
     <$action-navigate $to= {{{ [<currentTiddler>] }}} />
Edit
     </$button>
<%endif%>
<$transclude tiddler=<<currentTab>> $field="text" $mode="block" />
</$list>


<$list  filter="[<currentTab>caption[Gallery]]" >
<%if [{$:/TLS/State/EditMode!!editMode}match[true]] %>
<$button>
     <$reveal type="match" state=<<currentTab>> text="" >
          <$action-setfield $tiddler={{{ [<currentTab>] }}} $field="text" $value='You can add images to be displayed for this gun by adding the following line to this text, one line per image

```
<<displayICC "link to the image tiddler" "width of the image to display">>
```

For example

```
<<displayICC "WA-image-0015" "150">>
```
which will display the requested image at 150 pixels wide. For more information, [[Adding Images into Tiddlers]]

Remember to delete this text first.

 '/>
     </$reveal>
<$action-navigate $to= {{{ [<currentTiddler>] }}} />
 Edit Gallery
</$button>
<%endif%>
<$transclude tiddler=<<currentTab>> $field="text" $mode="block" />
</$list>


<$list filter="[<currentTab>caption[Map]]" >
<$reveal type="nomatch" stateTitle=<<parentID>> stateField="Longitude" text="">
     <$reveal type="nomatch" stateTitle=<<parentID>> stateField="Latitude" text="">
          <$geomap state="$:/TLS/MapState" >
       	       <$geolayer 
                   lat=<<parentLatitude>> 
                   long=<<parentLongitude>>
                 />
           </$geomap>
           <$button>
                <<displayIonly "MAP-centremap" "30" >>
                <$action-setfield $tiddler="$:/TLS/MapState" $field="lat" $value=<<parentLatitude>> />
                <$action-setfield $tiddler="$:/TLS/MapState" $field="long" $value=<<parentLongitude>> />
                 <$action-setfield $tiddler="$:/TLS/MapState" $field="zoom" $value="16" />
             </$button>
     </$reveal>
</$reveal>

</$list>


<$list  filter="[<currentTab>caption[Technical]]" >
<%if [{$:/TLS/State/EditMode!!editMode}match[true]] %>
  <$button>
     <$reveal type="match" state=<<currentTab>> text="" >
          <$action-setfield $tiddler={{{ [<currentTab>] }}} $field="text" $value="Now click the pencil icon {{$:/core/images/edit-button}} (top right hand of this record) and edit this record to add this gun's technical' information below. 

Remember to delete this text first.

" />
     </$reveal>
     <$action-navigate $to= {{{ [<currentTiddler>] }}} />
Edit
     </$button>
<%endif%>
<$transclude tiddler=<<currentTab>> $field="text" $mode="block" />
</$list>

</$let>

This is the current contents of $:/core/ui/ViewTemplate/title

\whitespace trim
\define title-styles() fill:$(foregroundColor)$;

<div class="tc-tiddler-title tc-clearfix">
	<div class="tc-titlebar">
		<span class="tc-tiddler-controls">
			<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewToolbar]!has[draft.of]] :filter[lookup[$:/config/ViewToolbarButtons/Visibility/]!match[hide]]"
				storyview="pop"
				variable="listItem"
			>
				<$set name="tv-config-toolbar-class" filter="[<tv-config-toolbar-class>] [<listItem>encodeuricomponent[]addprefix[tc-btn-]]">
					<$transclude tiddler=<<listItem>>/>
				</$set>
			</$list>
		</span>
		<$set name="tv-wikilinks" value={{$:/config/Tiddlers/TitleLinks}}>
			<$link>
				<$list filter="[<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerIconFilter]!is[draft]get[text]] +[!is[blank]]"
					variable="ignore"
				>
					<$let foregroundColor={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/TiddlerColourFilter]!is[draft]get[text]] }}}>
						<span class="tc-tiddler-title-icon" style=<<title-styles>>>
							{{||$:/core/ui/TiddlerIcon}}
						</span>
					</$let>
				</$list>
				<$transclude tiddler={{{ [<currentTiddler>] :cascade[all[shadows+tiddlers]tag[$:/tags/ViewTemplateTitleFilter]!is[draft]get[text]] :and[!is[blank]else[$:/core/ui/ViewTemplate/title/default]] }}} />
			</$link>
		</$set>
	</div>
	<$reveal tag="div" type="nomatch" text="" default="" state=<<tiddlerInfoState>> class="tc-tiddler-info tc-popup-handle" animate="yes" retain="yes">
		<$list filter="[all[shadows+tiddlers]tag[$:/tags/TiddlerInfoSegment]!has[draft.of]] [[$:/core/ui/TiddlerInfo]]" variable="listItem">
			<$transclude tiddler=<<listItem>> mode="block"/>
		</$list>
	</$reveal>
</div>

Some time ago when I was preparing a concept demonstrator, I had an exchange via this service and was informed that in many cases, display of caption overrides display of title. Many cases bit not all.

bobj

The is no mention of caption in $:/core/ui/ViewTemplate/title. Is the wiki online?

I do believe this is showing customised behaviours so we need to fix that.

Where are you doing this?

I have also tried setting the caption field to the value {{{ [{!!CommonName}] }}}

$:/core/ui/ViewTemplate/title uses a cascade based on $:/tags/ViewTemplateTitleFilterto control how the tiddler’s title is rendered.

Check $:/ControlPanel > info > advanced > cascades > View template Title to look for custom handling.

-e