Formatting based on field value

218 views
Skip to first unread message

Jake

unread,
Jul 18, 2020, 10:38:48 AM7/18/20
to TiddlyWiki
Thanks everyone for the previous answer, but I have another small question. I've searched the forum, but couldn't find the answer.

So, the question is rather simple. Is it possible to automatically apply formatting to the field in the text based on its value?
For example: I have a field "rating" with values from 0 to 100. I want to show it in green if it's above 70, in grey if it's between 50 and 70 and in red if it's below 50. 

To simply show field value in a text would be:
Rating: {{!!rating}}

But is it possible to automatically apply the said (or any other) formatting based on its value? Should I use some "compare" and "then" attributes?

Mat

unread,
Jul 18, 2020, 10:53:01 AM7/18/20
to TiddlyWiki
Fun little task.
You might want some additional style tweaking but here's how you can do it:

\define rating() Rating <span style="background-color:$(color)$">{{!!rating}}</span>

<$list filter="[{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]" variable=color>
<<rating>>
</$list>

<:-)

Jake

unread,
Jul 18, 2020, 12:03:44 PM7/18/20
to TiddlyWiki
Hmmm.... soooo... do I get it right, that in order not to type all that "list" thing each time I need to make 2 macros? 1st would be kinda "technical" macro <<rating-style>>
\define rating-style() <span style="font-size: 1.2em; font-weight: 500; color:$(color)$">{{!!rating}}</span>

and the second marco, smth like <<rating>>:
\define rating()
<$list filter="[{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]" variable=color>
<<rating-style>>
</$list>
\end

and the usage like: 
Rating (or whatever text): <<rating>>?

Mat

unread,
Jul 18, 2020, 12:22:48 PM7/18/20
to TiddlyWiki

Hmmm.... soooo... do I get it right, that in order not to type all that "list" thing each time I need to make 2 macros?

No, it could all be in one code if it weren't for the fact that "background-color:" can't take <<...>> as an argument but it can take $(...)$ as an argument. I'm not quite sure why. So it's a CSS syntax thing, not really a logic thing.

<:-)

Mat

unread,
Jul 18, 2020, 12:28:38 PM7/18/20
to TiddlyWiki
Maybe I answered in an incomplete way: If you want the outer code, i.e the listwidget, to be a macro then you would do as you correctly propose. But the reason so split it up into two macros is only because that css bit can't handle <<...>> as an argument.

<:-)

Jake

unread,
Jul 18, 2020, 3:13:04 PM7/18/20
to TiddlyWiki
Maybe I answered in an incomplete way: If you want the outer code, i.e the listwidget, to be a macro then you would do as you correctly propose. But the reason so split it up into two macros is only because that css bit can't handle <<...>> as an argument.

Can it be done via some "var" thingy?

Mat

unread,
Jul 18, 2020, 3:32:57 PM7/18/20
to TiddlyWiki
Jake wrote:
Can it be done via some "var" thingy?

A bit unclear what you mean. There is a variable created and named in my proposed code, i.e the "variable=color" bit. This variable gets the value that comes out from the filter.  Something like $vars would do a similar thing if you use it like

<$vars color={{{ the filter }}} >

...but you'd still have to put that color in the context of the "span" thingy.

BUT, come to think of it, you can actually do this:

<$vars style={{{ [{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]] +[addprefix[color:]]" }}} >
Rating <span style=<
<style>>>{{!!rating}}</span>
</$vars>

I.e the span style attribute does accept <<...>> so made the filter output a full css declaration rather than just the properytvalue.

<:-)

Jake

unread,
Jul 19, 2020, 12:36:08 AM7/19/20
to tiddl...@googlegroups.com
 
Hmmm.... soooo... do I get it right, that in order not to type all that "list" thing each time I need to make 2 macros?

No, it could all be in one code if it weren't for the fact that "background-color:" can't take <<...>> as an argument but it can take $(...)$ as an argument. I'm not quite sure why. So it's a CSS syntax thing, not really a logic thing.

 
B-but... why it needs a macro inside? why it can't be just: 

<$list filter="[{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]" variable=color>
Rating <span style="color:$(color)$">{{!!rating}}</span>
</$list>

or 

<$list filter="[{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]" variable=color</$list>
Rating <span style="color:$(color)$">{{!!rating}}</span>

or 

<$vars color={{{ [{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]}}} >
Rating <span style="color:$(color)$">{{!!rating}}</span>
</$vars>

?

is it because ideally it should be
<$vars color={{{ [{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]}}} >
Rating <span style="color:<<color>>">{{!!rating}}</span>
</$vars>

but you can't do <<>> inside a style and the only way to use variable inside it is via $_$ and you can do that only inside separate macro and you can't call a variable with $_$ anywhere other than macro?

Mat

unread,
Jul 19, 2020, 5:07:46 AM7/19/20
to TiddlyWiki
 
B-but... why it needs a macro inside?

That last solution of mine did not have any macro. A macro is a separate "codelet" that starts with "\definition". 
 
why it can't be just: 

<$list filter="[{!!rating}compare:integer:gt[70]then[green]] ~[{!!rating}compare:integer:gt[50]then[grey]] ~[[red]]" variable=color>
Rating <span style="color:$(color)$">{{!!rating}}</span>
</$list>

OK, first, I agree that it ought to be possible to directly insert the color into the span thing. Again, my last solution did kind of do this. But there are a few issues with the code you write here above:

I'll get to your exact syntax but first, here is a syntax that is "more correct but still faulty":

...
Rating <span style="color:<<color>>">{{!!rating}}</span>
...

The <<..>> syntax is the basic way to call a variable. I suspect this doesn't work here because the span reads this one: <<color>>  as if it was the closing angle bracket of the span tag. So this is why I, in my initial solution, split out the whole span out into a macro.

But you ask why $(...)$ doesn't work. This is because $(..)$ is the syntax to call a variable when you are in a place where the variable was not created. To see the difference, test this:

\define mymacro()
<$vars fruit=banana>
This says banana: <<fruit>><br>
This says apple: $(fruit)$
</$vars>
\end

<$vars fruit=apple>
This says apple: <<fruit>><br>
<<mymacro>>
</
$vars>

If you do this (no macro)

<$vars fruit=apple>
This says apple: $(fruit)$
</$vars>

...you don't get anything because it is simply not the syntax to use when calling the variable. It should be <<fruit>>.

Your examples also imply a question on the difference between $list and $vars. For this specific case, the output from the filter is only one value so you can use either, as in your examples. $vars sets a variable to be a specific value whereas $list sets a variable to be one value at a time from a list of values.

Hope this clarifies.

<:-)

Jake

unread,
Jul 20, 2020, 8:18:27 AM7/20/20
to tiddl...@googlegroups.com
Hmmm... I think I get... some of that... me thinks.... :)  I also just thought that "define" is possible only as part of marco (https://tiddlywiki.com/#Pragma) and only one define per macro is possible (the one that starts at the very beginning of tiddler), but that's not that important.

In the end I decided to use your second option like:

\define rating()
<$vars style={{{ [{!!rating}compare:number:gteq[7]then[green]] ~[{!!rating}compare:number:gteq[5]then[grey]] ~[[red]] +[addprefix[font-size: 1.5em; font-weight: 500; color:]]" }}} >
<span style=<<style>>>{{!!rating}}</span>
</$vars>
\end

since 1 macro is better than 2 macros :)  and I can put any kind of css formatting inside the "addprefix" stuff.

But I have one more little questing, since we touched the Compare operator... I read this compare Operator, this Filter Syntax and this ListWidget, but I still don't get it... :)

I still have no idea how to make compare operator work with field values inside a list widget?

For example I have a list filtered by some tag and I want to add condition to show only tiddlers that have some date older than 20200701 and filter them by that date.
So if I have a working list

<$list filter="[tag[Comedy]!sort[releasedate]]> <$link/> |  </$list>

and I want to add additional filter condition. if to do it in accordance with the above example if should be smth like: [{!!releasedate}compare:date:gr[20200701]] 

but why doesn't this thing work:
<$list filter="[tag[Comedy]] +[{!!releasedate}compare:date:gr[20200701]] +[!sort[releasedate]]"> <$link/> |  </$list>  ?

I tried experimenting with brackets, but haven't managed to achieve anything. :(


 

Mat

unread,
Jul 20, 2020, 9:17:11 AM7/20/20
to TiddlyWiki
Jake wrote:
Hmmm... I think I get... some of that... me thinks.... :)  I also just thought that "define" is possible only as part of marco (https://tiddlywiki.com/#Pragma) and only one define per macro is possible (the one that starts at the very beginning of tiddler), but that's not that important.

Oh, understanding this is very important. The "\define" pragma is what starts a macro. It can be a single line macro or it can be a multiline macro in which case it also needs an "\end". You can have an unlimited number of macros in one tiddler. All pragmas just need to be grouped at the top. Just check out some system tiddlers and you'll see this.

since 1 macro is better than 2 macros :)  and I can put any kind of css formatting inside the "addprefix" stuff.

Well, there's nothing wrong with macros. It's just that sometimes you're forced to use a macro which you might not have wanted to, were it possible to avoid it. Perhaps mostly for "overviewability".
 

[{!!releasedate}compare:date:gr[20200701]] 

After some testing I can only say I agree. Why on earth doesn't that work??? I also tried

<$vars date={{!!modified}}>
{{{ [[20220701]compare:date:gr
<date>] }}}
</$vars>

but this doesn't help. Maybe it's a bug.

If nobody answers here, I suggest you start a new thread and ask it.

@anybody - ?

<:-)

Eric Shulman

unread,
Jul 20, 2020, 9:44:43 AM7/20/20
to tiddl...@googlegroups.com
On Monday, July 20, 2020 at 6:17:11 AM UTC-7, Mat wrote:
After some testing I can only say I agree. Why on earth doesn't that work??? I also tried

<$vars date={{!!modified}}>
{{{ [[20220701]compare:date:gr
<date>] }}}
</$vars>

Three things:
1) The "greater than" compare suffix mode is "gt"... not "gr" !!!
2) If you are comparing against a date value like {{!!modified}}, you need to specify the full 17-digit value
3) The filter you used in your example will return the literal value, not the <date> variable.

Try this:
<$vars date={{!!modified}}>
{{{ [[20220701000000000]compare:date:gt
<date>then<date>] }}}
</$vars>
which means: if <date> is greater than [20220701000000000], result = <date>

or this:
{{{ [{!!modified}compare:date:lteq[20220701000000000]] }}}
which means: if [20220701000000000] is less than or equal to {{!!modified}}, result = {{!!modified}}

enjoy,
-e


Mat

unread,
Jul 20, 2020, 10:05:00 AM7/20/20
to TiddlyWiki
Eric Shulman wrote:
1) The "greater than" compare suffix mode is "gt"... not "gr" !!!

Doh!
 
2) If you are comparing against a date value like {{!!modified}}, you need to specify the full 17-digit value

Are you sure? This seems to work: {{{ [[20220701]compare:date:gt{!!modified}] }}}
 
3) The filter you used in your example will return the literal value, not the <date> variable.

While I believe you, it does seem to produce the desired result.

Thank you. 

...mumble mumble... gt... not gr... gollum stupid.... mumble mumble... ;-)

<:-)

Jake

unread,
Jul 20, 2020, 10:18:57 AM7/20/20
to TiddlyWiki

og_og_1485180781287968971[1].jpg

guys... guys... and to put it inside a $list?.. and to combine it with... a tag thing... and a sort thing...

ps. btw, if i use only YYYYMMDD format for dates - can I use just "integer" then as comparison type?

Mat

unread,
Jul 20, 2020, 10:26:09 AM7/20/20
to TiddlyWiki
Jake wrote:
guys... guys... and to put it inside a $list?.. and to combine it with... a tag thing... and a sort thing...

ps. btw, if i use only YYYYMMDD format for dates - can I use just "integer" then as comparison type?

Did you at all test it before asking others?

<:-) 

Jake

unread,
Jul 20, 2020, 10:29:06 AM7/20/20
to tiddl...@googlegroups.com
Yep, I did: nothing worked... ¯\_(ツ)_/¯

otherwise: why would I ask?.. i warned everyone: that's a newbie question. :)
 
PS. I still have no idea how to put compare filter into the $list (though I'm sorry for the gr/gt mistake)

Eric Shulman

unread,
Jul 20, 2020, 10:53:26 AM7/20/20
to TiddlyWiki
On Monday, July 20, 2020 at 7:05:00 AM UTC-7, Mat wrote:
2) If you are comparing against a date value like {{!!modified}}, you need to specify the full 17-digit value

Are you sure? This seems to work: {{{ [[20220701]compare:date:gt{!!modified}] }}}

OK... I guess that does work because it is a "date" compare, and the literal value
[20220701] is automatically padded with zeros before being compared to the
{!!modified}} value (which has the full 17-digit date number)

-e

Eric Shulman

unread,
Jul 20, 2020, 11:29:53 AM7/20/20
to TiddlyWiki
On Monday, July 20, 2020 at 7:18:57 AM UTC-7, Jake wrote:


guys... guys... and to put it inside a $list?.. and to combine it with... a tag thing... and a sort thing...
ps. btw, if i use only YYYYMMDD format for dates - can I use just "integer" then as comparison type? 

Try this:
<$list filter="[tag[Comedy]!sort[releasedate]]" variable="title">
   <$list filter="[
<title>get[releasedate]compare:integer:lteq[20200701]then<title>]">
      <$link/> |
   </$list>
</$list>

The outer $list gets the titles of the tiddlers with the desired tag, sorted in descending order by releasedate
The inner $list compares each releasedate to see if it is less than or equal to [20200701] and returns the title

-e

Jake

unread,
Jul 20, 2020, 12:03:52 PM7/20/20
to tiddl...@googlegroups.com

 
Try this:
<$list filter="[tag[Comedy]!sort[releasedate]]" variable="title">
   <$list filter="[
<title>get[releasedate]compare:integer:lteq[20200701]then<title>]">
      <$link/> |
   </$list>
</$list>

The outer $list gets the titles of the tiddlers with the desired tag, sorted in descending order by releasedate
The inner $list compares each releasedate to see if it is less than or equal to [20200701] and returns the title

Yes! This works! I ended with smth like this:

<$list filter="[tag[Comedy]!sort[releasedate
]]" variable="title">
<$list filter="[
<title>get[releasedate]compare:integer:gteq[20200701]then<title>]">

<ul> <li> <$link/> <$transclude tiddler={{{ [<currentTiddler>get[rating]addsuffix[-icon]] }}} /> (<$view field="releasedate" format="date" template="0DD.0MM.YYYY"/>) </li> </ul>  

</$list>
</$list>

It happened to be much more complicated then I initially thought... definitely not the newbie thing (at least with my level of newbiness)

Thanks a lot, Eric! 

Though... a little additional question: how to count those?.. if I had one filter I would just put it here <$count filter="MyFilter"/> but here are two filters... with a variable... so I'm a bit confused...
 

Eric Shulman

unread,
Jul 20, 2020, 12:40:04 PM7/20/20
to TiddlyWiki
On Monday, July 20, 2020 at 9:03:52 AM UTC-7, Jake wrote:
<$list filter="[tag[Comedy]!sort[releasedate]]" variable="title">
<$list filter="[
<title>get[releasedate]compare:integer:gteq[20200701]then<title>]">

<ul> <li> <$link/> <$transclude tiddler={{{ [<currentTiddler>get[rating]addsuffix[-icon]] }}} /> (<$view field="releasedate" format="date" template="0DD.0MM.YYYY"/>) </li> </ul>  

</$list>
</$list>
Though... a little additional question: how to count those?.. if I had one filter I would just put it here <$count filter="MyFilter"/> but here are two filters... with a variable... so I'm a bit confused...

Try this:
\define getItems()

<$list filter="[tag[Comedy]!sort[releasedate]]" variable="title">
   
<$list filter="[<title>get[releasedate]compare:integer:gteq[20200701]then<title>]">

     
<$text text="[["/><$text text=<<currentTiddler>>/><$text text="]]"/>
   
</$list>
</
$list>
\end

\define showItem()

<li>
   
<$link/>
   
<$transclude tiddler={{{ [<currentTiddler>get[rating]addsuffix[-icon]] }}} />

   
(<$view field="releasedate" format="date" template="[UTC]0DD.0MM.YYYY"/>)
</li>
\end

<$wikify name="theList" text=<<getItems>>>
There are <$count filter=<<theList>> /
> items:<br>
<ul><$list filter=<<theList>>><<showItem>></$list></ul>
</$wikify>

The getItems() macro does the 2-step filter and simply outputs the titles, each enclosed in "[[" and "]]" to account for any titles with spaces.
The $wikify widget then invokes <<getItems>> and captures the output into a variable, "theList".

You can then pass that captured list to the $count widget to show the number of results
and then also use it in a $list widget to iterate over all the titles and display them using
the desired formatting.

notes:
* The <ul>...</ul> is *outside* the output $list because you only need it ONCE to show all the bullets.
* The showItem() macro is used just to make the code easier to read.

-e

Jake

unread,
Jul 22, 2020, 11:03:01 AM7/22/20
to TiddlyWiki
Yes, the last one worked perfectly! Though it's a bit more difficult to understand then the first one. 
Which is the input set, the output set, where the variable is assigned to individual item and where the variable is assigned to the whole set, so on... 
I mean the main question is not exactly what is assigned to what, but "what you can assign to what and what you can not" in terms of TW. :)

PS. As I understood in this case <<theList>> variable you can use only inside "wikify" widget and <<getItems>> and <<showItem>> anywhere in the wiki once you add them in macro tiddler?
Reply all
Reply to author
Forward
0 new messages