Time Tracking in TiddlyWiki?

2,223 views
Skip to first unread message

si

unread,
Jun 21, 2020, 8:08:10 AM6/21/20
to TiddlyWiki
I use TiddlyWiki as a task manager, among other things, and I thought it would be cool to know how long I spent working on a completed task.

Off the top of my head I imagine having a "start/stop" button that will alternately add a timestamp to the fields "start" and "stop". Then I could (hopefully) create a macro that calculates the total time spent on the task.

I wonder if anyone has done something similar, or has a different approach worth sharing?

Eric Shulman

unread,
Jun 21, 2020, 12:33:31 PM6/21/20
to TiddlyWiki
On Sunday, June 21, 2020 at 5:08:10 AM UTC-7, si wrote:
I use TiddlyWiki as a task manager, among other things, and I thought it would be cool to know how long I spent working on a completed task.
Off the top of my head I imagine having a "start/stop" button that will alternately add a timestamp to the fields "start" and "stop". Then I could (hopefully) create a macro that calculates the total time spent on the task.

I just put this together:
\define startbutton()
<$button> start
   
<$action-setfield start=<<now YYYY0MM0DD0hh0mm0ss0XXX>>/>
   <$action-setfield stop=""/
>
   
<$action-setfield elapsed=""/>
</$button>
\end

\define stopbutton()
<$button> stop
   <$action-setfield stop=<<now YYYY0MM0DD0hh0mm0ss0XXX>>/
>
   
<$action-setfield elapsed={{{ [{!!stop}subtract{!!start}] }}}/>
</$button>
\end

\define showtable()
<$vars min={{{ [{!!elapsed}divide[60000]trunc[]] }}}>
<$vars minsec={{{ [<min>multiply[60]] }}}>
<$vars sec={{{ [{!!elapsed}divide[1000]subtract<minsec>multiply[1000]trunc[]divide[1000]] }}}>

| started:|<$view field="start" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" /
>|
| stopped:| <$view field="stop" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" />|
| elapsed:|<<min>> minutes <<sec>> seconds|
</$vars>
</
$vars>
</$vars>
\end

<$reveal default={{!!start}} type="match" text="">
   <<startbutton>>
</
$reveal>
<$reveal default={{!!start}} type="nomatch" text="">
   
<$reveal default={{!!stop}} type="match" text="">
     
<<stopbutton>>
   
</$reveal>
   <$reveal default={{!!stop}} type="nomatch" text="">
      <<startbutton>>
   </
$reveal>
</$reveal>
<<showtable>>

notes:
* startbutton() sets the "start" field using a complete zero-padded time value including milliseconds.  This is the same format used by the TWCore for the "created" and "modified" fields.
* stopbutton() sets the "stop" field and calculates elapsed time (i.e, stop - start)
* showtable() calculates the elapsed time as minutes and seconds and displays the results as a nicely formatted table, where:
   * minutes ("min") are truncated to the nearest integer
   * then multiplied by 60 to get the number of seconds in those whole minutes ("minsec")
   * seconds ("sec") subtracts the whole minutes (as "minsec") and then rounds to 3 decimal places (i.e., milliseconds) by multiplying by 1000, truncating, and dividing by 1000
* The first $reveal shows the startbutton if no start value is stored
* The second $reveal shows the stopbutton if a start value is stored but no stop value is stored
* The third $reveal shows the startbutton again if both start and stop values are stored

To use it:
* place the above code into a tiddler named "Timer"
* then, in any tiddler, simply write:
{{||Timer}}

Give it a try and let me know how it goes...

enjoy,
-e

si

unread,
Jun 21, 2020, 3:24:57 PM6/21/20
to TiddlyWiki
Wow Eric that's great thank you!

I think what's missing is the ability to record time for the same task across multiple sessions.

I've edited some of your code so that the start/stop buttons don't erase the field, but just add the new timestamps to the end of the field. This way the "start" and "stop" fields contain a list of all the times you started and stopped the timer.

What I can't figure out is how to calculate the total elapsed time. What I need to do is calculate the difference between the last timestamp in the "start" and "stop" fields each time I press the stop button, then sum all of these values.

Here is an edited version of your code:

\define startbutton()
<$button> start
   
<$set name="current-time" value=<<now YYYY0MM0DD0hh0mm0ss0XXX>> >
   
<$action-setfield start={{{ [{!!start}addsuffix[ ]addsuffix<current-time>] }}}/>
   
<$action-setfield current-button="stop"/>
   
</$set>
</
$button>
\end

\define stopbutton()
<$button> stop
   
<$set name="current-time" value=<<now YYYY0MM0DD0hh0mm0ss0XXX>> >
   
<$action-setfield stop={{{ [{!!stop}addsuffix[ ]addsuffix<current-time>] }}}/>

   
<$action-setfield elapsed={{{ [{!!stop}subtract{!!start}] }}}/>

   
<$action-setfield current-button="start"/>
   
</$set>
</
$button>

\end

\define showtable()
<$vars min={{{ [{!!elapsed}divide[60000]trunc[]] }}}>
<$vars minsec={{{ [<min>multiply[60]] }}}>
<$vars sec={{{ [{!!elapsed}divide[1000]subtract<minsec>multiply[1000]trunc[]divide[1000]] }}}>

| started:|<$view field="start" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" />|
| stopped:| <$view field="stop" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" />|
| elapsed:|<<min>> minutes <<sec>> seconds|
</$vars>
</
$vars>
<
/$vars>
\end

<$reveal default={{!!current-button}} type="nomatch" text="stop">
   <<startbutton>>
</
$reveal>
<$reveal default={{!!current-button}} type="match" text="stop">
   
<<stopbutton>>
</$reveal>

<<showtable>>

Any ideas how I can calculate the total elapsed time? Or maybe there is a better overall approach?

Eric Shulman

unread,
Jun 21, 2020, 7:41:56 PM6/21/20
to tiddl...@googlegroups.com
On Sunday, June 21, 2020 at 12:24:57 PM UTC-7, si wrote:
Wow Eric that's great thank you!

You are very welcome!
 
I think what's missing is the ability to record time for the same task across multiple sessions.
I've edited some of your code so that the start/stop buttons don't erase the field, but just add the new timestamps to the end of the field. This way the "start" and "stop" fields contain a list of all the times you started and stopped the timer.
What I can't figure out is how to calculate the total elapsed time. What I need to do is calculate the difference between the last timestamp in the "start" and "stop" fields each time I press the stop button, then sum all of these values.

I like what you've done here!

The first trick to calculating the elapsed and total time is to be able to get just the last start and stop timestamps.
The next bit is actually more involved than I previously considered.  It turns out that simply subtracting the timestamps does NOT give you the correct results because the timestamps do not represent "current time as seconds", but rather a compound days/hours/minutes/seconds value.  To properly compute the difference between two timestamps, we need to first convert the timestamps from their compound format into pure seconds.  Then we can subtract the values to get the difference.

It took me a while to get it just right, but here's some new code that does the job:
\define start_timer()
<$button actions="""
   <$vars time=<<now YYYY0MM0DD0hh0mm0ss0XXX>> >
   <$action-setfield startlist={{{ [{!!startlist}addsuffix[ ]addsuffix<time>trim[]] }}}/>
   <$action-setfield started=<<time>> stopped="" elapsed=""/>
   <$action-setfield button="
stop"/>
   </$vars>
"""
> start
</$button>
\end

\define stop_timer()
<$button actions="""
   <$vars time=<<now YYYY0MM0DD0hh0mm0ss0XXX>> >
   <$action-setfield stoplist={{{ [{!!stoplist}addsuffix[ ]addsuffix<time>trim[]] }}}/
>
   
<$vars
      msec
={{{ [{!!started}split[]last[5]join[]] }}}
      min
={{{ [{!!started}split[]butlast[5]last[2]join[]multiply[60]] }}}
      hour
={{{ [{!!started}split[]butlast[7]last[2]join[]multiply[3600]] }}}
      day
={{{ [{!!started}split[]butlast[9]last[2]join[]multiply[86400]] }}}>
   
<$vars start={{{ [<msec>add<min>add<hour>add<day>] }}}>
   
<$vars
      msec
={{{ [<time>split[]last[5]join[]] }}}
      min
={{{ [<time>split[]butlast[5]last[2]join[]multiply[60]] }}}
      hour
={{{ [<time>split[]butlast[7]last[2]join[]multiply[3600]] }}}
      day
={{{ [<time>split[]butlast[9]last[2]join[]multiply[86400]] }}}>
   
<$vars stop={{{ [<msec>add<min>add<hour>add<day>] }}}>

   
<$action-setfield stopped=<<time>> elapsed={{{ [<stop>subtract<start>] }}}/>
   
<$action-setfield total={{{ [{!!total}add{!!elapsed}] }}}/>
   
<$action-setfield button="start"/>
   
</$vars>
   </
$vars>
   
</$vars>
   </
$vars>
   
</$vars>
"""> stop
</
$button>
\end

\define reset_timer()
<$button> reset
   
<$action-deletefield startlist stoplist started stopped elapsed total button />
</$button>
\end

\define showtable()
<$vars
   elapsed_min={{{ [{!!elapsed}divide[60000]trunc[]] }}}
   elapsed_minsec={{{ [<elapsed_min>multiply[60]] }}}
   elapsed_sec={{{ [{!!elapsed}divide[1000]subtract<elapsed_minsec>multiply[1000]trunc[]divide[1000]] }}}>
<$vars
   total_min={{{ [{!!total}divide[60000]trunc[]] }}}
   total_minsec={{{ [<total_min>multiply[60]] }}}
   total_sec={{{ [{!!total}divide[1000]subtract<total_minsec>multiply[1000]trunc[]divide[1000]] }}}>

| started:|<$view field="started" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" /
>|
| stopped:|<$view field="stopped" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" />|
| elapsed:|<<elapsed_min>> minutes <<elapsed_sec>> seconds|
| total:|<<total_min>> minutes <<total_sec>> seconds|
</$vars>
</
$vars>
\end

<$reveal default={{!!button}} type="nomatch" text="stop">
   
<<start_timer>> <<reset_timer>>
</$reveal>
<$reveal default={{!!button}} type="match" text="stop">
   <<stop_timer>> <<reset_timer>>
</
$reveal>

<<showtable>>

Notes:
* I renamed a lot of stuff to hopefully make the code more understandable
* I added a "reset" button to easily clear all the fields and start fresh (this was really important during testing!)

As before, simply put the above code into a tiddler (e.g., "Timer") and then transclude it in other tiddlers by writing:
{{||Timer}}

I've also uploaded the code to a standalone TW file here: http://TiddlyTools.com/timer.html, so you can just go there and press the "save" button to download a copy

Let me know how it goes...

enjoy,
-e
Eric Shulman
TiddlyTools.com: "Small Tools for Big Ideas!" (tm)



TW Tones

unread,
Jun 21, 2020, 8:42:24 PM6/21/20
to TiddlyWiki
Eric,

This has some cute code patterns in it, like second padded field. Love your work. 
Before delving in, in detail have you accounted for tasks active across midnight?

Regards
Tony

Eric Shulman

unread,
Jun 21, 2020, 8:52:55 PM6/21/20
to TiddlyWiki
On Sunday, June 21, 2020 at 5:42:24 PM UTC-7, TW Tones wrote:
This has some cute code patterns in it, like second padded field. Love your work. 
Before delving in, in detail have you accounted for tasks active across midnight?

Yeah.. it should handle day boundaries just fine... but it will have problems if you cross a *month* boundary.

I punted on that since the number of seconds in a month varies because months have different number of days
and I didn't want to implement a lookup table to handle it.  It gets even more complicated if you want to account
for leap years.

But it should work properly as long as you a task is not active at midnight at the end of a month.

-e

TW Tones

unread,
Jun 21, 2020, 9:27:00 PM6/21/20
to TiddlyWiki
Eric,

Don't bother here, but a simple flag to detect a data change between start and end may be sufficient here. Basically a separate calculation for such "date transgressions" could do it, but it would be well served by having the actual start/end date collected as well. One could even count the number days between (With calendar utility perhaps leverage the days operator) for a full elapsed time calculator. Such a method should be immune from other calendar artefacts because the days should be appropriate from a calendar utility.

Just adding

Tony

Eric Shulman

unread,
Jun 22, 2020, 7:53:38 AM6/22/20
to TiddlyWiki
BUG FIX!

In my previous post, there were two errors in my code!

* in stop_timer(), when calculating the "start" and "stop" times, I was incorrectly treating seconds+milliseconds as if they were WHOLE SECONDS!
* in showtable(), I was incorrectly treating the stored !!elapsed and !!total values as MILLISECONDS.

I've fixed both problems, and posted the update tiddler here: http://TiddlyTools.com/timer.html

Here's the new code with both bugs corrected:
\define start_timer()
<$button actions="""
   <$vars time=<<now YYYY0MM0DD0hh0mm0ss0XXX>> >
   <$action-setfield startlist={{{ [{!!startlist}addsuffix[ ]addsuffix<time>trim[]] }}}/>
   <$action-setfield started=<<time>> stopped="" elapsed=""/>
   <$action-setfield button="
stop"/>
   </$vars>
"""
> start
</$button>
\end

\define stop_timer()
<$button actions="""
   <$vars time=<<now YYYY0MM0DD0hh0mm0ss0XXX>> >
   <$action-setfield stoplist={{{ [{!!stoplist}addsuffix[ ]addsuffix<time>trim[]] }}}/
>
   
<
$vars
      msec
={{{ [{!!started}split[]last[3]join[]divide[1000]] }}}
      sec
={{{ [{!!started}split[]butlast[3]last[2]join[]] }}}

      min
={{{ [{!!started}split[]butlast[5]last[2]join[]multiply[60]] }}}
      hour
={{{ [{!!started}split[]butlast[7]last[2]join[]multiply[3600]] }}}
      day
={{{ [{!!started}split[]butlast[9]last[2]join[]multiply[86400]] }}}>

   
<$vars start={{{ [<msec>add<sec>add<min>add<hour>add<day>] }}}>

   
<$vars
      msec
={{{ [<time>split[]last[3]join[]divide[1000]] }}}
      sec
={{{ [<time>split[]butlast[3]last[2]join[]] }}}

      min
={{{ [<time>split[]butlast[5]last[2]join[]multiply[60]] }}}
      hour
={{{ [<time>split[]butlast[7]last[2]join[]multiply[3600]] }}}
      day
={{{ [<time>split[]butlast[9]last[2]join[]multiply[86400]] }}}>

   
<$vars stop={{{ [<msec>add<sec>add<min>add<hour>add<day>] }}}>


   
<$action-setfield stopped=<<time>> elapsed={{{ [<stop>subtract<start>] }}}/>
   
<$action-setfield total={{{ [{!!total}add{!!elapsed}] }}}/>
   
<$action-setfield button="start"/>
   
</$vars>
   </
$vars>
   
</$vars>
   </
$vars>
   
</$vars>
"""> stop
</
$button>
\end

\define reset_timer()
<$button> reset
   
<$action-deletefield startlist stoplist started stopped elapsed total button />
<
/$button>
\end

\define showtable()
<$vars
   elapsed_min={{{ [{!!elapsed}divide[60]trunc[]] }}}
   elapsed_minsec={{{ [<elapsed_min>multiply[60]] }}}
   elapsed_sec={{{ [{!!elapsed}subtract<elapsed_minsec>multiply[1000]trunc[]divide[1000]] }}}>
<$vars
   total_min={{{ [{!!total}divide[60]trunc[]] }}}
   total_minsec={{{ [<total_min>multiply[60]] }}}
   total_sec={{{ [{!!total}subtract<total_minsec>multiply[1000]trunc[]divide[1000]] }}}>


| started:|<$view field="started" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" /
>|

| stopped:|<$view field="stopped" format="date" template="[UTC]MMM DD YYYY 0hh:0mm:0ss.0XXX" />|
| elapsed:|<<elapsed_min>> minutes <<elapsed_sec>> seconds|
| total:|<<total_min>> minutes <<total_sec>> seconds|

</$vars>
</
$vars>
\end

<$reveal default={{!!button}} type="nomatch" text="stop">
   
<<start_timer>> <<reset_timer>>
</$reveal>
<$reveal default={{!!button}} type="match" text="stop">
   <<stop_timer>> <<reset_timer>>
</
$reveal>

<<showtable>>

Just goes to show that even good coders make simple mistakes...

Eric Shulman

unread,
Jun 23, 2020, 4:15:44 AM6/23/20
to TiddlyWiki
ANOTHER BUG FIX! (much thanks to "ParisWiki" for reporting it)

in showtable(), a calculation error was caused by these lines:

<$vars
   elapsed_min={{{ [{!!elapsed}divide[60]trunc[]] }}}
   elapsed_minsec={{{ [
<elapsed_min>multiply[60]] }}}
   elapsed_sec={{{ [{!!elapsed}subtract
<elapsed_minsec>multiply[1000]trunc[]divide[1000]] }}}>
<$vars
   total_min={{{ [{!!total}divide[60]trunc[]] }}}
   total_minsec={{{ [
<total_min>multiply[60]] }}}
   total_sec={{{ [{!!total}subtract
<total_minsec>multiply[1000]trunc[]divide[1000]] }}}>

The problem is that the "minsec" calculation depends on the value of "min", and the "sec" calculation depends on the value of "minsec".  The issue is that I was using one $vars widget to calculate all three of the values, but because of the dependencies, I needed to calculate them one at a time, so that each calculation can correctly reference the results of the previous one.

The bug only appeared when the started/stopped values were at least 1 minute apart.  The reported minutes were correct, but the reported seconds included the full minutes (expressed as seconds).

For example: 
1287 seconds was reported as "21 minutes 1287 seconds".  However, 21 minutes is 1260 seconds, so it should have shown "21 minutes, 27 seconds"
and
1459 seconds was reported as "24 minutes 1459 seconds".  However, 24 minutes is 1440 seconds, so it should have shown "21 minutes, 19 seconds"

The fixed code is:
<$vars elapsed_min={{{ [{!!elapsed}divide[60]trunc[]] }}}>
<$vars elapsed_minsec={{{ [<elapsed_min>multiply[60]] }}}>
<$vars elapsed_sec={{{ [{!!elapsed}subtract
<elapsed_minsec>multiply[1000]trunc[]divide[1000]] }}}>

<$vars total_min={{{ [{!!total}divide[60]trunc[]] }}}>
<$vars total_minsec={{{ [<total_min>multiply[60]] }}}>
<$vars total_sec={{{ [{!!total}subtract
<total_minsec>multiply[1000]trunc[]divide[1000]] }}}>

I've posted the revised code to

To import the update into your own TiddlyWiki, just drag the "TaskTimer" title from the sidebar listing, and drop it on your open TiddlyWiki.

enjoy,
-e

si

unread,
Jun 23, 2020, 12:52:43 PM6/23/20
to TiddlyWiki
This is fantastic Eric - thanks!

Now all I have to do is remember to start/stop the timer...

Eric Shulman

unread,
Jul 17, 2020, 8:21:19 AM7/17/20
to TiddlyWiki
Updates to http://TiddlyTools.com/timer.html

* eliminated use of "temporary fields" for holding current values.
  All data (start time, stop time, elapsed time, total time) now stored using fields containing *lists* of values.
  These fields progressively accumulate separate data for each "task session", which enables "History" table output

* refactored into separate tiddlers for easier selective transclusion:

TiddlyTools/Timer - the start/stop/reset buttons
TiddlyTools/Timer/Elapsed - shows just the elapsed time for the most recent "task session"
TiddlyTools/Timer/Total - shows just the total accumulated time for all task sessions so far.
TiddlyTools/Timer/Summary - shows a table with start/stop times, elapsed time, and total time for the most recent task session
TiddlyTools/Timer/History - shows a table with start/stop times, elapsed time, and total time for all task sessions so far.

* added TiddlyTools/Timer/Info with documentation

* added SampleTask with example usage

enjoy,
-e

Eric Shulman

unread,
Jul 17, 2020, 10:29:35 PM7/17/20
to TiddlyWiki
big update to http://TiddlyTools.com/timer.html

* converted from using separate transclusion tiddlers to macros all defined in TiddlyTools/Timer (now tagged with $:/tags/Macro)

All of the macros accept an optional "taskname" that identifies a separate tiddler for storing the task data
If no taskname is provided, task data is stored in the current tiddler (i.e., the one in which the macro call is located)

* <<timer>> - shows all interface elements (buttons, elapsed time, total time, summary table, and history table)
* <<timer_buttons>> shows just start/stop and reset buttons
* <<timer_elapsed>> shows just elapsed time
* <<timer_total>> shows just total time
* <<timer_summary>> shows just summary table
* <<timer_history>> shows just history table

* updated documentation

enjoy,
-e

Atronoush

unread,
Jul 17, 2020, 11:06:34 PM7/17/20
to TiddlyWiki
Hi Eric,
 This update is really powerful simple to use and easy to learn.

Thank you

Mat

unread,
Jul 18, 2020, 6:47:49 AM7/18/20
to TiddlyWiki
@Eric

Thanks for sharing wonderful stuff!

This is a naive question but I have to ask (in reference to this thread): If one has a wiki with your plugin on a server like github... would that mean it can execute stuff automatically? For example, if the timer was used to trigger a download of stuff... would that mean that the fetching process can finish without human intervention so that when the human logs in and opens his gh hosted webpage, it is loaded with the goodies? I assume this would not work, right? (to name one unclarity: how would it save?)

What if the wiki is left open/active day in and day out could it do it then without human intervention?

Basically; must a wiki be loaded in the browser for it to do anything? 

Thanks.

<:-)

Eric Shulman

unread,
Jul 18, 2020, 8:18:40 AM7/18/20
to TiddlyWiki
The timer doesn't actually do anything without a user action.  It simply saves a "startime" (<<now YYYY0MM0DD0hh0mm0ss0XXX>>) when you press the "start" button, and saves the "stoptime" when you press the "stop" button.  Then it does some math to figure out the difference in minutes and seconds and saves that into the tiddler as "elapsedtime" and adds it to any previous "totaltime" to keep a running total.

To update the elapsed time without user intervention would require use of javascript setTimeout() or setInterval(...) to create an interrupt-driven event that would be triggered once a second (as long as the wiki is loaded) and write the elapsed time into the tiddler.  Updating the tiddler contents would then cause a TWCore refresh, so you could display the current elapsed time.  I did something like this in TWClassic (see http://tiddlytools.com/#TaskTimerPlugin).  But the new timer doesn't do any javascript at all... it's purely wikitext.

There's nothing that happens in between browser sessions.  The only possible "cross-session" processing would be if you were to "start" a timer and then save the file.  Then, when you reload later, you could "stop" the timer and it would calculate the difference to get the elapsed time.

-e

Mat

unread,
Jul 18, 2020, 8:38:49 AM7/18/20
to TiddlyWiki
@Eric - thanks for replying.

Aha, I assumed this TW5 version worked like the TWC version of yours. But so something like your TWC version could in fact be used to auto-perform tasks assuming the TW is running in the browser. Good to know.

<:-)

TiddlyTweeter

unread,
Jul 18, 2020, 1:02:46 PM7/18/20
to TiddlyWiki
Eric Shulman wrote:
... if you were to "start" a timer and then save the file.  Then, when you reload later, you could "stop" the timer and it would calculate the difference to get the elapsed time.

Very useful, even if not initially intended!!

Best wishes
TT 

Eric Shulman

unread,
Jul 19, 2020, 1:39:34 AM7/19/20
to tiddl...@googlegroups.com
On Saturday, July 18, 2020 at 5:38:49 AM UTC-7, Mat wrote:
Aha, I assumed this TW5 version worked like the TWC version of yours. But so something like your TWC version could in fact be used to auto-perform tasks assuming the TW is running in the browser. Good to know.

I just created a new widget: $action-timeout, which adds the ability to use javascript setTimeout()
to trigger actions to be performed after a specified number of milliseconds.

<$action-timeout id="..." delay="..." actions="""...""" />
where:
ID = an optional unique ID (needed if more than one timeout is to be active at the same time).
delay = time (in milliseconds) to wait before triggering the specified actions
actions = the wikitext actions to perform (the same as when used in a $button widget)

As with other $action- widgets, $action-timeout is usually triggered by a $button press or other user-interactions (e.g., choosing from a $select, reacting to a $keyboard, etc.).
However... I've also added another param, autostart="yes", which will actually trigger the $action-timeout as soon as it is rendered, even if it's not inside a $button.
I'm not sure when this param will be useful, and it's best to consider it "experimental" for now.

and...

I've used this new widget to enhance the TiddlyTools/Timer, so that when a task session is started,
instead of simply showing "task in progress", the elapsed time now shows the actual current elapsed
time, automatically updated once per second in real time!

Note: except for updating the elapsed time display, this does NOT (currently) provide support to
"auto-perform tasks", but I suppose that could be the next *big* enhancement to the timer.

Get the latest revision here: http://TiddlyTools.com/timer.html

enjoy,
-e

Mat

unread,
Jul 19, 2020, 4:43:27 AM7/19/20
to TiddlyWiki
Eric Shulman wrote:
I just created a new widget: $action-timeout, 
 
Neat! To work, as in "to not procrastinate", I sometimes use an ancient little program called InstantBoss (I can't vouch for downloading there, I don't remember where I downloaded it myself, but do check out the images). This is a fun little timer set so you work for 10 minutes then pause 2 min, and this is repeated 5 times totaling 1 hour when it gives a fanfare and applause. Now one can build this in TW!

 
... autostart="yes" ... I'm not sure when this param will be useful
... "auto-perform tasks" ... could be the next *big* enhancement

Well, that next big enhancement could - I think - be a partial solution for the current TWederation implementation to function better. Currently the user has to click Fetch and then sit and wait as it collects the tiddlers from the other wikis which takes a longish time. If fetching can be done automatically then it could at least be done when one is not staring at it. (The current TWederation implementation has other problems too so this is not the "key" to it all but it could be a piece in the puzzle.)

Thanks for creating great things Eric!

<:-)

PMario

unread,
Jul 19, 2020, 5:25:58 AM7/19/20
to TiddlyWiki
On Sunday, July 19, 2020 at 7:39:34 AM UTC+2, Eric Shulman wrote:
However... I've also added another param, autostart="yes", which will actually trigger the $action-timeout as soon as it is rendered, even if it's not inside a $button.
I'm not sure when this param will be useful, and it's best to consider it "experimental" for now.

Automatically triggering actions can be very useful, to create eg: automatic TW UI tests. ... On the other hand, if done wrong it can be very destructive (trust me!). Especially during development, if some action variables are not initialized in the right way.

I did create a <$trigger widget some time ago. It activates defined actions if the widget is rendered. I used it to create an automatic test-suite for TW navigation actions.

Due to the "potential destructive" nature of the widget, I did use "buttons" to switch from 1 test-tiddler to the next one. That's the reason, why I didn't promote that widget!

There is also a high risk, to create endless loops, if a triggered action causes a redraw of the tiddler elements, that contain the <$trigger widget.

@Eric. ... I personally would create 2 plugins. 1 with the "useful" timeout and 1 with the potentially dangerous "experimental" parameter.

just my thoughts.
mario

Saq Imtiaz

unread,
Jul 19, 2020, 6:13:24 AM7/19/20
to TiddlyWiki
Automatically triggering actions can be very useful, to create eg: automatic TW UI tests. ... On the other hand, if done wrong it can be very destructive (trust me!). 

It's probably useful to point out for end-users that the limitation that actions can only be triggered by direct user actions, like clicking a button, has never been a technical one as it is exceedingly easy to implement. 

Rather it has always been an intentional one based on what are perceived to be best practices.

I think at the least some very prominent disclaimers and warning messages are a good idea for any plugin that implements such a feature.

Saq Imtiaz

unread,
Jul 19, 2020, 6:16:38 AM7/19/20
to TiddlyWiki
@Mat


... autostart="yes" ... I'm not sure when this param will be useful
... "auto-perform tasks" ... could be the next *big* enhancement

Well, that next big enhancement could - I think - be a partial solution for the current TWederation implementation to function better.

Doesn't Jed already have a plugin that executes actions at timed intervals? You could probably use that in combination with startup actions.

Jed Carty

unread,
Jul 19, 2020, 6:24:36 AM7/19/20
to TiddlyWiki
To join in the fun, I also made a $action-delay widget that delays the execution of any action widgets contained inside it by a set time. It is an action widget so it gets triggered by the normal mechanisms.


The trigger actions plugin I made could be used in a similar way, it doesn't have a delay but it can trigger action widgets based on changes to a wiki and could be combined with a delay action widget to execute actions after a set time based on any change in the wiki as a trigger.


And I made a timer actions plugin that runs action widgets at specified intervals

TiddlyTweeter

unread,
Jul 19, 2020, 6:56:28 AM7/19/20
to TiddlyWiki
Right.

Just FYI the tools like "ToDoNow" have time based activation of alerts already.

Best wishes
TT

Thomas Elmiger

unread,
Jul 19, 2020, 7:27:39 AM7/19/20
to TiddlyWiki
Thank you for the mention, TT, but my Reminders for ToDoNow are triggered by (not so obvious) user interaction.

Cool stuff here!

Cheers,
Thomas

Eric Shulman

unread,
Jul 19, 2020, 7:57:43 AM7/19/20
to TiddlyWiki
On Sunday, July 19, 2020 at 2:25:58 AM UTC-7, PMario wrote:
On Sunday, July 19, 2020 at 7:39:34 AM UTC+2, Eric Shulman wrote:
However... I've also added another param, autostart="yes", which will actually trigger the $action-timeout as soon as it is rendered, even if it's not inside a $button.
I'm not sure when this param will be useful, and it's best to consider it "experimental" for now.
 
@Eric. ... I personally would create 2 plugins. 1 with the "useful" timeout and 1 with the potentially dangerous "experimental" parameter. 

As long as you don't specify the autostart="true" param, it just does the "useful" timeout when triggered from a user-action (button press).
Note that even without using autostart, you can still create "tail end" timer loops that can then be controlled by setting a flag field.

For example, here's how I implemented the timer's "elapsed time" display:

\define ticker_actions()
<$action-timeout delay="1000" id="$(currentTiddler)$" actions="""
   <$list filter="
[[$(currentTiddler)$]is[tiddler]]">
      <$action-setfield $timestamp="
no" now=<<now YYYY0MM0DD0hh0mm0ss0XXX>> />
      <$reveal default={{!!stop}} type="
match" text="">
         <$importvariables filter="
TiddlyTools/Timer"> <<ticker_actions>> </$importvariables>
      </$reveal>
   </$list>
"""
/>
\end

Note how the timeout widget invokes an action that sets the "now" field (to track the current time...
used to calculate the elapsed time) and then it checks if the "stop" field is blank.  If it is, then it
schedules another timeout to occur in one second.  This function will keep invoking itself once
a second until "stop" is set to a non-blank value (i.e., "true"), which is triggered by the user 
when they explicitly press the "stop" button in the timer interface.

-e


Eric Shulman

unread,
Jul 19, 2020, 10:31:59 AM7/19/20
to TiddlyWiki
On Sunday, July 19, 2020 at 3:24:36 AM UTC-7, Jed Carty wrote:
To join in the fun, I also made a $action-delay widget that delays the execution of any action widgets contained inside it by a set time. It is an action widget so it gets triggered by the normal mechanisms.

Except for the optional autostart="true" param (to invoke the widget outside of a $button) and using milliseconds
for the delay value, my code does pretty much the same as your $action-delay widget.

Normally, I eschew duplication of efforts, but in this case, I think I will stick with my own version of this widget
primarily because of the two differences noted above.  Triggering timeouts more often than 1 second is
useful when calculating elapsed times with sufficient accuracy to avoid processing overhead effects
as well as getting sub-second accuracy.

...and, I still think that the autostart="true" param has promise, even though it *might* cause some
"run-away" triggers if not used carefully.

-e

TW Tones

unread,
Jul 19, 2020, 10:00:28 PM7/19/20
to TiddlyWiki
Si, and Folks,

Interesting thread with some very interesting information and techniques.

Si Asked
I wonder if anyone has done something similar, or has a different approach worth sharing?

I understand the issues with alternative triggers and Eric was wise to keep the dirty method hidden, however I believe we need to extend functionality where possible, it can be done with with guidance and caution.

Because this is all so dependant on triggers I want to restate an Idea, I had some time a go and still intend to demonstrate, but the simple idea is to allow additional actions to be set for any existing trigger in tiddlywiki. The most common triggers are of course buttons. Buttons are triggered to save, close and edit, they can be used to save the wiki and reload, and many more functions. Often when trying to solve a problem with a trigger one (or more) of the existing buttons may actually fulfil this role. 

So given these various timers and triggers it may be quite easy to leverage existing buttons or the action navigate to trigger a timer action (conditionally).

One thought was to try and identify the missing triggers, for example a logout button that saves and resets the user would also be a suitable time to do "on exit" triggers, other on exit actions can be loaded on top of it, perhaps like backing up the content of local storage to file. Or my interest is check in on single file wikis.

An on exit trigger is the complement to the existing startup actions as they are for "on wiki load" trigger. Building a set of available buttons that by definition are used in the user interface at the practical occasions where we often need a trigger.

If we introduced a set of timer buttons, or a timer utility where you could set on off or reoccurring timers then enabled custom actions to be triggered 90% of all the timer trigger needs would be met. This tool can be designed to stop infinite loops as much as possible so the tools given to the user are not fragile.

As has being illustrated in this thread, date or period elapsed triggers are another desirable feature, This is a kind or raw functionality we should provide if not in the core in a key plugin. A generic non specific solution. One reason it should be provided upfront is it can be made efficient by cascading the test, on change in month we can test for a change in year, and at no other time except load.

The most tricky is change in day (midnight when wiki is still open)

Regards
Tony


On Sunday, June 21, 2020 at 10:08:10 PM UTC+10, si wrote:
I use TiddlyWiki as a task manager, among other things, and I thought it would be cool to know how long I spent working on a completed task.

Off the top of my head I imagine having a "start/stop" button that will alternately add a timestamp to the fields "start" and "stop". Then I could (hopefully) create a macro that calculates the total time spent on the task.

I wonder if anyone has done something similar, or has a different approach worth sharing?

Scott Kingery

unread,
Jul 19, 2020, 10:57:55 PM7/19/20
to TiddlyWiki
I built this Time Log almost 2 years ago. I've updated it over time and just today pushed a new version. https://techlifeweb.com/timelog.html

I need to dig into Eric's code posted here to see if I can make it better.

Scott

Eric Shulman

unread,
Jul 22, 2020, 10:42:25 PM7/22/20
to TiddlyWiki


* Now provides both DigitalClock *AND* AnalogClock displays
* When no clocks are displayed, the interrupt-driven timeouts are stopped so there's no wasted overhead

I'm particularly pleased with the new AnalogClock feature which is rendered using just CSS!!


enjoy,
-e

TW Tones

unread,
Jul 23, 2020, 3:17:16 AM7/23/20
to TiddlyWiki
Eric,

They look and work well, Can it update the fields like in SampleTask?

Regards
Tony

Mat

unread,
Jul 25, 2020, 4:50:52 PM7/25/20
to TiddlyWiki
Eric, as noted previously, very nice stuff.

I made a quick attempt to make a countdown timer (for an InstantBoss as mentioned previously in this thread) but it didn't really work out well. Basically I took a time, e.g 10 minutes and, in a filter, subtracted the timer value. How would you propose to use your timer for this?

Thanks.

<:-)

Eric Shulman

unread,
Jul 25, 2020, 11:29:07 PM7/25/20
to TiddlyWiki
On Saturday, July 25, 2020 at 1:50:52 PM UTC-7, Mat wrote:
I made a quick attempt to make a countdown timer (for an InstantBoss as mentioned previously in this thread) but it didn't really work out well. Basically I took a time, e.g 10 minutes and, in a filter, subtracted the timer value. How would you propose to use your timer for this?

I've just posted an update with a new tiddler:

To use it:
  • To display the countdown timer in another tiddler, use {{||TiddlyTools/Timer/CountDown}}
  • Enter the desired hours, minutes, and seconds in the input fields.
  • The start button begins the countdown. The input fields automatically update to show the time remaining.
  • The stop button pauses the countdown. You can adjust the time remaining. Press start to resume the countdown.
Coming soon: display a message when the countdown reaches 0

Let me know if you have any additional features you want it to do.

enjoy,
-e

TW Tones

unread,
Jul 26, 2020, 2:37:59 AM7/26/20
to TiddlyWiki
Eric,

Great stuff, One requirement may be to trigger a sound or mpeg to play?

Thanks for all your work, you are very prolific as well as helpful, always have being for more than a decade. Much appreciated.

Tony

Eric Shulman

unread,
Jul 26, 2020, 2:41:38 AM7/26/20
to TiddlyWiki
On Saturday, July 25, 2020 at 8:29:07 PM UTC-7, Eric Shulman wrote:
I've just posted an update with a new tiddler:

Coming soon: display a message when the countdown reaches 0

You can now enter and display a modal message when the countdown reaches 0.
Default message is "Countdown completed!"
Also, added a "reset" button to stop countdown and clear all inputs.

-e

Mat

unread,
Jul 26, 2020, 3:44:45 AM7/26/20
to TiddlyWiki
 
Let me know if you have any additional features you want it to do.

Thanks for asking! As noted, I'm hoping to use TW like an InstantBoss so I can set several consecutive timers; a typical session is "workduration + breakduration * reps", e.g 10+2 * 5. i.e for a total of one hour. If I understand your code, all "getTime" are started with "doStart" so I'm not sure how such multiple conseqcutive timers can be run? 

Like Tony requests, it would be very desirable if it is possible to fire an auditory file because otherwise one has to watch the countdown to know it has ended. (InstantBoss has the sound of a coffee being pured after 10 min, then after 2 min break it says "Aw, man" and after the full session there's well deserved applause - in other words, it fires different audio files.)

BTW, I found google gives a useable timer when searching "countdown timer".

<:-)

Eric Shulman

unread,
Jul 27, 2020, 7:48:23 AM7/27/20
to TiddlyWiki
On Sunday, July 26, 2020 at 12:44:45 AM UTC-7, Mat wrote:
Thanks for asking! As noted, I'm hoping to use TW like an InstantBoss so I can set several consecutive timers; a typical session is "workduration + breakduration * reps", e.g 10+2 * 5. i.e for a total of one hour. If I understand your code, all "getTime" are started with "doStart" so I'm not sure how such multiple consecutive timers can be run? 

I've just posted an update: http://tiddlytools.com/timer.html

I refactored the TiddlyTools/Timer/CountDown code to support "Programmed Countdown Sequences" (aka, "consecutive timers").


Note that this tiddler is *experimental*... I think I can simplify the "programmed" syntax
as well as adding support for repeating timer "sessions" (e.g. "workduration + breakduration * reps")
I'd also like to make some improvements to the interface, such as letting you *enter* times and
messages for each consecutive timer, rather than directly coding that information into the tiddler.
There's also a little bug (gasp!) where the countdown skips 1 second when starting the consecutive timers.

Give it a try and let me know what you think.

enjoy,
-e

Mat

unread,
Jul 27, 2020, 10:01:27 AM7/27/20
to TiddlyWiki
Eric Shulman wrote:
"Programmed Countdown Sequences" (aka, "consecutive timers").
Give it a try and let me know what you think.

Looks great! I am totally confusded by the notes there though, i.e:
  • When the first countdown ends, you will get an additional minute.
"First" should probably read "third" (counting from left), or better yet, "the seconds countdown"? Or maybe you do refer to the hours countdown and the bug you mention so when the hours are ended, there is buggily an extra minute ended?
  • When the second countdown ends, you will get an additional 30 seconds.
...??? 
  • When the third countdown ends, the sequence is completed.
Maybe you mean, when all three are ended it is completed?

I'm probably missing something obvious because I clearly don't understand.

<:-)

Eric Shulman

unread,
Jul 27, 2020, 10:34:28 AM7/27/20
to TiddlyWiki
On Monday, July 27, 2020 at 7:01:27 AM UTC-7, Mat wrote:
Eric Shulman wrote:
"Programmed Countdown Sequences" (aka, "consecutive timers").
Give it a try and let me know what you think.

Looks great! I am totally confusded by the notes there though, i.e:
  • When the first countdown ends, you will get an additional minute.
"First" should probably read "third" (counting from left), or better yet, "the seconds countdown"? Or maybe you do refer to the hours countdown and the bug you mention so when the hours are ended, there is buggily an extra minute ended?
  • When the second countdown ends, you will get an additional 30 seconds.
...??? 
  • When the third countdown ends, the sequence is completed.
The 3 input fields are hours, minutes, and seconds... and are only used as input for the first countdown.
The *second* countdown doesn't use those inputs and is coded directly into the tiddler using hours=00, minutes=01, seconds=00.
The *third* countdown is also coded directly into the tiddler using hours=00, minutes=00, seconds=30.

The bug occurs in the 2nd countdown where you can see the time remaining jump from 1 minute to 58 seconds
and in the 3rd countdown where the time remaining jumps from 30 seconds to 28 seconds.

I hope that helps explain things a bit better...

-e
 

Mat

unread,
Jul 27, 2020, 12:22:15 PM7/27/20
to TiddlyWiki
I hope that helps explain things a bit better...

Yes. I mistook "the n:th countdown" to mean "the n:th counter". I would think this is an easy mistake to make since there are three counters in front of ones eyes as one reads this.

So do I understand it right that to achieve a repetition of 10minutes + 2minutes * 5times, I'd need to, in the tiddler, type in about 10 calls, right? I made a quick, but failed attempt to modify firstDone into: 

\define firstDone()
<$list filter="[range[5]]" variable="_NUL">
<$list filter="00:00:03 00:00:06" variable=duration>
<$vars
 H={{{ [<duration>split[:]nth[1]] }}}
 M={{{ [<duration>split[:]nth[2]] }}}
 S={{{ [<duration>split[:]nth[3]] }}}
>
<$macrocall $name=setCountdown H=<<H>> M=<<M>> S=<<S>> />
</$vars>
</$list>
</$list>
\end

...but it seems to omit the 00:00:03 item.


I must also ask something else - what kind of syntax is this:

\define controls()
<$vars here=<<currentTiddler>>>
<$vars done=<<firstDone>>>
<<getCountdown>> <<start>> <<stop>> <<reset>>
\end

...i.e no closing vars tags!? I know on *can* do that but is the system OK with it? No sideeffects?

<:-)

Eric Shulman

unread,
Jul 27, 2020, 1:29:17 PM7/27/20
to TiddlyWiki
On Monday, July 27, 2020 at 9:22:15 AM UTC-7, Mat wrote:
So do I understand it right that to achieve a repetition of 10minutes + 2minutes * 5times, I'd need to, in the tiddler, type in about 10 calls, right? I made a quick, but failed attempt to modify firstDone into: 

\define firstDone()
<$list filter="[range[5]]" variable="_NUL">
<$list filter="00:00:03 00:00:06" variable=duration>
<$vars
 H={{{ [<duration>split[:]nth[1]] }}}
 M={{{ [<duration>split[:]nth[2]] }}}
 S={{{ [<duration>split[:]nth[3]] }}}
>
<$macrocall $name=setCountdown H=<<H>> M=<<M>> S=<<S>> />
</$vars>
</$list>
</$list>
\end

Each of the "...Done" macros handles one, and ONLY one, countdown result.   For example, firstDone()
\define firstDone()
<<showMessage "First Countdown ended. You have another minute!">>
<$vars done=<<secondDone>>>
<<setCountdown 00 01 00>>
\end

Is invoked when the first countdown ends, and it's job is to
* display a message 
* set up the next "done" handler (i.e., "secondDone()")
* start the next countdown with the specified hh mm ss values

There is *currently* no easy syntax for setting up a repeating pattern of countdowns.
That is something I will be adding soon.
In the mean time, to do the one hour cycle you described, you would need to
create 10 separate macros (2 macros per cycle, times 5 cycles) and then
"daisychain" them using the syntax demonstrated in the SampleCountdownSequence tiddler.
 
I must also ask something else - what kind of syntax is this:
\define controls()
<$vars here=<<currentTiddler>>>
<$vars done=<<firstDone>>>
<<getCountdown>> <<start>> <<stop>> <<reset>>
\end
...i.e no closing vars tags!? I know one *can* do that but is the system OK with it? No sideeffects?

Yeah.  When the end of a macro is reached, any unterminated widgets are automatically terminated.

This comes in handy for several types of widgets, such as $vars and $tiddler.
For example, take a look in TiddlyTools/Timer/CountDown at the showRemaining() macro:

\define showRemaining()
<$tiddler tiddler=<<temp>>>
<$vars  R={{{ [<temp>get[text]subtract[1]]       }}}>
<$vars  H={{{ [<R>divide[3600]trunc[]]           }}}>
<$vars HM={{{ [<H>multiply[60]]                  }}}>
<$vars  M={{{ [<R>divide[60]subtract<HM>trunc[]] }}}>
<$vars HS={{{ [<H>multiply[3600]]                }}}>
<$vars MS={{{ [<M>multiply[60]]                  }}}>
<$vars  S={{{ [<R>subtract<HS>subtract<MS>]      }}}>
<$action-setfield hours={{{ [<H>addprefix[00]split[]last[2]join[]] }}} />
<$action-setfield  mins={{{ [<M>addprefix[00]split[]last[2]join[]] }}} />
<$action-setfield  secs={{{ [<S>addprefix[00]split[]last[2]join[]] }}} />
\end

It's very convenient to NOT have to terminate all those $vars (and the $tiddler).
Of course, if the $vars occurred inside other syntax (e.g., a <$reveal>), then you MUST terminate each $vars before the
</$reveal> or there would be unbalanced nesting.  However, in the above example, since the $vars and $tiddler occur
at the outermost level of the macro definition, the end of the macro takes care of it for you, regardless of how many
$vars were used.

-e

Mat

unread,
Jul 27, 2020, 3:18:42 PM7/27/20
to TiddlyWiki
Eric Shulman wrote:
There is *currently* no easy syntax for setting up a repeating pattern of countdowns.
That is something I will be adding soon.
In the mean time, to do the one hour cycle you described, you would need to 
[...]
 
Thank you, especially for continuing to develop and improve it :-)

 
Yeah.  When the end of a macro is reached, any unterminated widgets are automatically terminated.

Very good to know. I have not seen this by anyone. Shouldn't we slim down the core using this?

Thank you Eric

<:-)

Eric Shulman

unread,
Jul 28, 2020, 3:36:54 PM7/28/20
to TiddlyWiki
On Monday, July 27, 2020 at 12:18:42 PM UTC-7, Mat wrote:
Eric Shulman wrote:
There is *currently* no easy syntax for setting up a repeating pattern of countdowns.
That is something I will be adding soon.


* SampleCountdownSequence now does cycles!

Demo is 10 minutes work session followed by 2 minutes break time, repeated 5 times
(1 hour total).

There's still more customization and optimization to come:

* Interface for entering worksession/breaktime durations (currently coded into the demo)
* Option for triggering other actions (e.g., "play a sound") (currently just shows modal notifications)

Let me know what else it should do...

-e

Mat

unread,
Jul 28, 2020, 6:25:44 PM7/28/20
to TiddlyWiki
Eric Shulman wrote:
* SampleCountdownSequence now does cycles!

Yehaaww!
 
Demo is 10 minutes work session followed by 2 minutes break time, repeated 5 times
(1 hour total).

Good demo choice ;-) ;-) 
 
Let me know what else it should do...

1) RSOE at when worksession 4 break is to start. "Uncaught RangeError: Maximum call stack size exceeded"

2) For the practical use of these CountdownSequences, it would be neat if it is possible to define sessions that one can select. I imagine a little form where you fill in the session name and its steps, something like so (copied straight from my actual routine)

Daily Worksession
Read book     : 30 m
Lunch             : 2 m
TiddleFiddle   : 10:30 h
Family dinner : 5 m

Exercise before breakfast
Pushups    : 2:59 h
Run 15 km : 15 m
Ice-bath     : 3 h 

3)  If one doesn't dismiss a modal, the subsequent modals will (eventually) pile on in front. (Interestingly, also the dark surrounding the modal is added so it gets darker and darker). Maybe a modal should clear any preceding modal?

Thank you!

<:-)

Eric Shulman

unread,
Jul 28, 2020, 7:23:08 PM7/28/20
to TiddlyWiki
On Tuesday, July 28, 2020 at 3:25:44 PM UTC-7, Mat wrote:
Eric Shulman wrote:
* SampleCountdownSequence now does cycles!

Yehaaww!
 
Demo is 10 minutes work session followed by 2 minutes break time, repeated 5 times
(1 hour total).

Good demo choice ;-) ;-) 
 
Let me know what else it should do...

1) RSOE at when worksession 4 break is to start. "Uncaught RangeError: Maximum call stack size exceeded"

I have not seen this error, and I've run through the whole sequence of 5 work sessions/break times (with shortened times of 1 minute work and 15 seconds break).   Can you tell me more about what happened?  Can you reproduce it with the latest version (just updated to add configuration controls)


2) For the practical use of these CountdownSequences, it would be neat if it is possible to define sessions that one can select. I imagine a little form where you fill in the session name and its steps, something like so (copied straight from my actual routine)

Daily Worksession
Read book     : 30 m
Lunch             : 2 m
TiddleFiddle   : 10:30 h
Family dinner : 5 m

Exercise before breakfast
Pushups    : 2:59 h
Run 15 km : 15 m
Ice-bath     : 3 h 

Right now, the "demo" has only two steps, "work session" and "break time".
Each step is implemented by "daisy-chaining" coded macros.
Ideally, you would just enter a table of steps and times and the macros
would be auto-generated.  But that's certainly more complex.
I need to think about the best way to do this.

Also... you only spend 2 minutes for lunch and 5 minutes for dinner, but 3 hours for an ice-bath?!? 
and you can run 15km in just 15 minutes?!?  WOW!
 
3)  If one doesn't dismiss a modal, the subsequent modals will (eventually) pile on in front. (Interestingly, also the dark surrounding the modal is added so it gets darker and darker). Maybe a modal should clear any preceding modal?

I need to look into this a bit to figure out how to programatically dismiss an existing modal.
 
Thank you!

You're welcome.  This has been an interesting exercise in interrupt-driven TW coding.

-e

Mat

unread,
Jul 29, 2020, 9:15:19 AM7/29/20
to TiddlyWiki
Eric Shulman wrote:
1) RSOE
I have not seen this error, and I've run through the whole sequence of 5 work sessions/break times (with shortened times of 1 minute work and 15 seconds break).   Can you tell me more about what happened?  Can you reproduce it with the latest version (just updated to add configuration controls)

Yes, having tried it now several times I do get it to happen repeatedly in the latest version: I just leave the default(!) values and start the countdown and let it run while I do other stuff in other tabs. I do peek back every now and then to see how things were going. Unfortunately I can't say after exactly how long time it happens but my best estimation is after some three sessions. Not faster.
I'm on Win10, Chrome. 


Also... you only spend 2 minutes for lunch and 5 minutes for dinner, but 3 hours for an ice-bath?!? 
and you can run 15km in just 15 minutes?!?  WOW!

You don't ??? 
 

 I need to look into this a bit to figure out how to programatically dismiss an existing modal.

Perhaps worth considering that they don't have to be modals. Just sayin'. Apropos modals, here's an interesting css based variant- basically the thing you want to show has a pseudoelement beneath it with dark color that covers the whole screen. (...or maybe that is exactly how a 

<:-)

Eric Shulman

unread,
Jul 29, 2020, 11:20:18 AM7/29/20
to TiddlyWiki
On Wednesday, July 29, 2020 at 6:15:19 AM UTC-7, Mat wrote:
Eric Shulman wrote:
1) RSOE
I have not seen this error, and I've run through the whole sequence of 5 work sessions/break times (with shortened times of 1 minute work and 15 seconds break).   Can you tell me more about what happened?  Can you reproduce it with the latest version (just updated to add configuration controls)

Yes, having tried it now several times I do get it to happen repeatedly in the latest version: I just leave the default(!) values and start the countdown and let it run while I do other stuff in other tabs. I do peek back every now and then to see how things were going. Unfortunately I can't say after exactly how long time it happens but my best estimation is after some three sessions. Not faster.
I'm on Win10, Chrome. 

uh oh.  This suggests something bad about how my $action-timeout code works.  Since the timeout widget re-invokes itself each second, I think it's leaving behind the previous "timed out" widget object, resulting in a slow accumulation of junk on the call stack.  This is *very* bad.  I will have to think about ways to re-write the underlying JS to not do this.   This likely also affects the basic "timer" functionality (if the timer runs too long).
 
 I need to look into this a bit to figure out how to programatically dismiss an existing modal.

Perhaps worth considering that they don't have to be modals. Just sayin'. Apropos modals, here's an interesting css based variant- basically the thing you want to show has a pseudoelement beneath it with dark color that covers the whole screen. (...or maybe that is exactly how a ...

I did some experimenting, and it doesn't look like modals can be programmatically dismissed.  Some alternatives I can think of:
1) Use tm-notify to put up the message.  These messages automatically go away (by default, after 3 seconds).  My concern is that the message might not be as noticeable.
2) Don't use ANY TWCore message, but simply write the status into a separate tiddler.  Then, just transclude that tiddler's content somewhere (maybe with an ok/hide button)
3) Possibly combine (2) with a modal-like display.  Since the tiddler in (2) would be overwritten each time, the previous display would automatically vanish.

Stay tuned for another update... but it might be a while.  These last few problems are tricky!

-e

Ken Gray

unread,
Jul 29, 2020, 11:20:46 AM7/29/20
to TiddlyWiki
Silly question: How do I install this?

Mat

unread,
Jul 29, 2020, 11:50:33 AM7/29/20
to TiddlyWiki
Eric Shulman wrote:
uh oh.  This suggests something bad about how my $action-timeout code works.  Since the timeout widget re-invokes itself each second, I think it's leaving behind the previous "timed out" widget object, resulting in a slow accumulation of junk on the call stack.  This is *very* bad.  I will have to think about ways to re-write the underlying JS to not do this.   This likely also affects the basic "timer" functionality (if the timer runs too long).

:-/ sorry. BUT before anything; did you or anyone else succeed to recreate the problem?
One thought: I recall these news about Chrome some time ago which kind of deactivates unused tabs to save memory... might that have sth to do with it? (I have not hit the ceeling in memory usage during these tests, at least nothing I've noticed.)

 
 I need to look into this a bit to figure out how to programatically dismiss an existing modal.

Another conceptual approach: I note that InstantBoss instead functions in another way and which possibly makes more sense: It demands that the user actively dismisses the popup in order to start the next countdown. After all, if you're not attentive to the alert, then what's the point in having it continue to count down on your next task? IMO it makes sense: If one wants an unstoppable countdown... then it's just a backward counting clock! Demanding that the user actually starts the next countdown is actually giving control to the user.

BTW, even if you were not to agree with that logic, it is a functionality that I know is useful so I guess it's a feature request then :-)

 <:-)

Eric Shulman

unread,
Jul 29, 2020, 11:52:20 AM7/29/20
to tiddl...@googlegroups.com
On Wednesday, July 29, 2020 at 8:20:46 AM UTC-7, Ken Gray wrote:
Silly question: How do I install this?

It's not packaged as a plugin, so you just need to copy all the TiddlyTools/Timer tiddler into your TiddlyWiki.

You can do this by dragging each tiddler title, one at a time, from the SideBar list and dropping it into your
TiddlyWiki.  This will create a temporary $:/Import tiddler. When you have dropped all the tiddlers, you
can then press the "import" button in the $:/Import tiddler to actually install those tiddlers.  Note that
after importing, you will need to save-and-reload since TiddlyTools/Timer/action-timeout.js uses javascript
code to define a new widget.

Another way to import the whole bunch is to use the $:/AdvancedSearch Filter tab with this filter:
   [all[]!prefix[$:/]]
This should result in a list of all the tiddlers in the document (excluding system tiddlers).
Then, use the "Export tiddlers" button (the "half box with arrow" next to the filter input field), and
choose "JSON file".  This will save a "tiddlers.json" file on your system.  Note: if you have your
browser set to "Always ask where to save downloads", it will give you a dialog box to enter the
filename/location.  If you browser is not set to "ask", then then look in your Downloads folder.
Then, drag-n-drop this file onto your TW to do the same $:/Import process as described above.

-e

Ken Gray

unread,
Jul 29, 2020, 1:51:29 PM7/29/20
to TiddlyWiki
Thanks!

Eric Shulman

unread,
Jul 29, 2020, 8:49:49 PM7/29/20
to TiddlyWiki
On Wednesday, July 29, 2020 at 8:20:18 AM UTC-7, Eric Shulman wrote:
I did some experimenting, and it doesn't look like modals can be programmatically dismissed.  Some alternatives I can think of:
1) Use tm-notify to put up the message.  These messages automatically go away (by default, after 3 seconds).  My concern is that the message might not be as noticeable.
2) Don't use ANY TWCore message, but simply write the status into a separate tiddler.  Then, just transclude that tiddler's content somewhere (maybe with an ok/hide button)
3) Possibly combine (2) with a modal-like display.  Since the tiddler in (2) would be overwritten each time, the previous display would automatically vanish.


* TiddlyTools/Timer/SampleCountdownSequence now uses a custom message display instead of tm-modal (solution #2, above)
* improved "start" button logic to disable button when time values are all zero or countdown is actively running

Next... try to figure out where the memory leak is in the $action-timeout widget.  This may be a really hard problem to solve.

-e

TW Tones

unread,
Jul 29, 2020, 10:55:46 PM7/29/20
to TiddlyWiki
Eric,

I was just reviewing the state of play on your timer work. It really is fantastic. These features have being long sort after, a question and a feature request if I may.

Question
  • What function do you see the pause-able clock playing?
    • One could click it when starting work and review it
    • But I wonder if you have another idea in mind.
Feature request
  • Perhaps this already possible, but is it possible to trigger some actions defined in a tiddler or macro when a timer completes?
    • I ask this because then any set of actions can be triggered.
    • One could send a message to save 15 mins after the last save or regularly.
    • Or in startup set a count down to open a modal 10 minutes
    • Perhaps even a timer to save and logout/check in after 30 minutes of inactivity
      • I assume we can just reset the value to restart the count down when we save.
    • Not unlike your SampleCountdownSequence one could use a timer action to trigger another timer action
      • This a set of tiddlers with expected times eg a calendar could trigger and action/message and set the next timer on the next tiddler.
This solution really benefits from you being the author with you extensive knowledge, because timing solutions can kill an app or software, if not done correctly, so this is greatly appreciated.


Regards
TW Tones

TW Tones

unread,
Jul 29, 2020, 11:01:47 PM7/29/20
to TiddlyWiki
Eric,

Sorry, one more point.

In some cases we do not need to keep the time start and end history, and the total time work can be added to the previous total.

I imagine for example having a sidebar with a set of elapsed timers where one would click while working on correspondence, phone calls, coding, customer relations social media etc... Saving total for at the end of day in a journal tiddler, but starting afresh each day. This would support a range of productivity methods suggested in time management and productivity methods.

I think I can build this on top of your solution already, but thought I would share what I would possibly want to do once this is published.

Thanks Again
TW Tones

Eric Shulman

unread,
Jul 30, 2020, 5:51:51 AM7/30/20
to TiddlyWiki
On Wednesday, July 29, 2020 at 7:55:46 PM UTC-7, TW Tones wrote:
  • What function do you see the pause-able clock playing?
    • One could click it when starting work and review it
    • But I wonder if you have another idea in mind.
At it's basic level, each instance of the clock (analog or digital) adds a once-a-second repeating interrupt that writes to a $:/temp tiddler.
If there are multiple instances, there are multiple interrupts occurring.  While this is not a lot of overhead, it's conceivable that there might
be a situation where this overhead could have an effect on performance of some timing-critical processing like animations or streaming
high-bandwidth video, or some such use-case.  It just seems reasonable to have a way to toggle the clock interrupts if/when it becomes
necessary to do so.
 
Feature request
  • Perhaps this already possible, but is it possible to trigger some actions defined in a tiddler or macro when a timer completes?
  • I ask this because then any set of actions can be triggered.
The general-purpose Timer/Countdown invokes a tm-modal message display when the timer completes.

The SampleCountdownSequence doesn't use tm-modals, but does create a tiddler containing a message,
and then displays that tiddler content inline.

The new Timer/AutoSaver (just wrote it tonight!!!) invokes a tm-save-file message to actually save the file.

In general, any set of action-* widgets could be fired off when a timer completes.  Perhaps I can add
a way to specify an optional tiddler title that could contain action-* widgets to be triggered by the
general-purpose Countdown timer.
    • One could send a message to save 15 mins after the last save or regularly.
This is essentially what the new Timer/AutoSaver does.  It sets up a timer "loop" that periodically
performs a tm-save-file action.  The default is once-per-hour, but it is configurable to suit the
work patterns of individual users (i.e, some people might like to save every 15 or 30 minutes) 
    • Or in startup set a count down to open a modal 10 minutes
I haven't thought about triggering a Countdown timer on startup... but it shouldn't be too hard
to implement.  The basic Timer/Countdown expect user interaction to trigger the start of
processing, but a simple set of action-* widgets could be used at startup to create an
appropriate $:/temp/timer/* tiddler with the right fields to specify the hours, minutes, seconds,
go flag (set to "go" for "autostart"), and done (the action to perform when the timer completes)
    • Perhaps even a timer to save and logout/check in after 30 minutes of inactivity
I'm not sure how we would determine "inactivity".

This solution really benefits from you being the author with you extensive knowledge, because timing solutions can kill an app or software, if not done correctly, so this is greatly appreciated.

Aw, gee.  Shucks!  Thanks for the nice words.

Eric Shulman

unread,
Jul 30, 2020, 6:02:11 AM7/30/20
to TiddlyWiki
On Wednesday, July 29, 2020 at 8:01:47 PM UTC-7, TW Tones wrote:
In some cases we do not need to keep the time start and end history, and the total time work can be added to the previous total.

Each task timer tiddler stores the start, end, elapsed, and total times as *lists* in fields.
Each start/end time is a standard 17-digit timestamp number. 
Each elapsed/total time value is a numeric value with a maximum of 3 decimal places.

Thus, the storage overhead for keeping all this data is relatively minor.
 
I imagine for example having a sidebar with a set of elapsed timers where one would click while working on correspondence, phone calls, coding, customer relations social media etc... Saving total for at the end of day in a journal tiddler, but starting afresh each day. This would support a range of productivity methods suggested in time management and productivity methods.

It would be easy enough to create a new Journal tiddler with a template that embeds a Task timer.
In this way, each time you start a new journal, you start a fresh collection of start, end, elapsed
and total list fields in that tiddler.  Of course, if you really don't need/want to save the start, end
or elapsed values, it would also be easy enough to write a bit of $list-based wiki code that would
delete those list fields from older tiddlers.
 
-e

Eric Shulman

unread,
Jul 30, 2020, 10:53:12 AM7/30/20
to TiddlyWiki
On Thursday, July 30, 2020 at 2:51:51 AM UTC-7, Eric Shulman wrote:
The new Timer/AutoSaver (just wrote it tonight!!!) invokes a tm-save-file message to actually save the file.


* fixed handling for TiddlyTools/Timer/Setup autosave interval (autosave_hours, autosave_mins, and autosave_secs)

Previously, the autosave interval entered via the config popup was only being applied for one autosave cycle.
After the current cycle, it was ignoring the settings saved in TiddlyTools/Timer/Setup, and reverting back to
using the default "factory settings" (1 hour).

Now, it correctly uses the configured autosave interval for each autosave cycle.  To revert to the 1 hour
default setting, use the config popup's "reset" button.

enjoy,
-e

Eric Shulman

unread,
Jul 31, 2020, 12:36:52 PM7/31/20
to TiddlyWiki
On Wednesday, July 29, 2020 at 8:50:33 AM UTC-7, Mat wrote:
Eric Shulman wrote:
uh oh.  This suggests something bad about how my $action-timeout code works.  Since the timeout widget re-invokes itself each second, I think it's leaving behind the previous "timed out" widget object, resulting in a slow accumulation of junk on the call stack.  This is *very* bad.  I will have to think about ways to re-write the underlying JS to not do this.   This likely also affects the basic "timer" functionality (if the timer runs too long).

:-/ sorry. BUT before anything; did you or anyone else succeed to recreate the problem?

I ran through a full 1 hour sequence without any error occurring.  In addition, I've run the AnalogClock and DigitalClock continuously for *many* hours.  The clocks also tick once a second, so if there was a memory leak of some kind, they *should* have triggered it.  Again... no errors appeared.  If the error still happens for you, try to give as much info as possible to help me find the cause.  Specifically, what *other* activities did you do during the CountdownSequence?  Did you open/close the clocks?  Did you pause/reset the Countdown?  etc.
 
Another conceptual approach: I note that InstantBoss instead functions in another way and which possibly makes more sense: It demands that the user actively dismisses the popup in order to start the next countdown. After all, if you're not attentive to the alert, then what's the point in having it continue to count down on your next task? IMO it makes sense: If one wants an unstoppable countdown... then it's just a backward counting clock! Demanding that the user actually starts the next countdown is actually giving control to the user.

BTW, even if you were not to agree with that logic, it is a functionality that I know is useful so I guess it's a feature request then :-)

I've just added an *optional* setting to "pause between sessions".  When this checkbox is enabled, the CountdownSequence uses a modal dialog instead of the "inline message display" to announce the end of each worksession and breaktime.  The countdown is automatically paused while the modal dialog is displayed, and only resumes when you press the "ok" button.  You can even toggle the option while the CountdownSequence is running and it will be applied when the next event occurs.

-e

TiddlyTweeter

unread,
Jul 31, 2020, 2:41:26 PM7/31/20
to TiddlyWiki
Eric

Fabulously flexible and useful tool! Could replace the smorgasbord of not-interworking time tools I currently use.

In one vital case I'd like to trigger sound alarms on end of countdowns (alerts for taking tablets).

I can't quite see how to do that yet. Could you give a clue so I can implement that?

Best wishes
TT

Eric Shulman

unread,
Jul 31, 2020, 5:52:37 PM7/31/20
to TiddlyWiki
On Friday, July 31, 2020 at 11:41:26 AM UTC-7, TiddlyTweeter wrote:
Fabulously flexible and useful tool! Could replace the smorgasbord of not-interworking time tools I currently use.
In one vital case I'd like to trigger sound alarms on end of countdowns (alerts for taking tablets).
I can't quite see how to do that yet. Could you give a clue so I can implement that?

I will be adding another feature to the Timer/Countdown, so that you can specify a separate tiddler
containing $action-* widgets that will be invoked when the countdown reaches zero.

I'll probably have an update for you later today or early tomorrow.

-e

Eric Shulman

unread,
Jul 31, 2020, 8:27:56 PM7/31/20
to TiddlyWiki
On Friday, July 31, 2020 at 2:52:37 PM UTC-7, Eric Shulman wrote:
On Friday, July 31, 2020 at 11:41:26 AM UTC-7, TiddlyTweeter wrote:
Fabulously flexible and useful tool! Could replace the smorgasbord of not-interworking time tools I currently use.
In one vital case I'd like to trigger sound alarms on end of countdowns (alerts for taking tablets).
I can't quite see how to do that yet. Could you give a clue so I can implement that?

I will be adding another feature to the Timer/Countdown, so that you can specify a separate tiddler
containing $action-* widgets that will be invoked when the countdown reaches zero.


To invoke additional custom actions when the countdown is completed:

  • Create a tiddler with the same name as your countdown tiddler with an added suffix of "Actions".
  • Enter the desired <$action-... /> widget syntax into the body of that tiddler.
  • See SampleCountdownActions for an example.
enjoy,
-e

TW Tones

unread,
Jul 31, 2020, 9:13:11 PM7/31/20
to TiddlyWiki
Eric,

Thanks for the timer actions it adds a powerful dimension.

This is more than enough for many applications however perhaps in future we could supply the action tiddlername as a variable or parameter.

Why?
Because I am very likely to have one action definition that is used many times and it would be nice to have one defined in this case, also allowing for one to be modified, affecting all that use that action tiddler.

An aside,
I am working on a solution to introduce additional actions to every button. It has some really nice methods in it which I would share now but I must revisit first. This would offer designers a particular generic method for creating matching actions, and reusing them as needed.

Regards
Tony

Eric Shulman

unread,
Aug 1, 2020, 12:14:40 AM8/1/20
to TiddlyWiki
On Friday, July 31, 2020 at 6:13:11 PM UTC-7, TW Tones wrote:
Thanks for the timer actions it adds a powerful dimension.
This is more than enough for many applications however perhaps in future we could supply the action tiddlername as a variable or parameter.

I've reworked how the custom actions are defined:

To define custom actions to be performed when the countdown is completed:

  • Add a macro named done in the tiddler containing your countdown timer. This macro replaces the standard message box.
  • Enter the desired <$action-... /> widget syntax inside the macro definition.
  • Use $(here)$ to refer to the title of tiddler containing your countdown timer.
  • To display the standard message box, use <<showMessage msg:"your message here">>
  • See  for an example.
I am very likely to have one action definition that is used many times and it would be nice to have one defined in this case, also allowing for one to be modified, affecting all that use that action tiddler.

To re-use one action definition multiple times you can define the done() macro to just transclude the <$action-.../> widgets from a separate tiddler, like this:
\define done() <$transclude tiddler="MyCommonDoneAction" />

-e

TW Tones

unread,
Aug 1, 2020, 3:29:57 AM8/1/20
to TiddlyWiki
Eric,

Thanks for that. I feel I need to return some demo solutions soon.

Best wishes
TW Tones

TW Tones

unread,
Aug 1, 2020, 4:14:43 AM8/1/20
to TiddlyWiki
Eric,

Before attempting to hack the clocks can you see an easy way to set them to operate in different time Zone's?

Perhaps with a +10 or -8 etc..? which does not take account of Daylight savings etc.. 

For example one could show the different time zones our tiddlywiki users are in.

Regards
Tony



On Saturday, August 1, 2020 at 2:14:40 PM UTC+10, Eric Shulman wrote:

Mat

unread,
Aug 1, 2020, 1:15:22 PM8/1/20
to TiddlyWiki
@Eric

First off - wow, it's getting really good!

There is still something not working 100%. I don't get the RSOE (great!) but the "Work session X in progress" doesn't update. This is what I do:
In Win10, with 3 Chrome windows open, each with between 5~20 tabs,
I open your page and start the SampleCountdownSequence with default values (and not touching the pause checkbox, but I do click Apply.)
Then I flip to another tab in that window and thereafter, over time, flip around doing other stuff. No other interaction with your page.
Peeking back at the page, after much more than 10+2 mins have passed, the countdown it still reads "Work session 1 in progress".

 
I've just added an *optional* setting to "pause between sessions". 

Excellent! I will have much use of this.

It is definitely pushing it, but like for the CSS clock you made it is much easier to see the countdown "visually" like e.g here. It would be cool with a little visual display in the corner of ones wiki showing how much more time one has to work.

Thanks for these really useful things!

<:-)

Eric Shulman

unread,
Aug 1, 2020, 4:14:35 PM8/1/20
to TiddlyWiki
On Saturday, August 1, 2020 at 1:14:43 AM UTC-7, TW Tones wrote:
Before attempting to hack the clocks can you see an easy way to set them to operate in different time Zone's?

It wasn't exactly "easy"... but I've added the ability to set a custom timezone offset for displaying the Analog and Digital clocks.  The offsets are specified relative to GMT.

Note: there's 18 clocks (9 analog and 9 digital), so the $action-timeout interrupt processing is a bit overdone, but I wanted to test some limits to see how bad it might get.

I'm experimenting with ways to optimize the action-timeout widget to use shared global timeouts so there would only be 1 timeout for Analog and 1 timeout for Digital, regardless of how many clocks are rendered.... but I haven't gotten this to work yet.  In the meantime, use the WorldClocks with a bit of caution in case it overwhelms the browser's resources or degrades the performance too much.

I've also added some more Setup options for the SidebarClocks so they are easy to show, hide and resize without having to edit the tiddler definition.

enjoy,
-e

TW Tones

unread,
Aug 1, 2020, 8:44:21 PM8/1/20
to TiddlyWiki
Eric,

The world clocks are wonderful, My family use is likely to be Australia and France, and perhaps other Australian Time Zones, so we only need two or more clocks to make this a valuable feature. I will see if I can source a Time Zone list, as tiddlywiki data, then one may select only the time zone perhaps that we want to phone. A little css play to show daylight/nighttime would be fun but in no way essential. That is for people to play with.

We need to build, as a community, a set of implementations based on your clock and timer solution because I think they will be in demand.

Thanks again for your contribution, superb.

Regards
Tony

Eric Shulman

unread,
Aug 1, 2020, 8:59:51 PM8/1/20
to TiddlyWiki
On Saturday, August 1, 2020 at 5:44:21 PM UTC-7, TW Tones wrote:
The world clocks are wonderful, My family use is likely to be Australia and France, and perhaps other Australian Time Zones, so we only need two or more clocks to make this a valuable feature. I will see if I can source a Time Zone list, as tiddlywiki data, then one may select only the time zone perhaps that we want to phone. A little css play to show daylight/nighttime would be fun but in no way essential. That is for people to play with.

Unfortunately, I've just found a nasty logic error in my handling for timezone.  It doesn't work right when calculating across date boundaries.  For example, my time zone is UTC-7 (Pacific Time), and I was converting from GMT to local time by simply subtracting the number of hours.  But... when its just after 5pm here the hour is 17, but in GMT, it's just after midnight *the next day* and the hours there is 00, so simply subtracting the timezone offset give hour 93 (00 - 07)!!!

Thanks again for your contribution, superb.

I *will* solve this problem.... but it's not done yet.

:(

I'll let you know when I have a *working* update!

-e

Eric Shulman

unread,
Aug 2, 2020, 1:20:32 AM8/2/20
to TiddlyWiki
On Saturday, August 1, 2020 at 5:59:51 PM UTC-7, Eric Shulman wrote:
Unfortunately, I've just found a nasty logic error in my handling for timezone.  It doesn't work right when calculating across date boundaries.  For example, my time zone is UTC-7 (Pacific Time), and I was converting from GMT to local time by simply subtracting the number of hours.  But... when its just after 5pm here the hour is 17, but in GMT, it's just after midnight *the next day* and the hours there is 00, so simply subtracting the timezone offset give hour 93 (00 - 07)!!!

I'll let you know when I have a *working* update!


The AnalogClock and DigitalClock now support optionally specifying the timezone offset.


Tony: check out the "adjustForTimezone()" code in TiddlyTools/Timer/DigitalClock (same code is also used in TiddlyTools/Timer/AnalogClock)

The math was tricky... and it still has two issues to deal with:
1) It needs to handle MONTH date adjustments (i.e., when it's the evening of 8/31 somewhere, it will be 9/01 somewhere else)
2) It needs to handle MINUTE timezone offset (there's a few timezones that aren't on the even hours.... especially in Australia!)

I also plan to build in a multi-select list of places, so you can choose which locations to show clocks for...

enjoy,
-e


Birthe C

unread,
Aug 2, 2020, 3:19:21 AM8/2/20
to TiddlyWiki
I am from Denmark. Copenhagen is GMT+1, but right now we have summertime  GMT+2. I guess summertime also will represent problems around the globe.

Birthe

Eric Shulman

unread,
Aug 2, 2020, 7:34:05 AM8/2/20
to TiddlyWiki
On Sunday, August 2, 2020 at 12:19:21 AM UTC-7, Birthe C wrote:
I am from Denmark. Copenhagen is GMT+1, but right now we have summertime  GMT+2. I guess summertime also will represent problems around the globe.

Yes... "Summertime" (aka Daylight Saving Time) is highly problematic for these calculations.

TiddlyWiki uses UTC (Universal Time Coordinated) as the basis for its system time values (e.g., the tiddler's created and modified timestamps).  See https://www.timeanddate.com/time/aboututc.html.  Unlike GMT (Greenwich Mean Time), UTC is not a time zone, and doesn't change during the summer months.

Right now, in California (where I am) we are currently using PDT (Pacific Daylight Time), which has an offset of -07:00 from UTC. In Autumn, we will switch back to PST (Pacific Standard Time), which has an offset of -08:00 from UTC.  Similarly, right now, in Denmark, you are currently using CEST (Central European Summer Time), which has an offset of +02:00 from UTC. In Autumn, you will switch back to CET (Central European Time), which has an offset of +01:00 from UTC.

My timer.html code doesn't account for "Summer Time" in any way.  It simply accepts an optional "offset" parameter which is currently hard-coded into the SampleWorldClocks tiddler, like this:
<<showClock "local time"    >> <<showClock "Honolulu" -1000>> <<showClock "Los Angeles" -0700>><br>
<
<showClock "New York" -0400>> <<showClock "London"   +0100>> <<showClock "Rome"        +0200>><br>
<
<showClock "Moscow"   +0300>> <<showClock "Tokyo"    +0900>> <<showClock "Sydney"      +1000>><br>

As currently written, the offsets are based on Summer Time values, which will be changing in the Autumn; e.g., while Los Angeles is currently -0700, it will be -08:00 later this year.

Complicating this is the fact that the dates on which the change to/from Daylight Saving Time (Summer Time) occurs is varies for different locations.  The US change occurs several weeks before/after Britain and Europe, so the time difference between those places actually varies (e.g., most of the time, California is 8 hours behind Britain, but for a few weeks in Spring and Autumn, we are just 7 hours behind).

Further complicating this is the fact that some places *do not switch at all*; e.g., Hawaii (Honolulu) is always -1000 from UTC because it is closer to the Equator and gets enough daylight all the time that it has no need to shift timezones seasonally.  There's also exceptions in some places that are mostly for political reasons; e.g., Arizona hasn't observed Daylight Saving Time for about the last 40 years, except for the Navajo Nation area, which does!

One exception in my SampleWorldClocks offsets is the "local time" clock.  It uses "<<now TZD>>" to get the current offset value directly from the system, rather than using a hard-coded offset value.  Thus, it will automatically change from Daylight Saving Time to Standard Time when the system clock changes in the Autumn.

At some point in the future, I will probably add the ability to select the time zone for a given location, so that manually editing the tiddler to change the hard-coded offsets won't be needed.  But you will still have to know which time zone a location is currently using, as the rules for where and when the switch between Daylight Saving Time and Standard Time occurs are just too complicated to calculate without a lot of effort.

... has your head exploded yet?  I think there's some blood dripping from my ears just from writing the above description of the problem!

-e

Birthe C

unread,
Aug 2, 2020, 8:20:50 AM8/2/20
to TiddlyWiki
Eric,

You are creating fantastic material for Tiddlywiki. Always well researched and you have a way of explaining difficult matters, that makes it lovely to read and learn from. You make things understandable at least to some level. (depending on the reader)
Thank you so much for taking the effort. And sorry to be the cause of head injury and ear bleeding. (A lovely expression though)

Birthe

Eric Shulman

unread,
Aug 2, 2020, 12:02:35 PM8/2/20
to tiddl...@googlegroups.com
On Saturday, August 1, 2020 at 10:20:32 PM UTC-7, Eric Shulman wrote:
The AnalogClock and DigitalClock now support optionally specifying the timezone offset.

The math was tricky... and it still has two issues to deal with:
1) It needs to handle MONTH date adjustments (i.e., when it's the evening of 8/31 somewhere, it will be 9/01 somewhere else)


* AnalogClock and DigitalClock now handles month "wraparounds".  For example:
    for local TZD < 0 (e.g., US), early morning 9/1 UTC becomes late evening 8/31 local time
    for local TZD > 0 (e.g., Australia), late evening 8/31 UTC becomes early morning 9/1 local time

-e

Eric Shulman

unread,
Aug 4, 2020, 1:29:33 PM8/4/20
to tiddl...@googlegroups.com
On Saturday, August 1, 2020 at 10:20:32 PM UTC-7, Eric Shulman wrote:
The AnalogClock and DigitalClock now support optionally specifying the timezone offset.
2) It needs to handle MINUTE timezone offset (there's a few timezones that aren't on the even hours.... especially in Australia!)

update August 4, 10:20am: http://TiddlyTools.com/timer.html

* AnalogClock and DigitalClock now handle MINUTE timezone offsets
* Added "New Delhi", "Perth" and "Adelaide" to http://tiddlytools.com/timer.html#SampleWorldClocks

 -e

Eric Shulman

unread,
Aug 4, 2020, 7:15:50 PM8/4/20
to tiddl...@googlegroups.com
update August 4, 16:05: http://TiddlyTools.com/timer.html

* AnalogClock/DigitalClock - fixed "days per month" (dpm) calculations in adjustForTimezone() 

This wasn't actually working before, but I didn't notice because date wraparound for July/August, both have 31 days.

Now, I tested with dates like "2020-03-01 04:00:00" with offset "-07:00"... result is Feb 28th... before it was Feb 31st!!!

Note dpm for February is hard-coded to "28", so it doesn't handle leap years.
<$set name="dpm" value="31 28 31 30 31 30 31 31 30 31 30 31"> <!-- days per month     -->
<$set name="dm"  value={{{ [
<dpm>split[ ]nth<mm>] }}}>        <!-- days in this month -->

Be sure to update before the end of September (the next month for which the bug would have mattered).

-e

Eric Shulman

unread,
Aug 5, 2020, 11:38:39 AM8/5/20
to TiddlyWiki
update August 5, 08:30: http://TiddlyTools.com/timer.html

* AnalogClock/DigitalClock - handle leap years in "days per month" (dpm) calculations in adjustForTimezone()

<$vars   leap={{{ [<yyyy>divide[4]split[.]count[]match[1]then[yes]] }}}>

<$set    name="dpm" value="31 28 31 30 31 30 31 31 30 31 30 31">
<!-- days per month -->
<$set    name="dpm" filter="[
<leap>!match[]]" value="31 29 31 30 31 30 31 31 30 31 30 31" emptyValue=<<dpm>>>

Be sure to update before the end of February 2024 (the next leap year)
This will be accurate until the year 2100 (which is NOT a leap year)

-e

Eric Shulman

unread,
Aug 8, 2020, 8:40:35 PM8/8/20
to TiddlyWiki
Update August 8, 17:22pm (PDT): http://TiddlyTools.com/timer.html

* There are a number of significant changes in this update:

1) TiddlyTools/Timer/AnalogClock and TiddlyTools/Timer/DigitalClock has been combined into TiddlyTools/Timer/Clocks
2) This new combined Clocks tiddler no longer uses "templated transclusion" (e.g., {{||TiddlyTools/Timer/AnalogClock}}) to embed a clock in a tiddler.
3) Instead, the new Clocks tiddler defines a <<clock>> *macro* that can be used to embed either the analog or digital clock.
4) This macro also includes parameters for specifying the timezone "offset" and an optional "format" override for the digital clock.
5) The SidebarClock and WorldClocks tiddlers have been updated to use the new <<clock>> macro instead of transclusions.
6) The WorldClocks tiddler has also been updated to provide a multi-select list for choosing which places to display.
7) A new tiddler, TiddlyTools/Timer/Places, has been added to define the list of available places for use with the WorldClocks tiddler.

Documentation for all of the above changes in syntax and usage have been updated in TiddlyTools/Timer/Info.

Note that, while these changes do not alter the overall functionality, they do make usage and customization easier and more consistent
by using macro parameters to control clock options, rather than defining "context variables" to pass those values to the underlying code.

Hopefully these changes don't cause too much grief for anyone who had been using the previous version...

Please let me know right away if you run into any problems with using this update.

enjoy,
-e

TW Tones

unread,
Aug 8, 2020, 11:33:10 PM8/8/20
to TiddlyWiki
Eric,

Looks good and very professional. You have addressed a serious gap in tiddlywiki capabilities through this set of solutions. For the community I thought I would provide some suggestions why I think this is a Big step;
  • Tiddlywiki has now increased the usable time date resolution to seconds (or less), perhaps before it was good for history and task management now its good for time management.
    • This allows time of day planning, event reminder and popups giving the "time of day" part of calendars, thus calendar events.
  • Time triggered events now allow an alternative trigger that does not demand a user trigger, this means new forms of automation are now possible that were not so easy, and at a minimum, needed a plugin to be developed for a specific purpose.
    • Solutions with Reminders are now much more feasible
  • With timed "events/actions" a TiddlyWiki can produce meaningful results without any user interactions
    • With TiddlyDesktop this can include triggering processes on the computer
I hope other that are inspired also share what they can get from your solution.

Thanks very much Eric.
Tones

Pit.W.

unread,
Aug 9, 2020, 6:08:53 AM8/9/20
to tiddl...@googlegroups.com

Eric,

  1. No problems running it so far. It exactly meets what I need for a task I am working on, so I use it for productivity. All fine so far.
  2. Do you plan to pack this into a plugin?
  3. I propose to set the default formats for date and time to ISO 8601 https://en.wikipedia.org/wiki/ISO_8601, to ease the use for newcomers.

Thanks as always,

Pit.W

--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/07bb6406-7509-437e-8eb2-3682793e79beo%40googlegroups.com.


_________________________________________________________________
________________________________________________________
Ihre E-Mail-Postfächer sicher & zentral an einem Ort. Jetzt wechseln und alte E-Mail-Adresse mitnehmen! https://www.eclipso.de


Eric Shulman

unread,
Aug 9, 2020, 10:43:28 AM8/9/20
to TiddlyWiki
Update August 9 7:43am PDT: http://TiddlyTools.com/timer.html

On Sunday, August 9, 2020 at 3:08:53 AM UTC-7, Pit.W. wrote:

No problems running it so far. It exactly meets what I need for a task I am working on, so I use it for productivity. All fine so far.
 
found a few configuration bugs... see below...  get the update!

Do you plan to pack this into a plugin?

Probably.. but not yet. 

I propose to set the default formats for date and time to ISO 8601 https://en.wikipedia.org/wiki/ISO_8601, to ease the use for newcomers.

Agreed.  See update notes below: 

* use ISO 8601 date format for Timer, Clocks, AutoSaver, WorldClocks, SidebarClocks
* note: Clocks, WorldClocks, SidebarClocks also show day name in addition to ISO 8601
* note: WorldClocks also always shows timezone offsets (using "+00:00" format)
* Timer - use "ticker_temp" instead of "temp" (was colliding with Clocks macros)
* Clocks - use "clock_temp" instead of "temp" (was colliding with Timer macros)
* WorldClocks - use "world_format" configuration for easier customization
* SidebarClocks - use sidebar_format (was using default clock_format by mistake)
* Info - added WorldClocks setup (world_format), revised WorldClocks info to match setup

enjoy,
-e

Eric Shulman

unread,
Aug 11, 2020, 9:06:44 PM8/11/20
to TiddlyWiki
Update August 11 6pm PDT: http://TiddlyTools.com/timer.html

NEW TIDDLER ADDED: TiddlyTools/Timer/Alarms

Displays a digital AlarmClock that can have multiple alarms set.

  • To define an alarm, begin by selecting OnceDaily, or a specific Day of the week.
  • If you select Once, select a monthdate, and year. The inputs will default to the current date.
  • Enter the desired hoursminutes and seconds using 24-hour notation. Any inputs left blank will default to the current time.
  • Enter an (optional) message that will be displayed when the alarm is triggered. If no message is provided a default message will be displayed.
  • Press [checkmark] to save the alarm. You can press [X] to reset the inputs.
  • When at least one alarm has been saved, a list of alarms will be displayed.
  • You can click on the list heading to pause/resume the saved alarms. While paused, [paused clock] is displayed, indicating that no alarm processing will occur.
  • To delete all saved alarms, press [trashcan] in the alarm list heading. You will be asked to confirm before the alarms are deleted.
  • To delete a specific saved alarm, press the [trashcan] button next to that alarm. You will be asked to confirm before the alarm is deleted.
enjoy,
-e

Eric Shulman

unread,
Aug 14, 2020, 10:40:23 PM8/14/20
to TiddlyWiki
Update August 14 7pm PDT: http://TiddlyTools.com/timer.html

MAJOR PERFORMANCE IMPROVEMENT!

Previously:
each timer, clock, countdown and alarm created a separate timeout. This resulted in increasing overhead as more clocks, timers, etc. were in use.

Now:
A new tiddler has been added: TiddlyTools/Timer/Ticker, tagged with $:/tags/StartupAction.  This tiddler establishes one *shared* ticker for all clocks, timers, and alarms. The result is a MAJOR reduction in overhead.  No matter how many clocks, timers, or alarms are in use, there is only ONE tick per second.  This is especially noticeable when displaying the WorldClocks, which currently can show up to 24 simultaneous clock displays (12 analog and 12 digital).  So... instead of 24 timeouts per second, there's only 1 !!!!

This also eliminates a subtle but troubling problem whereby tiddler refresh events would result in extra timeouts being started, resulting in "runaway" interrupts accumulating until performance slowed to a crawl (or even caused "stack overflow" red screens!).  Everything is now MUCH more stable, reliable, and efficient!

Note: CountDown (and AutoSaver) functions still start separate timeouts because they do very different logic.  Instead of simply tracking the current datetime value, they compute seconds of "time remaining", and when they reach 0 seconds, they stop and trigger events (e.g., a message display or a file save action). However, unlike the clock and alarm functions, the Countdown/AutoSaver functions do not "auto start on render".   Thus, they don't stack up
"runaway" interrupts due to refresh events, and the timeout overhead for each countdown is automatically eliminated as soon as it reaches 0.

enjoy,
-e

TW Tones

unread,
Aug 15, 2020, 2:59:12 AM8/15/20
to TiddlyWiki
Eric

This is fabulous. I was thinking of placing two world clock on a site. I realised that your solutions are contained in a set of tiddlers with a given prefix and I was not sure which are dependencies and which are options.

Have you planed to package these in a particular way or can you provide a little guidance as to how we can take these wonderful tools to our wikis?

I am happy to package these as needed for myself but would like a little guidance on this. Perhaps I should already understand this but I am uncertain. I have followed your development journey and are very impressed but not confident I know how to select or bundle these. I am aware as developer it can be hard to imagin what a nieve user will understand when you have such a deep knowledge since you built it.

I am very excited with the possibilities you have opened up to us all, and certainly plan to share some implementations back.

Thanks
Tones

Eric Shulman

unread,
Aug 15, 2020, 4:41:21 AM8/15/20
to TiddlyWiki
Update August 15 1am PDT: http://TiddlyTools.com/timer.html
 
Another bit of PERFORMANCE IMPROVEMENT...

Previously... I said that CountDown and AutoSaver still started separate timeouts (instead of the new *shared* TiddlyTools/Timer/Ticker StartupAction).  I had *claimed* that they don't stack up interrupts due to refresh events... but I was mistaken.  It turned out that if you repeatedly open and close a countdown timer, it would start to count faster and faster (because of the multiple stacked interrupts due to the refresh events).

Of course, this was a problem.... so I solved it.

Now... CountDown and AutoSaver now use the same *shared* TiddlyTools/Timer/Ticker.  I had to rework the ticker logic in TiddlyTools/Timer/CountDown, but it turned out to not be as difficult as I had thought.

So... now ALL the TiddlyTools/Timer functions use the same once-a-second ticker loaded as a StartupAction, and there is NO additional timeout overhead regardless of how many times you open/close these tiddlers.

-e

Eric Shulman

unread,
Aug 15, 2020, 4:46:34 AM8/15/20
to TiddlyWiki
On Friday, August 14, 2020 at 11:59:12 PM UTC-7, TW Tones wrote:

... I was not sure which are dependencies and which are options.

Have you planed to package these in a particular way or can you provide a little guidance as to how we can take these wonderful tools to our wikis?

I've updated the TiddlyTools/Timer/Info so that each tiddler indicates which other tiddlers it uses.
So... to install a particular feature, you need to copy that tiddler plus all the tiddlers listed as dependencies (i.e., "Uses: ....")

enjoy,
-e



TiddlyTweeter

unread,
Aug 15, 2020, 7:07:46 AM8/15/20
to TiddlyWiki
Eric

I'm really appreciating how you have worked on this set of tools.

You taking them "all the way". Persisting to squeeze the best out of TW. 
And thereby showing brilliance in the time "apps" & the underlying nature of "mother". App. dev leverage for purpose off given primitives. Superb.

I have read & sampled each step. Big learning experience for me! Very Good to see all the iterations. 

It is an instance of the actual iterative process of getting stuff optimal.

Its own case study! Briiliant!

Thank you!

(P.S. FWIW, your latest changes do solve the lag on "World Times" clocks.)

Best wishes
TT

Eric Shulman

unread,
Aug 17, 2020, 7:28:10 PM8/17/20
to TiddlyWiki
Update August 17 4pm PDT: http://TiddlyTools.com/timer.html

* IMPORTANT: TiddlyTools/Timer/Ticker adjusts for "drift" due to Alarms and CountDown processing overhead.
\define ticker(delay:1000)
<$action-timeout delay="$delay$" actions="""
   <$action-setfield $tiddler="
$:/temp/timer/ticker" text=<<now [UTC]YYYY0MM0DD0hh0mm0ss0XXX>> />
   <$importvariables filter="
TiddlyTools/Timer/Alarms">    <<alarms_check>>   </$importvariables>
   <$importvariables filter="
TiddlyTools/Timer/CountDown"> <<countdown_tick>> </$importvariables>
   <!-- ADJUST FOR MSEC DRIFT DUE TO PROCESSING OVERHEAD -->
   <$vars msec=<<now "
0XXX">>><$vars delay={{{ [[1000]subtract<msec>] }}}>
   <$macrocall $name="
ticker" delay=<<delay>> />
   </$vars></$vars>
"""
/>
\end
<<ticker>>
Previously, ticks could accumulate as much as several hundred milliseconds overhead that would eventually cause it to "skip" to the next second (this could occur as frequently as every few seconds, depending upon how much processing overhead was taken by servicing the Alarms and CountDown handlers.

* SampleSequence (a programmed CountDown example)
   - completely re-written to work with global ticker-based timeouts
   - no longer skips a second when cycling through multiple sessions (actually a fix to underlying CountDown code)
   - has option to enable/disable modal messages ("ask to continue")
   - displays event messages inline for better tracking of events during active sequence

Note: The tiddler contents have been updated, but the tiddler modified datetimes haven't changed (I had the timestamps off for testing purposes).  You should copy ALL tiddlers when updating.

enjoy,
-e

TW Tones

unread,
Aug 17, 2020, 10:32:27 PM8/17/20
to TiddlyWiki
Eric

An observation fyi but no expectation of remedy, my windows HTA version the clock in the sidebar does not tick.

Regards
Tony

Eric Shulman

unread,
Aug 17, 2020, 11:05:06 PM8/17/20
to TiddlyWiki
On Monday, August 17, 2020 at 7:32:27 PM UTC-7, TW Tones wrote:

An observation fyi but no expectation of remedy, my windows HTA version the clock in the sidebar does not tick.


Hmm... that's odd.  The first thing to do is to check to see if TiddlyTools/Timer/Ticker is actually running by opening $:/temp/timer/ticker.  The text of that tiddler should be a 17-digit datetime value that is being automatically updated once per second.  Note that the Ticker is tagged with $:/tags/StartupAction, which is supposed to be invoked when you load the file.  I wonder if the HTA somehow fails to trigger the StartupActions, which are run from $:/core/modules/startup.js

If the Ticker IS running, then the next thing to check is to see if the sidebar digital clock is running.  If it is, then the problem would be limited to just the analog clock display, and might be related to the CSS used to render the analog clock.  Perhaps the HTA isn't responding to dynamically changing updates to CSS?

Let me know what happens...

-e

Eric Shulman

unread,
Aug 18, 2020, 12:03:45 AM8/18/20
to TiddlyWiki
On Monday, August 17, 2020 at 8:05:06 PM UTC-7, Eric Shulman wrote:
On Monday, August 17, 2020 at 7:32:27 PM UTC-7, TW Tones wrote:

An observation fyi but no expectation of remedy, my windows HTA version the clock in the sidebar does not tick.


OK... I did a little testing myself.  Here's what I did:

1) Open timer.html in my usual browser, Chrome
2) Open empty.html from TiddlyWiki.com in a separate Chrome tab
3) Use drag-and-drop to import the following tiddlers into empty.html from timer.html
TiddlyTools/Timer/Ticker
TiddlyTools/Timer/action-timeout.js
TiddlyTools/Timer/Clocks
TiddlyTools/Timer/SidebarClocks
4) Save empty.html to a local file (default download saver)
5) From local filesystem, rename empty.html to empty.hta
6) Double click empty.hta to start it

What happens:
* The HTA opens as a stand-alone application window.
* The $:/temp/timer/ticker IS updating once per second.
* The Sidebar digital clock IS running.
* The Sidebar analog clock is NOT running.
* The display of the Analog clock has all three hands pointing straight down, and all the clock numbers are in the center, along with all the tick marks.

This suggests that the problem is due to a failure of the HTA to handle CSS "transforms" (which are used to set the position and angle of the hands, numbers, and tick marks)

-e


TW Tones

unread,
Aug 18, 2020, 3:15:15 AM8/18/20
to TiddlyWiki
Eric,

Thanks for doing that test. I will abandon the hta for this timer need. It was going to be my main implementation because it opens on boot of my computer. But the HTA depends on the IE hta component which I believe is deprecated.

Although if this is the only but it can do more,

Regards
Tony

Jon

unread,
Mar 9, 2021, 10:03:35 AM3/9/21
to TiddlyWiki
Hi Eric,

Whilst I can enter an alarm that repeats every day at http://tiddlytools.com/timer.html, it doesn't work in my wiki - I can set alarms once but the daily alarm doesn't retain the time for some reason. Any ideas?

Also, are alarms which have expired whilst the computer has been turned off supposed to trigger when switched back on as I can't reproduce that?

Regards
Jon

mohamed maghrabi

unread,
Apr 5, 2021, 10:58:29 AM4/5/21
to TiddlyWiki
is it possible to trigger , start or stop a timer automatically if a certain criteria is met?  so similar to a CRM ticketing tool, creating and saving a new tidler would automatically start a timer , or maybe creating a new tidler with a specific Tag would trigger a predefined duration ?

Eric Shulman

unread,
Apr 5, 2021, 11:54:50 AM4/5/21
to TiddlyWiki
On Tuesday, March 9, 2021 at 7:03:35 AM UTC-8 Jon wrote:
Whilst I can enter an alarm that repeats every day at http://tiddlytools.com/timer.html, it doesn't work in my wiki - I can set alarms once but the daily alarm doesn't retain the time for some reason. Any ideas?

When you set an alarm, it is stored in the "alarms" field of a tiddler and will be triggered when the specified date/time is reached, as long as the file remains loaded.  However, if you want that alarm to persist across sessions (i.e., when you reload the file after closing it or exiting the browser), then you must save the file so the tiddler with the "alarms" field is saved.
 
Also, are alarms which have expired whilst the computer has been turned off supposed to trigger when switched back on as I can't reproduce that?

No.  Alarms are only triggered while the file is open in the browser.  If the date/time for a "once" alarm has already passed (i.e., "expired"), the alarm will never trigger.  If the time for an "everyday" or specific day alarm has already passed, it will be triggered the next day, or on the specified day, but only if the file is currently open in the browser.  Note that "once" alarms are not automatically removed, even if the date/time has already passed.  This allows you to easily change the existing alarm to some future date or time, so that it will no longer be "expired", and will then trigger when that date/time is reached (assuming the file is opened in the browser, of course).

-e

Eric Shulman

unread,
Apr 5, 2021, 12:24:11 PM4/5/21
to TiddlyWiki
On Monday, April 5, 2021 at 7:58:29 AM UTC-7 mohamed.e...@vodafone.com wrote:
is it possible to trigger , start or stop a timer automatically if a certain criteria is met?  so similar to a CRM ticketing tool, creating and saving a new tiddler would automatically start a timer , or maybe creating a new tiddler with a specific Tag would trigger a predefined duration ?

Alarms are defined by creating a field named "alarms" in *any* tiddler.  The contents of the alarms field is a space-separated list, where each alarm has several parts delimited by semi-colons, like this: type;date;time;msg, where:

type is a keyword: "once", "daily", or a specific day (e.g., "Sunday", "Monday", etc.)
date is specified using YYYY-0MM-0DD format (e.g. "2021-04-05")
time is specified using 0hh:0mm:0ss format (e.g., "09:15:30")
msg is the text to display when the alarm is triggered.

Note that if the type is "daily" or a specific day, then the date part of the alarm definition is left blank but the semi-colon delimiters are still present, so there will be two adjacent semi-colons (see example below).  Also, if the msg text contains any spaces, then the entire alarm definition must be surrounded by doubled square brackets.  For example, the following "alarms" field content specifies four individual alarms:

[[Monday;;07:00:00;Time for another work week :(]] [[daily;;12:00:00;Lunch break]] [[Friday;;17:00:00;Weekend starts...  YAY!]] [[once;2021-01-01;00:00:00;Happy New Year!]]

For your specific use-case (i.e. adding an alarm for a given criteria), you would need to have a custom button that would create the desired tiddler and add the appropriate alarms field definition, using one or more $action-setfield widgets.  It might also be possible to do this whenever a tiddler is created via the standard "save tiddler" button from the tiddler editor, but this would require adding some JS code to catch the "th-saving-tiddler" hook (see https://tiddlywiki.com/dev/#Hook%3A%20th-saving-tiddler).

enjoy,
-e

paulgilbert2000

unread,
Apr 30, 2021, 11:14:37 PM4/30/21
to TiddlyWiki
Thanks Eric,

is it possible to pause the timer ? so would it be possible to do a drop down with different values that would stop the , resume the timer based on the value chosen ? this is what i am really after , pretty much similar to a ticketing tool

paulgilbert2000

unread,
May 13, 2021, 11:34:41 PM5/13/21
to TiddlyWiki
how can i add a value in a field automatically after an alarm is triggered, so asside from the popup message ,i also want a field to say "done" for example?

Eric Shulman

unread,
May 14, 2021, 1:17:03 AM5/14/21
to TiddlyWiki
On Thursday, May 13, 2021 at 8:34:41 PM UTC-7 Mohamed...@hotmail.com wrote:
how can i add a value in a field automatically after an alarm is triggered, so asside from the popup message ,i also want a field to say "done" for example?

I just added a new feature to the Alarms, so that you can invoke custom actions instead of displaying a message box.

To define custom actions to be performed when an alarm is triggered:
  • Create a tiddler containing one or more desired <$action-... /> widgets and enter the title of this tiddler as the message text for the alarm.
  • When the alarm is triggered, the <$action-... /> widgets contained in the specified tiddler will be invoked.
  • To display a message in addition to performing the specified actions, you can define a separate alarm with the desired message text.

enjoy,
-e

paulgilbert2000

unread,
May 14, 2021, 12:53:23 PM5/14/21
to TiddlyWiki
Thank you very much eric

it works perfectly fine :)

one more question , if i may, how would this work in a list situation , so if i am listing a group of tiddlers , i can assign different alarms to them, but when the action triggers for one alarm it affects all tiddlers , is this because how it is intended to be used , or am i using the code wrong

thanks again for your help
Capture10.PNG
It is loading more messages.
0 new messages