Thank you for sharing! This looks fantastic. I will be needing charts in a few months and it’s great to have a simple tool to use for them.
@andrewg_oz thought you may be in OZ, although I did not notice the .au
, I am in Sydney.
- Perhaps I will get this meetup Sydney TWIG - TiddlyWiki Interest group started one day, join if interested.
I am yet to work through the operation of your plugins, although thanks for sharing.
All I am suggesting here is if we could pass a javaScript “object” to it that can be generated from parameters; it may be possible to “request” simple charts using a just some parameters. Even simpler.
However my initial look into the <$apexchart
widget suggests I may be able to construct a method myself.
For example a procedure <<pie "dark energy":68 "dark-matter":27 matter:"5">>
would present a sumple pie chart, with the need for a separate data tiddler.
Code snipit
\procedure pie()
<$parameters $params=params>
calling `<$apexchart` with <<params>>
</$parameters>
\end pie
<<pie dark-energy:68, dark-matter:27, matter:5>>
result, just illustrating.
calling <$apexchart with {"dark-energy":"68,","dark-matter":"27,","matter":"5"}
- The above method would work immediately if a variable can be given as the data input to $apexchart
- A common alternative in tiddlywiki is $names and $values parameters containing filters as in SetMultipleVariables widget.
- Whatever you wish, of course. This was not intended to be a detailed request, just I noticed it may be a simple step to invoke your plugin(s) a different way (or may not be), allowing easy use and further integration.
Hopeful the above illustrates what I mean. I am not a JavaScript programmer (yet), but I am well versed in TiddlyWiki, as you say I think it may be;
I agree with the followig;
I can help with the following if and when you come to it.
But for now “I gotta go learn some things”
Thanks again.
Hi @andrewg_oz
I appreciate your work on TiddlyWiki charting and I’ve been exploring your plugins. Nice job, thanks for sharing!
May I suggest some improvements in your examples?
In your example tiddlers, you often use this code pattern for value series:
<$list counter="is" filter="[[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]">
<$text text={{{ [<is-first>match[no]then[,]] }}}/>
<$text text={{{ [<currentTiddler>]+[get[text]length[]] }}}/>
</$list>
and then this for labels:
<$list counter="is" filter="[[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]">
<$text text={{{ [<is-first>match[no]then[,]] }}}/>
"<$text text={{{ [<currentTiddler>]+[removeprefix[$:/plugins/tiddlywiki-scss-com-au/chartjs/]] }}}/>"
</$list>
Notice here the subtle variation with leading and trailing "
around the second $text widget.
Example code borrowed from this tiddler.
There are repeated lines of code in both code blocks:
- The whole $list widget, which selects the source tiddlers holding the data
- The first $text widget, which adds a
,
separator between values
The second point can be simplified by adding a +[join[,]]
filter step to the values filter, which also obsoletes the counter="is"
attribute of the $list widget, like this:
<$list filter="[[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]">
<$text text={{{ [<currentTiddler>]+[get[text]length[]]+[join[,]] }}}/>
</$list>
This works for values, but not for labels because of the surrounding "
, which can be replaced by a +[addprefix["]addsuffix["]]
filter run:
<$list filter="[[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]">
<$text text={{{ [<currentTiddler>]+[removeprefix[$:/plugins/tiddlywiki-scss-com-au/chartjs/]]+[addprefix["]addsuffix["]]+[join[,]] }}}/>
</$list>
These code blocs can be further simplified by merging $list filter inside $text filtered transclusion:
<$text text={{{ [[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]+[get[text]length[]]+[join[,]] }}}/>
...
<$text text={{{ [[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]+[removeprefix[$:/plugins/tiddlywiki-scss-com-au/chartjs/]]+[addprefix["]addsuffix["]]+[join[,]] }}}/>
This is more compact, but also less readable… Enter subfilter
:
\define chartTiddlers() [[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]
\define chartValues() [get[text]length[]]
\define chartLabels() [removeprefix[$:/plugins/tiddlywiki-scss-com-au/chartjs/]] +[addprefix["]addsuffix["]]
...
<$text text={{{ [subfilter<chartTiddlers>] +[subfilter<chartValues>] +[join[,]] }}} />
...
<$text text={{{ [subfilter<chartTiddlers>] +[subfilter<chartLabels>] +[join[,]] }}} />
The whole code before:
<$chartjs type=pie title="Plugin Composition" width=530px>{
"options":{"plugins":{"legend":{"position":"right"}}},
"data":{"datasets":[{"data":[
<$list counter="is" filter="[[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]">
<$text text={{{ [<is-first>match[no]then[,]] }}}/>
<$text text={{{ [<currentTiddler>]+[get[text]length[]] }}}/>
</$list>
]}],"labels":[
<$list counter="is" filter="[[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]">
<$text text={{{ [<is-first>match[no]then[,]] }}}/>
"<$text text={{{ [<currentTiddler>]+[removeprefix[$:/plugins/tiddlywiki-scss-com-au/chartjs/]] }}}/>"
</$list>]}}</$chartjs>
and after:
\define chartTiddlers() [[$:/plugins/tiddlywiki-scss-com-au/chartjs]plugintiddlers[]]
\define chartValues() [get[text]length[]]
\define chartLabels() [removeprefix[$:/plugins/tiddlywiki-scss-com-au/chartjs/]] +[addprefix["]addsuffix["]]
<$chartjs type=pie title="Plugin Composition" width=530px>{
"options":{"plugins":{"legend":{"position":"right"}}},
"data":{"datasets":[{"data":[
<$text text={{{ [subfilter<chartTiddlers>] +[subfilter<chartValues>] +[join[,]] }}} />
]}],"labels":[
<$text text={{{ [subfilter<chartTiddlers>] +[subfilter<chartLabels>] +[join[,]] }}} />
]}}</$chartjs>
I hope you liked this little journey, and thanks again for your plugins
Fred
Hi Fred,
Thanks for your comments.
TiddlyWiki filters, macros, procedures, functions and similar things are fundamental to TiddlyWiki and I struggle with how they all work together.
For some things I started with “+[join[,]]” but later found it unusable in some cases and ended up with the list/counter pattern. I have clearly re-used that pattern where join would have worked and been the better option. It’s good to be reminded of these things!
I’ve uploaded a new wiki. The composition charts are simpler now. A couple of other charts got similar treatment.
Andrew
@andrewg_oz I was trying to use the apex charts with a Habit-tracker. Habit tracker is saving data in a json tiddler like this. Is it possible to retrieve data from such a json tiddler for creating charts.
Nice plugins, so you created two plugins, supporting ApexChart and Chart.js, and I can see on you website you also created another version of echarts plugin, I think this has been done by ECharts - Bringing amazing visualization tools to TiddlyWiki!.
But seems charts.js is much smaller, which can be a nice replacement for smaller wikis.
But what into my concern is that we might need to install multiple chart library if other plugins like Habit tracker in TW directly depend on them.
A better approach will be like Fishing, flashcard in TiddlyWiki, add new features to help remember tiddler more efficiently in release v1.2.0, it make its analysts feature be a sub-plugin, so user can choose install a version with the chat library they already installed. (Can have 2 analysts sub-plugin, depends on charts.js and echarts)
The short answer is yes.
The longer answer is that all the chart libraries tend to use JavaScript timestamps (that is, milliseconds since 1-Jan-1970) and that the dates in the JSON will need to be parsed into something that can be ultimately converted into a timestamp. It will also make the date sortable - something I assume you’d want to do and something that can’t be done in the string form the dates are in now.
I’ve done some testing and found that the date in your JSON cannot be parsed by the TiddlyTools parsedate function. In other words, “21/9/2023” won’t work, but “9/21/2023”, “21-Sep-2023”, “20230921”, “2023/9/23” will. Other formats might work too, like an ISO8601 or similar. My first preference for writing dates is “21-Sep-2023” since it is clear which part is a year, month, or day. My second preference is ISO8601, so “20230921”
Once date parsing is resolved you’ll be able to use TW widgets to construct a suitable JSON that can be charted.
I’ve just updated my wiki with the following:
I don’t know what sort of chart you’re after, but the general idea is this:
- Change your JSON date format to something parsable. Ideally it would be directly sortable without parsing, like a TW timestamp.
- Use TW widgets to construct a chartable JSON.
The “Data from Json” tiddler converts the JSON dates into a sortable form (“YYYY0MM0DD”) then sorts them. Then it sets a “key” variable that returns that sortable date back to the original format in the JSON to allow lookups to work. This could be avoided if the dates were already stored in the JSON in a sortable form.
Then an example table is output using the key for looking up data in the JSON, the JavaScript (not TW) timestamp for charting, and the looked-up value (also for charting?)
I’ve tried to keep my chart plugins as “thin” as possible, since I don’t know how other people will try to use them.
I really don’t see much alternative for plugins that want to support charting other than to provide (or allow for) chart-specific plugins.
There are a couple of things I could think of that I could change.
One would be to support a “json” parameter that would provide an additional way to provide chart data to the widget. Another way would be to support a parameter “dict” (for “dictionary tiddler”) that would make use of the dictionary-tiddler-macros I’ve written for my ApexCharts and Chart.js widgets.
I’m not sure of the best way to proceed, so I’m just seeing what ideas people may have before doing anything more.
Thank you @andrewg_oz for taking a look at this issue. As per your advice, I changed the date format in the json tiddler into a parsable format.
But the Value
column is remaining empty
Any idea whats going wrong here ?
I think the most widely recognized, easily parseable format is the ISO-8601 version with the hyphens, 2023-09-21
, which conveniently extends to including times as well. And it’s easy to convert to TW date format. In JS:
const d = new Date()
console.log(d.toISOString()) //=> 2023-09-21T16:35:48.771Z
console.log(d.toISOString().slice(0, 10)) //=> 2023-09-21
console.log(d.toISOString().replace(/\D/g, '')) //=> 20230921163612589
Go jogging_data.json (338 Bytes)
When you’re creating the key variable the format string has to match the format in the JSON. In your case, it should be “YYYY-MM-DD”.
@andrewg_oz … There seems to be a problem with Andrew's TiddlyWiki — Plugins and Macros – I does not work with FireFox
Is there a GitHub repo to report bugs?
@andrewg_oz I got it working as you suggested.
Do you know of any charts which can display yes or no
data like this from json
tiddlers
@john.edw_gmail.com How to modify the code of this timeline chart tiddler to get the data from this tiddler.
@pmario No repo, sorry. The problem was in the demo data - apparently Firefox doesn’t parse “1793-11-31” as a date (only 30 days in November!)
Thank you @andrewg_oz
I did something testing and created a chart based on the one you shared
It is working, but there is some issues I am seeing. Chart data is not getting correctly updated when I add a data in the habit tracker tiddler.
Edit: After adding caption
field to those json tiddlers, it’s working as intended…Thank you @andrewg_oz for the help.
No problem. Just a tweak to my code. I think the tooltips look better if they’re the same date. Instead of “86400000” it should be 1 less: “86399999”.
@andrewg_oz
Can candlestick charts be used to create best streaks from the habit json data tiddlers like this