Refactor code for EditTemplate fields (#9582)

* Refactored fields.tid

* Add changenote

* Optimize indentation and remove unneeded variable

* Consolidate some variables, procedures and functions

* Streamlined conditional and reveal structures

* Eliminate the fieldmangler widget

* Add tc-edit-field-exists to new field name input if applicable

* Call save-tiddler-actions on Ctrl-Enter in name input field
This commit is contained in:
yaisog
2026-02-04 11:13:53 +00:00
committed by GitHub
parent 2e76cc08a1
commit 42a3928960
2 changed files with 175 additions and 141 deletions
+165 -141
View File
@@ -1,157 +1,181 @@
title: $:/core/ui/EditTemplate/fields
tags: $:/tags/EditTemplate
\procedure lingo-base() $:/language/EditTemplate/
\function tf.config-title() [[$:/config/EditTemplateFields/Visibility/]addsuffix[$(currentField)$]substitute[]get[text]]
\function tf.config-filter() [[hide]] :except[title<tf.config-title>]
<!-- Beware this is duplicated from EditTemplate.tid. For details see bug #7054 -->
\procedure get-field-value-tiddler-filter() [subfilter<get-field-editor-filter>sha256[16]addprefix[/]addprefix<newFieldValueTiddlerPrefix>]
\procedure get-field-editor-filter() [<newFieldNameTiddler>get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
\procedure prefix.bracket() [
\procedure suffix.bracket() ]
\function tf.current-tiddler-new-field-selector() [[data-tiddler-title=]addprefix[$(prefix.bracket)$]substitute[]addsuffix<currentTiddlerCSSescaped>addsuffix[$(suffix.bracket)$]substitute[]] .tc-edit-field-add-name-wrapper input :and[join[ ]]
\procedure new-field-actions()
\whitespace trim
<$action-sendmessage $message="tm-add-field" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldNameTiddler>get[text]] :map[subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
</$set>
<$action-sendmessage $message="tm-focus-selector" $param=<<tf.current-tiddler-new-field-selector>>/>
\end
\procedure lingo-base() $:/language/EditTemplate/
\procedure delete-state-tiddlers() <$action-deletetiddler $filter="[<newFieldNameTiddler>] [<storeTitle>] [<searchListState>]"/>
\procedure cancel-search-actions-inner()
\whitespace trim
<$list
filter="[<storeTitle>has[text]] [<newFieldNameTiddler>has[text]]"
variable="ignore"
emptyMessage="<<cancel-delete-tiddler-actions 'cancel'>>">
<<delete-state-tiddlers>>
</$list>
\procedure focus-new-field-input() <$action-sendmessage $message="tm-focus-selector" $param=`[data-tiddler-title="$(storyTiddler)$"] .tc-edit-field-add-name-wrapper input` />
\procedure new-field-actions()
<$action-setfield $tiddler=<<storyTiddler>> $field={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldValueTiddler>get[text]] }}} />
<$action-deletetiddler $filter="[prefix[$:/temp/NewFieldValue]prefix<newFieldValueTiddlerPrefix>]"/>
<<delete-state-tiddlers>>
<<focus-new-field-input>>
\end
\procedure delete-field-actions()
<$action-deletefield $field=<<currentField>>/>
<<focus-new-field-input>>
\end
\procedure cancel-search-actions()
\whitespace trim
<$set name="userInput" value={{{ [<storeTitle>get[text]] }}}>
<$list
filter="[<newFieldNameTiddler>get[text]!match<userInput>]"
emptyMessage="<<cancel-search-actions-inner>>">
<$action-setfield $tiddler=<<newFieldNameTiddler>> text=<<userInput>>/><$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
</$list>
</$set>
<$let userInput={{{ [<storeTitle>get[text]] }}}>
<%if [<newFieldNameTiddler>get[text]!match<userInput>] %>
<$action-setfield $tiddler=<<newFieldNameTiddler>> text=<<userInput>>/>
<$action-setfield $tiddler=<<refreshTitle>> text="yes"/>
<%else%>
<%if [<storeTitle>has[text]] [<newFieldNameTiddler>has[text]] %>
<<delete-state-tiddlers>>
<%else%>
<<cancel-delete-tiddler-actions 'cancel'>>
<%endif%>
<%endif%>
</$let>
\end
\procedure new-field()
\whitespace trim
<$vars name={{{ [<newFieldNameTiddler>get[text]] }}}>
<$reveal type="nomatch" text="" default=<<name>>>
<$button tooltip={{$:/language/EditTemplate/Fields/Add/Button/Hint}}>
<$action-sendmessage $message="tm-add-field"
$name=<<name>>
$value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
</$set>
<<lingo Fields/Add/Button>>
</$button>
</$reveal>
<$reveal type="match" text="" default=<<name>>>
<$button>
<<lingo Fields/Add/Button>>
</$button>
</$reveal>
</$vars>
<%if [<newFieldNameTiddler>get[text]!is[blank]] %>
<$button actions="<<new-field-actions>>" tooltip={{$:/language/EditTemplate/Fields/Add/Button/Hint}}>
<<lingo Fields/Add/Button>>
</$button>
<%else%>
<$button>
<<lingo Fields/Add/Button>>
</$button>
<%endif%>
\end
\whitespace trim
<$set name="newFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
<div class="tc-edit-fields">
<table class={{{ [all[current]fields[]] :filter[lookup[$:/config/EditTemplateFields/Visibility/]!match[hide]] :and[count[]!match[0]] :and[then[tc-edit-fields]] :else[[tc-edit-fields tc-edit-fields-small]] }}}>
<tbody>
<$list filter="[all[current]fields[]] :and[sort[title]]" variable="currentField" storyview="pop">
<$list filter=<<tf.config-filter>> variable="temp">
<tr class="tc-edit-field">
<td class="tc-edit-field-name">
<$text text=<<currentField>>/>:</td>
<td class="tc-edit-field-value">
<$keyboard key="((delete-field))" actions="""<$action-deletefield $field=<<currentField>>/><$set name="currentTiddlerCSSescaped" value={{{ [<currentTiddler>escapecss[]] }}}><$action-sendmessage $message="tm-focus-selector" $param=<<tf.current-tiddler-new-field-selector>>/></$set>""">
<$transclude tiddler={{{ [<currentField>] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}] }}} />
</$keyboard>
</td>
<td class="tc-edit-field-remove">
<$button class="tc-btn-invisible" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}>
<$action-deletefield $field=<<currentField>>/>
{{$:/core/images/delete-button}}
</$button>
</td>
</tr>
</$list>
</$list>
</tbody>
</table>
</div>
\function tf.config-filter() [lookup:show[$:/config/EditTemplateFields/Visibility/]!match[hide]]
<$fieldmangler>
<div class="tc-edit-field-add">
<em class="tc-edit tc-small-gap-right">
<<lingo Fields/Add/Prompt>>
</em>
<$vars refreshTitle=<<qualify "$:/temp/fieldname/refresh">> storeTitle=<<newFieldNameInputTiddler>> searchListState=<<newFieldNameSelectionTiddler>>>
<div class="tc-edit-field-add-name-wrapper">
<$transclude $variable="keyboard-driven-input" tiddler=<<newFieldNameTiddler>> storeTitle=<<storeTitle>> refreshTitle=<<refreshTitle>>
selectionStateTitle=<<searchListState>> tag="input" default="" placeholder={{$:/language/EditTemplate/Fields/Add/Name/Placeholder}}
focusPopup=<<qualify "$:/state/popup/field-dropdown">> class="tc-edit-texteditor tc-popup-handle" tabindex={{$:/config/EditTabIndex}}
focus={{{ [{$:/config/AutoFocus}match[fields]then[true]] :else[[false]] }}} cancelPopups="yes"
configTiddlerFilter="[[$:/config/EditMode/fieldname-filter]]" inputCancelActions=<<cancel-search-actions>> />
<$button popup=<<qualify "$:/state/popup/field-dropdown">> class="tc-btn-invisible tc-btn-dropdown tc-small-gap" tooltip={{$:/language/EditTemplate/Field/Dropdown/Hint}} aria-label={{$:/language/EditTemplate/Field/Dropdown/Caption}}>{{$:/core/images/down-arrow}}</$button>
<$reveal state=<<qualify "$:/state/popup/field-dropdown">> type="nomatch" text="" default="">
<div class="tc-block-dropdown tc-edit-type-dropdown">
<$set name="tv-show-missing-links" value="yes">
<$linkcatcher to=<<newFieldNameTiddler>>>
<div class="tc-dropdown-item">
<<lingo Fields/Add/Dropdown/User>>
</div>
<$set name="newFieldName" value={{{ [<storeTitle>get[text]] }}}>
<$list filter="[!is[shadow]!is[system]fields[]search:title<newFieldName>sort[]] :except[[created]] :except[[creator]] :except[[draft.of]] :except[[draft.title]] :except[[modified]] :except[[modifier]] :except[[tags]] :except[[text]] :except[[title]] :except[[type]]" variable="currentField">
<$list filter="[<currentField>addsuffix[-primaryList]] :except[<searchListState>get[text]]" emptyMessage="""<$link to=<<currentField>> class="tc-list-item-selected"><$text text=<<currentField>>/></$link>""">
<$link to=<<currentField>>>
<$text text=<<currentField>>/>
</$link>
</$list>
</$list>
<div class="tc-dropdown-item">
<<lingo Fields/Add/Dropdown/System>>
</div>
<$list filter="[fields[]search:title<newFieldName>sort[]] :except[!is[shadow]!is[system]fields[]]" variable="currentField">
<$list filter="[<currentField>addsuffix[-secondaryList]] :except[<searchListState>get[text]]" emptyMessage="""<$link to=<<currentField>> class="tc-list-item-selected"><$text text=<<currentField>>/></$link>""">
<$link to=<<currentField>>>
<$text text=<<currentField>>/>
</$link>
</$list>
</$list>
</$set>
</$linkcatcher>
</$set>
</div>
</$reveal>
</div>
<$let currentTiddlerCSSescaped={{{ [<currentTiddler>escapecss[]] }}} currentTiddler={{{ [subfilter<get-field-value-tiddler-filter>] }}} currentField="text" currentFieldName={{{ [<newFieldNameTiddler>get[text]] }}}>
<span class="tc-edit-field-add-value tc-small-gap-right">
<$keyboard key="((add-field))" actions=<<new-field-actions>>>
<$transclude tiddler={{{ [subfilter<get-field-editor-filter>] }}} />
</$keyboard>
</span>
<span class="tc-edit-field-add-button">
<$transclude $variable="new-field"/>
</span>
</$let>
</$vars>
</div>
</$fieldmangler>
</$set>
\function tf.field-cascade()
[<currentField>]
:cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]]
:and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
\end
\function tf.get-field-editor()
[<newFieldNameTiddler>get[text]else[]]
:cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]]
:and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
\end
\function tf.primary-list-exceptions() created creator draft.of draft.title modified modifier tags text title type
\function tf.list-selection-class(listSuffix) [<searchListState>get[text]removesuffix<listSuffix>match<currentField>then[tc-list-item-selected]]
<$let newFieldValueTiddlerPrefix={{{ [<newFieldValueTiddlerPrefix>!is[blank]else<qualify "$:/temp/NewFieldValue">] }}} >
<div class="tc-edit-fields">
<!-- table of user fields of the current tiddler -->
<table class=`tc-edit-fields ${ [all[current]fields[]] :filter[tf.config-filter[]] :and[count[]match[0]then[tc-edit-fields-small]] }$`>
<tbody>
<$list filter="[all[current]fields[]] :and[sort[title]]" variable="currentField" storyview="pop">
<%if [<currentField>tf.config-filter[]] %>
<tr class="tc-edit-field">
<td class="tc-edit-field-name">
<$text text=<<currentField>>/>:
</td>
<td class="tc-edit-field-value">
<$keyboard key="((delete-field))" actions="<<delete-field-actions>>">
<$transclude tiddler=<<tf.field-cascade>> />
</$keyboard>
</td>
<td class="tc-edit-field-remove">
<$button actions="<<delete-field-actions>>"
aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}
class="tc-btn-invisible"
tooltip={{$:/language/EditTemplate/Field/Remove/Hint}}
>
{{$:/core/images/delete-button}}
</$button>
</td>
</tr>
<%endif%>
</$list>
</tbody>
</table>
</div>
<!-- input control for new field name with selection dropdown -->
<div class="tc-edit-field-add">
<em class="tc-edit tc-small-gap-right">
<<lingo Fields/Add/Prompt>>
</em>
<$let refreshTitle=<<qualify "$:/temp/fieldname/refresh">>
storeTitle=<<newFieldNameInputTiddler>>
searchListState=<<newFieldNameSelectionTiddler>>
>
<div class="tc-edit-field-add-name-wrapper">
<$transclude $variable="keyboard-driven-input"
cancelPopups="yes"
class=`tc-edit-texteditor tc-popup-handle ${ [<newFieldNameTiddler>get[text]] :intersection[<storyTiddler>fields[]] :then[[tc-edit-field-exists]] }$`
configTiddlerFilter="[[$:/config/EditMode/fieldname-filter]]"
default=""
focus={{{ [{$:/config/AutoFocus}match[fields]then[true]] :else[[false]] }}}
focusPopup=<<qualify "$:/state/popup/field-dropdown">>
inputAcceptVariantActions=<<save-tiddler-actions>>
inputCancelActions=<<cancel-search-actions>>
placeholder={{$:/language/EditTemplate/Fields/Add/Name/Placeholder}}
refreshTitle=<<refreshTitle>>
selectionStateTitle=<<searchListState>>
storeTitle=<<storeTitle>>
tag="input"
tabindex={{$:/config/EditTabIndex}}
tiddler=<<newFieldNameTiddler>>
/>
<$button aria-label={{$:/language/EditTemplate/Field/Dropdown/Caption}}
class="tc-btn-invisible tc-btn-dropdown tc-small-gap"
popup=<<qualify "$:/state/popup/field-dropdown">>
tooltip={{$:/language/EditTemplate/Field/Dropdown/Hint}}
>
{{$:/core/images/down-arrow}}
</$button>
<$reveal state=<<qualify "$:/state/popup/field-dropdown">> type="nomatch" text="" default="" tag="div" class="tc-block-dropdown tc-edit-type-dropdown">
<$let tv-show-missing-links="yes">
<$linkcatcher to=<<newFieldNameTiddler>>>
<div class="tc-dropdown-item">
<<lingo Fields/Add/Dropdown/User>>
</div>
<$let newFieldName={{{ [<storeTitle>get[text]] }}}
primaryListFields={{{ [!is[shadow]!is[system]fields[]format:titlelist[]join[ ]] }}}
>
<$list filter="[enlist<primaryListFields>search:title<newFieldName>sort[]] :except[tf.primary-list-exceptions[]]" variable="currentField">
<$link to=<<currentField>> class=<<tf.list-selection-class "-primaryList">> >
<$text text=<<currentField>>/>
</$link>
</$list>
<div class="tc-dropdown-item">
<<lingo Fields/Add/Dropdown/System>>
</div>
<$list filter="[fields[]search:title<newFieldName>!enlist<primaryListFields>sort[]]" variable="currentField">
<$link to=<<currentField>> class=<<tf.list-selection-class "-secondaryList">>>
<$text text=<<currentField>>/>
</$link>
</$list>
</$let>
</$linkcatcher>
</$let>
</$reveal>
</div>
<!-- input control for new field content -->
<$let currentFieldName={{{ [<newFieldNameTiddler>get[text]] }}}
fieldEditor=<<tf.get-field-editor>>
newFieldValueTiddler={{{ [<newFieldValueTiddlerPrefix>] [[/]] [<fieldEditor>sha256[16]] :and[join[]] }}}
currentTiddler=<<newFieldValueTiddler>>
>
<span class="tc-edit-field-add-value tc-small-gap-right">
<$keyboard key="((add-field))" actions="<<new-field-actions>>">
<$transclude $tiddler=<<fieldEditor>> />
</$keyboard>
</span>
<span class="tc-edit-field-add-button">
<$transclude $variable="new-field"/>
</span>
</$let>
</$let>
</div>
</$let>
@@ -0,0 +1,10 @@
title: $:/changenotes/5.4.0/#9582
description: Refactor code for EditTemplate fields
release: 5.4.0
tags: $:/tags/ChangeNote
change-type: enhancement
change-category: internal
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9582
github-contributors: yaisog
Refactored the EditTemplate fields.tid template to improve code maintainability and readability