Re: [tw] TW5 Clock

260 views
Skip to first unread message

andrew harrison

unread,
Dec 13, 2013, 11:32:57 PM12/13/13
to tiddly...@googlegroups.com
So my use case is that I want the top menu and the first button in the top left corner I want it to be with a clock that when I click it stamps the time in a form that I have in a tiddler. I found the following but I wouldn't know how to put it in a button that would be interactive with the form in the tiddler I have open.

<!DOCTYPE html>
<html>
<body>

<p>A script on this page starts this clock:</p>
<p id="demo"></p>

<script>
var myVar=setInterval(function(){myTimer()},1000);

function myTimer()
{
var d=new Date();
var t=d.toLocaleTimeString();
document.getElementById("demo").innerHTML=t;
}
</script>

</body>
</html>

Previously when I had TWC there I had modified Eric Shulman's DigitalClock from Tiddlytools.com and it has worked wonderfully for a couple years now. But now that I am upgrading to TW5, it seems that everything is different. I still wouldn't know where to begin with trying to write a widget?


On Thu, Dec 5, 2013 at 7:03 AM, PMario <pmar...@gmail.com> wrote:
On Thursday, December 5, 2013 2:42:56 PM UTC+1, infernoape wrote:
Well, I found setTimeout(), setInterval(), clearTimeout(), and clearInterval() which are supported by node.js but I'm trying to access the computer's internal clock using what? It's just javascript? I'm confused as to what language to use to program a widget in TW5? Does it matter if I'm using TW5 stand alone edition or if it is shared via an actual node.js install?

Imo it also depends on your usecase. eg:

If you just want to show the actual time somewhere, the iframe solution jeremy suggested, imo would be the best solution.
If you want to click the watch and record some start / stop timestamps to eg: track working hours, imo it would be the best idea to just get the actual time / date if you click a "start" or "stop" button .....

So if you can describe your usecase a bit closer, we may be able to point you in the right direction, that fits your usecase, instead of guessing your usecase.

-mario


SpiderX

unread,
Dec 16, 2013, 1:18:52 PM12/16/13
to tiddly...@googlegroups.com
I've always done that with this bit of markup...
{ts}

Entering that in a tiddler always seems to place a timestamp of when the tiddler was saved. I don't know if it was a standard feature of Tiddlywiki or if it was an extension that was popular, but it's always seemed to work for me.

andrew harrison

unread,
Jan 7, 2014, 1:01:45 AM1/7/14
to tiddly...@googlegroups.com
I am still trying to make my first widget, which is still a clock button for my top menu. So here is what I have so far. I put the following in a tiddler with title: $:/core/modules/widgets/clock.js, Type: application/javascript and added a filed module-type: widget. In another tiddler I put <$clock> but all still get Undefined widget 'clock'. What am I missing?

/*\
title: $:/core/modules/widgets/clock.js
type: application/javascript
module-type: widget

A widget to display a clock

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var Widget = require("$:/core/modules/widgets/clock.js").widget;

var ClockWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};

/*
Inherit from the base widget class
*/
ClockWidget.prototype = new Widget();

/*
Render this widget into the DOM
*/
ClockWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
var domNode = this.document.createElement('p');
domNode.setAttribute("id","tw-clockbutton");
parent.insertBefore(domNode,nextSibling);
this.renderChildren(domNode,null);
this.domNodes.push(domNode);
};

/*
Compute the internal state of the widget
*/
ClockWidget.prototype.execute = function() {
var myVar=setInterval(function(){myTimer()},1000);
};

ClockWidget.prototype.myTimer = function() {
var d=new Date();
var t=d.toLocaleTimeString();
document.getElementById("tw-clockbutton").innerHTML=t;
};

/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ClockWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes(),
hasChangedAttributes = $tw.utils.count(changedAttributes) > 0;
if(hasChangedAttributes) {
// Update our attributes
this.assignAttributes(this.domNodes[0]);
}
return this.refreshChildren(changedTiddlers) || hasChangedAttributes;
};

exports.clock = ClockWidget;

})();

Stephan Hradek

unread,
Jan 7, 2014, 1:48:04 AM1/7/14
to tiddly...@googlegroups.com


Am Dienstag, 7. Januar 2014 07:01:45 UTC+1 schrieb infernoape:
I am still trying to make my first widget, which is still a clock button for my top menu. So here is what I have so far. I put the following in a tiddler with title: $:/core/modules/widgets/clock.js, Type: application/javascript and added a filed module-type: widget. In another tiddler I put <$clock> but all still get Undefined widget 'clock'. What am I missing?

I did not check your code, but:
  1. Did you save and reload? Widgetcode can only be activated when the wiki is loaded.
  2. Additionally you need to put  <$clock/> or <$clock></$clock>

Jeremy Ruston

unread,
Jan 7, 2014, 8:37:41 AM1/7/14
to TiddlyWikiDev
Hi Andrew

At least one problem is the line:

var Widget = require("$:/core/modules/widgets/clock.js").widget;

It should be:

var Widget = require("$:/core/modules/widgets/widget.js").widget;

There is also a deeper problem with the way that you're updating the DOM. In TW5 the DOM is only updated in response to changes in the state of tiddlers in the store that trigger a refresh cycle. Using DOM IDs in the way that you've done would fail if there were multiple instances of the widget on screen at once, for instance.

An alternative way of thinking about your requirements might be to implement a plugin containing a browser-startup module that sets up a timer to update a system tiddler $:/CurrentTime with the current time every second. You can then transclude that tiddler whereever you need to display the current time.

Best wishes

Jeremy





--
You received this message because you are subscribed to the Google Groups "TiddlyWikiDev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywikide...@googlegroups.com.
To post to this group, send email to tiddly...@googlegroups.com.
Visit this group at http://groups.google.com/group/tiddlywikidev.
For more options, visit https://groups.google.com/groups/opt_out.



--
Jeremy Ruston
mailto:jeremy...@gmail.com

andrew harrison

unread,
Jan 7, 2014, 4:11:39 PM1/7/14
to tiddly...@googlegroups.com
With enthusiastic jumping up and down screaming I did it, I got the clock to work. Well, sort of. Using <$clock/> in a tiddler but I'm hacking here and I know I'm doing it wrong. It works until I try to open the tiddler that I put the <$clock/> into and then it throws an error: Unable to set property 'innerHTML' of undefined or null reference. Sitting here with that sinking feeling. Which I guess would make sense because if you take the clock out of production, then the widget isn't able to set the property because it isn't there anymore. I have no Idea how to gracefully get it to stop if I want to edit it. Anyone?

/*\
title: $:/core/modules/widgets/clock.js
type: application/javascript
module-type: widget

A widget to display a clock

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var Widget = require("$:/core/modules/widgets/widget.js").widget;

var ClockWidget = function(parseTreeNode,options) {
	this.initialise(parseTreeNode,options);
};

/*
Inherit from the base widget class
*/
ClockWidget.prototype = new Widget();

/*
Render this widget into the DOM
*/
ClockWidget.prototype.render = function(parent,nextSibling) {
	this.parentDomNode = parent;
	this.computeAttributes();
	this.execute();
	var domNode = this.document.createElement('p');
	domNode.setAttribute("id","tw-clockbutton");
	parent.insertBefore(domNode,nextSibling);
	this.renderChildren(domNode,null);
	this.domNodes.push(domNode);
};

/*
Compute the internal state of the widget
*/
ClockWidget.prototype.execute = function() {
	var myVar=setInterval(function(){
	var d=new Date();
	var t=d.toLocaleTimeString();
	document.getElementById("tw-clockbutton").innerHTML=t;
},1000);
};

/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
ClockWidget.prototype.refresh = function(changedTiddlers) {
	var changedAttributes = this.computeAttributes(),
		hasChangedAttributes = $tw.utils.count(changedAttributes) > 0;
	if(hasChangedAttributes) {
		// Update our attributes
		this.assignAttributes(this.domNodes[0]);
	}
	return this.refreshChildren(changedTiddlers) || hasChangedAttributes;
};

exports.clock = ClockWidget;

})();

andrew harrison

unread,
Jan 7, 2014, 4:43:04 PM1/7/14
to tiddly...@googlegroups.com
It turns out that as long as I have one instance of it running, it doesn't error. Unfortunately it will only update one instance of itself. So when I have 2 of them, only one works which is alright for my use case. And since I am only sticking it in my top menu all I have left to do is figure out how to style it. Which so far, I am at a loss because no matter what I try, I can't seem to change the font for some reason.

Stephan Hradek

unread,
Jan 7, 2014, 5:35:05 PM1/7/14
to tiddly...@googlegroups.com
I think it could be quite helpful, would you put yor stuff on tiddlyspot or somewhere else where we can view it.

andrew harrison

unread,
Jan 8, 2014, 7:40:23 AM1/8/14
to tiddly...@googlegroups.com
That is my plan, it just takes time. I do have a tiddlyspace that I can put it on. It might take me a few days. I will let you know.


On Tue, Jan 7, 2014 at 3:35 PM, Stephan Hradek <stephan...@gmail.com> wrote:
I think it could be quite helpful, would you put yor stuff on tiddlyspot or somewhere else where we can view it.

--

Andrew

unread,
Feb 19, 2015, 8:36:56 AM2/19/15
to tiddly...@googlegroups.com
I know it has been over a year but after alot of learning and reading all messages again, I discovered one of jeremy's responses about my clock and I thought I would try to tackle it again. When I put startup module-type in and save and reload, well, obviouly I don't know how to program. Anyone interested in helping? http://t5a.tiddlyspot.com/#%24%3A%2FModules%2FStartup%2FClock.js Just trying to follow jeremy's suggestion of a system tiddler that automatically updates with the time.

Jeremy Ruston

unread,
Feb 19, 2015, 1:09:10 PM2/19/15
to TiddlyWikiDev
Hi Andrew

The main problem is JavaScript's peculiar habit of overwriting 'this' within nested functions. Try this:

exports.startup = function () {
    // Install the clock mechanism
    this.actionTiddler = "$:/temp/clock";
    var self=this, timer=setInterval(function(){
    var d=new Date();
    var t=d.toLocaleTimeString();
    self.actionValue = t;
    self.wiki.setText(this.actionTiddler,text,null,this.actionValue);},250);
};

You also need to give your module a "module-type" field with the value "startup".

Best wishes

Jeremy






On Thu, Feb 19, 2015 at 1:36 PM, Andrew <andrew.j....@gmail.com> wrote:
I know it has been over a year but after alot of learning and reading all messages again, I discovered one of jeremy's responses about my clock and I thought I would try to tackle it again. When I put startup module-type in and save and reload, well, obviouly I don't know how to program. Anyone interested in helping? http://t5a.tiddlyspot.com/#%24%3A%2FModules%2FStartup%2FClock.js Just trying to follow jeremy's suggestion of a system tiddler that automatically updates with the time.
--
You received this message because you are subscribed to the Google Groups "TiddlyWikiDev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywikide...@googlegroups.com.
To post to this group, send email to tiddly...@googlegroups.com.
Visit this group at http://groups.google.com/group/tiddlywikidev.
For more options, visit https://groups.google.com/d/optout.

Andrew

unread,
Feb 19, 2015, 2:21:53 PM2/19/15
to tiddly...@googlegroups.com
Thank you for looking at this. Well, I tried it and now I have a setText error message. I'm wondering if I'm trying to do something before a function is defined? I can't run developer tools from my phone. Do I have to pass "text" and "null" as params? I thought that setText didn't need them.

Jeremy Ruston

unread,
Feb 20, 2015, 11:57:24 AM2/20/15
to TiddlyWikiDev
Hi Andrew

> Thank you for looking at this. Well, I tried it and now I have a setText error message. I'm wondering if I'm trying to do something before a function is defined? I can't run developer tools from my phone. Do I have to pass "text" and "null" as params? I thought that setText didn't need them.

Wow, I would never have guessed that you'd be doing this on a phone, that's pretty impressive. I fear it may also be impractical to do JS development without being able to see the error messages.

Anyhow, wiki.setText is defined like this:

exports.setText = function(title,field,index,value) {

So, when you call it, you basically need to specify all those parameters (you can omit unused ones at the end of the list, but in this case you want to pass a value for the parameter "value", which is at the end of the list).

What does the error message say?

Best wishes

Jeremy





On Thu, Feb 19, 2015 at 7:21 PM, Andrew <andrew.j....@gmail.com> wrote:
Thank you for looking at this. Well, I tried it and now I have a setText error message. I'm wondering if I'm trying to do something before a function is defined? I can't run developer tools from my phone. Do I have to pass "text" and "null" as params? I thought that setText didn't need them.
--
You received this message because you are subscribed to the Google Groups "TiddlyWikiDev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywikide...@googlegroups.com.
To post to this group, send email to tiddly...@googlegroups.com.
Visit this group at http://groups.google.com/group/tiddlywikidev.
For more options, visit https://groups.google.com/d/optout.

Andrew

unread,
Feb 22, 2015, 2:16:01 AM2/22/15
to tiddly...@googlegroups.com, jeremy...@gmail.com
ok, so I get Uncaught TypeError: Cannot read property 'setText' of undefined

andrew harrison

unread,
Feb 22, 2015, 2:44:35 AM2/22/15
to tiddly...@googlegroups.com
I got something to work. Here I tried using instead:
exports.startup = function() {
    var timer=setInterval(function(){
    var d=new Date();
    var t=d.toLocaleTimeString();
    $tw.wiki.addTiddler(new $tw.Tiddler({title: "$:/temp/clock", text: t}));
},250);
};

--
You received this message because you are subscribed to a topic in the Google Groups "TiddlyWikiDev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/tiddlywikidev/qwyXraJ6bkI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to tiddlywikide...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages