[TW5] List tiddlers by year and month, like "archive" widgets on blogs

634 views
Skip to first unread message

Nicholay Nascimento

unread,
Aug 26, 2015, 8:24:48 PM8/26/15
to TiddlyWiki
I'm trying to implement a sidebar tiddler for my journal entries that lists tiddlers tagged "journal" by year and month created, like in this image. I want the list to generate automatically, i.e. I don't have to "hard code" specific years and months into filters using things like [regexp:created[^201508]]. I fiddled with the timeline macro trying to get it to group by month, below is what I have so far. The problem is the inner list filters by full date and I think it could work if I could just extract the portion of the "created" field that I need (6 digits for month, 4 for associated year in another list). Admittedly I don't understand too well about how widgets work but after a lot of searching it seems like the problem is that Tiddlywiki itself doesn't have such a mechanism to do what I want. Is there any built-in way to do this in Tiddlywiki? If not, is there a way to get the effect I'm after in general? I definitely don't want to go with a calendar view solution. Sorry if I'm not clear enough. Any help on this would be appreciated, thanks.

<div class="tc-timeline">
    <$list filter="[tag[Journal]!is[system]has[created]!sort[created]each[created]]">
       
<div class="tc-menu-list-item">
            <$view field="created" format="date" template="MMM"/>
           
<$list filter="[created{!!created}!is[system]!sort[created]]">
                <div class="tc-menu-list-subitem">
                    <$link to={{!!title}}>
                        <
<timeline-title>>
                    </$link>
               
</div>
            </$list>
       
</div>
    </$list>
</div>


Mark S.

unread,
Aug 27, 2015, 12:37:25 AM8/27/15
to tiddl...@googlegroups.com
I'm thinking that the way to go about it, if it doesn't pose too much of a compromise, is to make a tiddler for each year/month with a field like "yearmo".

Then list all the year/months and use them to filter in a sub-list with a regular expression and a couple of massaging macros, like:

\define findme2() ^$(findme)$

<div class="tc-timeline">
    <$list filter="[has[yearmo]sort[yearmo]]">
        <div class="tc-menu-list-item">
            <$view field="title" />
<$set name="findme" value={{!!yearmo}} >

            <$list filter="[regexp:created<findme2>!sort[created]]">

                <div class="tc-menu-list-subitem">
                    <$link to={{!!title}}>
                        <<timeline-title>>
                    </$link>
                </div>
            </$list>
</$set>
        </div>
    </$list>
</div>

The compromise is that you have to remember to add a year/month label for each active month. But you shouldn't have to modify your code.

-- Mark --

Jed Carty

unread,
Aug 27, 2015, 4:00:00 AM8/27/15
to TiddlyWiki
I can't think of a quick way to achieve what you want without adding year and month fields to your tiddlers. You may be able to pull off some magic using the removeprefix filter operator. For example you could manually make something horribly inefficient like this:

<$list filter='[tag[Journal]!is[system]has[created]!sort[created]each[created]]' variable=JournalEntry>
<$list filter='2014 2015 2016 2017 2018 2019 2020' variable=Year>
<$list filter='01 02 03 04 05 06 07 08 09 10 11 12' variable=Month>
<$list filter='[is[current]get[created]removeprefix<Year>removeprefix<Month>]'>

<<JournalEntry>> - <$view tiddler=<<JournalEntry>> field='created'/>

</$list>
</$list>
</$list>
</$list>

where you replace the inside content with whatever you want to display. It would group all the entries by year and month but you would either have to list the year and month on each post listing or not at all. You should be able to improve it with some other filtering. Note that this does require you to manually enter in the list of possible years.

If you want something much more complex, you could check out the archives I have over on my site. At the moment I have absolutely no documentation for it. One of the 1865436732348754 projects I am hoping to do at some point is making a blogging edition of tiddlywiki.

I have archives in calendar form and in a list form.

If you have any specific questions I will be around and can hopefully help.

Nicholay Nascimento

unread,
Aug 29, 2015, 4:51:16 PM8/29/15
to TiddlyWiki
Mark and Jed, I hadn't thought of those ways. Unfortunately, they're exactly what I'm trying to avoid. Do you think some javascript can help? If so, it might motivate me even more to start learning in a couple months' time (currently learning C).

It looks to me like the ability to extract a portion of a field would provide the easiest solution, think slicing in Python but for Tiddlywiki. Something similar has been discussed to some extent in an unrelated TW5 issue on Github proposing a text length filter. I don't know where to go with this, however. There doesn't seem to be an issue for this specific thing on Github. Should I propose it? I've never opened an issue before, so I don't know how that works.

Jed Carty

unread,
Aug 29, 2015, 6:24:01 PM8/29/15
to TiddlyWiki
Javascript is pretty easy compared to most other languages I have tried, so learning it wouldn't be a bad idea. It wouldn't be hard to do the needed string manipulations in javascript, there are functions equivalent using slicing in python. The date objects may let you do something simpler than that if you just want to solve this problem.  For adding an issue on github  go ahead if you want, you may get more feedback there. I don't think that this is something that would be added into the core, but it could be a useful plugin and would probably be a good way to learn how to use javascript in tiddlywiki. I think you need an account on github to add an issue, but it is pretty much the same thing as adding a forum post so just poke buttons until it works. There isn't really any way you could break anything and no one gets angry when a new person is stumbling around trying to learn how things work.

Nicholay Nascimento

unread,
Aug 30, 2015, 2:43:19 PM8/30/15
to TiddlyWiki
It wouldn't be hard to do the needed string manipulations in javascript, there are functions equivalent using slicing in python.

That gives me hope. I remember joking with one of my friends about how painful javascript looks. Anyway, I might just try working out something with it in the future and share it with the community. Not sure whether I'll raise an issue.

In the meantime, I think I'll set it up somehow so that journal tiddlers are tagged with the year and month (as two distinct tags), and the sidebar tiddler is explicitly set to list entries by each year tag (sigh) and sub-group by month tag. I might post specifics later when I fix it up for readers of this thread who are looking for something similar.

Still, thanks to both of you for your input!

Mark S.

unread,
Sep 2, 2015, 10:12:17 PM9/2/15
to tiddl...@googlegroups.com
With a few caveats, the following code mostly works. Basically I take a stream of tiddlers sorted by the "created" field, and then insert a year/month label whenever the year/month changes.

!!! breaker test
<$macrocall $name=breaker variable="myvar" input="n/a" pos=6 reset="y" ending="" />
<$list filter="[tag[Journal]!is[system]has[created]sort[created]]">
<b><$macrocall $name=breaker variable="myvar" input={{!!created}} pos=6 reset="N" ending="<br/>" /> </b>
<$view field="title"/
><br/>
</$list>


So if you want the sub-lists to be sorted in a different order than the month data ... you're out of luck.

This is the only way I could find to do it without actually writing a widget that does it all. Widgets are messy to write -- at least at this point in my TW5 development. What I used instead was a javascript macro to break out labels. Code below. There are several parameters (variable,input,pos,ending,reset) that you need to pass to the macro. I can document them a little better if people find they are actually using the code. I figure this is more of a starter kit.

Something to be aware of is that the creation date field may not be the field you want. It apparently shows the UTC date of the actual moment the tiddler created, which may not be the same as the journal date. In fact, depending on where you live, it may be be on a different day than than the day in the tiddler title. When I created a journal tiddler at night, for instance, the creation date was already on the following day. For this reason, it might be better to alter the Journal template code to create and update a separate "journaldate" field that has the datestamp in a form that matches the journal title.

Javascript macros are tiddlers that have their type set to "javascript/application" and an addtional module-type field of "macro". Be absolutely sure to backup your data before trying this, because a single byte mistake can crash your TW, requiring you to manually edit the tw file with a text editor.

The breaker macro gets called once before the listing begins to clear out a global variable and then called in a second way inside the listing.

By looking at the code, I think you can readily see how to change it if you want a different way of representing months/years. Here's the code for the breaker:

/*\
title: $:/MAS/breaker.js
type: application/javascript
author: MAS
module-type: macro
Break when first n characters of parameter change. User needs to reset.
\*/

(function(){
/*jslint node: true, browser: true */
/*
Information about this macro
*/

exports
.name = "breaker";
exports
.params = [{name:"variable",default:"masstuff"},{name:"input",default:""},{name: "pos",default:0},{name:"ending",default:""},{name:"reset",default:"n"}];
/*
Run the macro
*/

exports
.run = function() {

var variable=arguments[0] ;
var input = arguments[1] ;
var pos = arguments[2] ;
var ending = arguments[3] ;
var reset = arguments[4] ;

/* For reset at start of loop */

if(reset==="y"  || reset==="Y") {
     $tw
[variable]=input ;
     
return "" ;
}

var slc = input.slice(0,pos) ;
var twslc = $tw[variable] ;

if(slc==twslc) { return "" ; }
$tw
[variable] = slc ;

var year = slc.slice(0,4) ;
var mo={"01":"January","02":"February","03":"March" ,"04":"April" ,"05":"May" ,"06":"June","07":"July","08":"August","09":"September","10":"October","11":"November","12":"December"}[slc.slice(4,6)] ;

return year+" "+mo+ending ;

};
})();

 



Reply all
Reply to author
Forward
0 new messages