The Good and Bad of Qualify

189 views
Skip to first unread message

Mohammad

unread,
Feb 6, 2020, 3:17:07 AM2/6/20
to TiddlyWiki

The qualify macro is an important part of the StateMechanism.

It returns a unique string that encodes its position within the widget tree, as identified by the stack of transcluded tiddlers that lead to that position.


ISSUES
It is true that qualify should returns a unique, but considering transclusion in Tiddlywiki it cause confusion!

  • I have attached a test set and you can simple drag and drop into Tiddlywiki.com to evaluate by yourself
  • The test uses a edit widget to get some input from user in a tiddler "Test Qualify"
  • This tiddler transcluded in different places, each place shows a different result
  • This force very restricted use case for qualify and one should take care how and where used qualify macro!

What do you think?

--Mohammad
Test-Qualify.json

Mohammad

unread,
Feb 6, 2020, 3:38:25 AM2/6/20
to TiddlyWiki
Some old discussions


The issue is with transclusion!
Transclusion is one the unique feature of TW, and this qualify causes confusion!
One solution is to use separate state tiddler manually and restrict to use of qualify to cases like popup state, dropdown state, ...

--Mohammad

TonyM

unread,
Feb 6, 2020, 5:02:33 AM2/6/20
to TiddlyWiki
Mohammad

A large part of the factors used to create a qualified name is the tiddler name. Thus it depends on what current Tiddler value is.

It is designed to generate a unique and reproducible qualification on a per tiddler and title.

I have developed a tiddlyserial number that issues a unique serial number to each tiddler on first save. This is a better qualifyer as it never changes after assignment regardless of the title.

I hope to publish soon, perhaps on the weekend.

Another simpler way is to just use the title which is unique by definition and add a prefix

New tiddler = $:/qualified/$(currentTiddler)$

Does this help?

Mohammad

unread,
Feb 6, 2020, 5:09:52 AM2/6/20
to TiddlyWiki
Hi Tony!
I partially solved the problem using a similar approach! I learned NOT to use qualify when it seems the content may be used elsewhere through transclusion or in a tabs macro or like that!

 

Does this help?


Thanks 

PMario

unread,
Feb 6, 2020, 8:21:40 AM2/6/20
to TiddlyWiki
On Thursday, February 6, 2020 at 9:17:07 AM UTC+1, Mohammad wrote:

The qualify macro is an important part of the StateMechanism.

Not really. The state mechanism works perfectly fine, without the qualify macro. The <<qualify>> macro solves a very special usecase. It was built to create unique names for templates used in the core UI.
 
It returns a unique string that encodes its position within the widget tree, as identified by the stack of transcluded tiddlers that lead to that position.

That's right. This behaviour is intended. AND it means: "As soon as the <<qualify xxx>> code is transcluded, it will create a _different_ string!"
That's the only thing your examples show and that's intended.
 
ISSUES
It is true that qualify should returns a unique, but considering transclusion in Tiddlywiki it cause confusion!

I think it doesn't do what you expect and that produces confusion. You can't use qualify in your examples as you do, because of the nature of qualify. So you use it in the wrong way.
  • This force very restricted use case for qualify and one should take care how and where used qualify macro!
That's true.

It should be used only where it solves the problem it was designed for.

There are some rules that you found out and some you missed.

1) <<qualify baseName>> only creates the same name if it is called within the same tiddler
2) If a qualify state name should survive transclusion in needs to be written to a variable
3) If you need human predictable state-names, you need to create them on your own
4) If <<qualify>> causes problems, you probably can't use it.

add 1)
If you have a look at the TW core code which uses the <<qualify xxx>> macro you'll find this pattern:

<$button popup=...> ... <$reveal state=...>  OR <$button set=...> ... <$reveal state=...>


<$button popup=<<qualify "$:/state/popup/tag">> ...>

and some lines later you'll find:

<$reveal state=<<qualify "$:/state/popup/tag">> type="popup" ... />

add 2)
Whenever a transclusion is used later in the code <<qualify xxx>> output is set to a variable.

<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>>
.....
</$vars>

The transcluded templates need to use the variable names instead of the macro. above eg: tiddlerInfoState

add 3)
Either use 2)  or create it like this:

\define folded-state()
$:/state/folded/$(currentTiddler)$
\end
<$vars storyTiddler=<<currentTiddler>> ....>>
.....
</$vars>

See: folded-state also from: $:/core/ui/ViewTemplate
Internally variables and \define xx() are handled very similar.

add 4)
see add 3)

------------------------

More to follow ....

have fun!
mario

PMario

unread,
Feb 6, 2020, 8:42:06 AM2/6/20
to TiddlyWiki
Hi,

There is one more problem with the <<qualify>> macro, which is different to your description. ... and I'll try to create a PR which fixes it soon.

Problem: Whenever an existing core utility uses <<qualify xxx>> macro human users are screwed, if they want to provide a "user state" which is already unique.

... eg: <<tabs>> macro.

The tabs macro has a signature like this:

\define tabs(tabsList,default,state:"$:/state/tab",class,template,buttonTemplate,retain)

The default state parameter is set to $:/state/tab. This makes it convenient for new users, since they don't need to deal with state uniqueness. Later in the code it looks like this:

<$button set=<<qualify "$state$">> ....
...
<$reveal type="match" state=<<qualify "$state$">> ...

But now the problem is: If I do want to call the tabs macro like so:

<<tabs state:"human/predictable/unique/state" .... >> ... The tabs macro will screw it !!!

This problem was introduced with the introduction of the <<qualify>> macro. .. What we need is <<qualify title:xxxx isUnique:yes>> which tells the macro, that the incoming title is already unique and it should use it.

This won't solve your OP problems, but it may probably solve some for Tony's.

I'll try to create a PR for this very soon.

have fun!
mario

Mohammad

unread,
Feb 6, 2020, 9:49:50 AM2/6/20
to TiddlyWiki
Mario,
Many thanks for your clarifications. This worth to be added to documentation.

 I have explained the situation in Shiraz plugin, where it uses qualify to create state tiddlers with unique name.
I explained how to transclude tiddlers have dynamic tables and use them in tabs macro!

Best
Mohammad

Mat

unread,
Feb 6, 2020, 11:45:42 AM2/6/20
to TiddlyWiki
Side note:
As I briefly note in the slugify request, I think we could use slugs, instead of cryptic numbers, for qualify. This should make the "logic" of the mechanism more transparent e.g: HelloThere-working-with-tiddlywiki and HelloThere-customize-tiddlywiki (i.e this clearly shows which is the surrounding tiddler). And it would be possible to construct qualified tiddlers without the state mechanism by using a slugify operator - for example it would be much simpler to conditionally steer/control a qualified title.

<:-)

Mohammad

unread,
Feb 6, 2020, 11:56:20 AM2/6/20
to TiddlyWiki
Hi Mat,
 I closely follow your PR on the GitHub!

--Mohammad

Joshua Fontany

unread,
Feb 8, 2020, 9:26:15 PM2/8/20
to tiddl...@googlegroups.com
Hi guys,

The Qualify Macro & the javascript version, the Widget class' "this.getStateQualifier()" method are key to differentiating WHERE within the total widget tree the current widget/tiddler is located. It allows me to build a state tiddler for the CSV Widget render-er as below during the "this.execute()" method:

```
 var title = this.getAttribute("tiddler"this.getVariable("currentTiddler")),
        stateTitle = "$:/widgets/csv/" + title + this.getStateQualifier();
    this.stateTiddler = $tw.wiki.getTiddler(stateTitle);
    if(!this.stateTiddler){ //Build stateTiddler Fields and save it
```
When the widget code is called - when a tiddler with type: application/csv is displayed in the story river - it generated a different state-value than if that tiddler was transcluded through another tidder. This means the UI settings, such as how many rows-per page, and which page you are on, can be different values - and it is all handled appropriately behind the scenes. Because I transclude other tiddlers with wiki-code when I build the CSV table html, I manually set a `<<stateTiddler>>` value in javascript that can then be accessed by anything rendered WITHIN the widget.

I have demos of this behavior in my latest JsonMangler demo wiki:

https://joshuafontany.github.io/TW5-JsonMangler/

Open the "Csv/vgsales" tiddler is open on launch. In the Recents sidebar tab there is a tiddler named "CSV Transclude Test". Open that. Manipulate each UI indepenetendly (open the CSV file icon at the top of the table for full options).

Best,
Joshua Fontany
Reply all
Reply to author
Forward
0 new messages