ANN: widget tutorial

204 views
Skip to first unread message

Brian Theado

unread,
Feb 3, 2019, 8:14:15 AM2/3/19
to tiddly...@googlegroups.com
I have a work in progress tutorial for writing TW widgets at https://btheado.github.io/tw-widget-tutorial/. It starts with the simplest widget I could think of and builds from there. I will be adding more over the coming days and weeks.

It uses the innerwiki plugin to provide an interactive playground for the javascript code. In fact I developed it all using a single file tiddlywiki. The immediate feedback provided by the innerwiki widget was most helpful.

Any feedback appreciated, especially if I've misrepresented anything.

Brian

Mohammad Rahmani

unread,
Feb 3, 2019, 10:41:25 AM2/3/19
to tiddly...@googlegroups.com
Many thanks Brian,
 I like the tutorial and I will return to you after some experimenting!

By the way for me it is also interesting to know how innerwiki itself works!

--Mohammad

TonyM

unread,
Feb 3, 2019, 6:09:36 PM2/3/19
to TiddlyWikiDev
Brian,

Great stuff, I am keen to complete the course because I feel that it my next step in the TiddlyWiki verse. 

Thanks for contributing to the community, this is a good place to do so

Tony

Brian Theado

unread,
Feb 3, 2019, 10:35:41 PM2/3/19
to tiddly...@googlegroups.com
Tony and Mohammad, thanks for the feedback.

I just added "Widget attributes tutorial part I".

So now these sections are written:

Undefined widget tutorial
Do nothing widget tutorial
Hello World widget tutorial
Widget refresh tutorial part I
Widget refresh tutorial part II
Widget refresh tutorial part III
Widget attributes tutorial part I

With these still left to write:

Widget attributes tutorial part II
3rd party library tutorial part I
3rd party library tutorial part II
Child widgets tutorial

Brian

stefano franchi

unread,
Feb 3, 2019, 11:14:36 PM2/3/19
to tiddly...@googlegroups.com
Brian,

great work and greatly needed. Can't wait to read the 3rd party library tutorial!

Cheers,
Stefano

--
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 https://groups.google.com/group/tiddlywikidev.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywikidev/CAO5X8CzUa3%3D50x2fFUW-EvMPzmUsDsrPW98ESLigEFp8zT8YmA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


--
__________________________________________________
Stefano Franchi

stefano...@gmail.com
http://stefano.cleinias.org

Jeremy Ruston

unread,
Feb 4, 2019, 2:39:56 AM2/4/19
to tiddly...@googlegroups.com
Congratulations, Brian, that's a terrific piece of work and beautifully fulfils our urgent need for better docs.

Would you consider contributing it to tiddlywiki.com/dev? The material there needs some love and attention but it would be good to keep things together.

Best wishes

Brian Theado

unread,
Feb 4, 2019, 11:48:04 AM2/4/19
to tiddly...@googlegroups.com
Thanks, Jeremy. I like the idea of contributing it to tiddlywiki.com/dev and I'll look into that after I write more of the content.

Joe Armstrong

unread,
Feb 5, 2019, 6:28:02 AM2/5/19
to tiddly...@googlegroups.com
Brilliant - thanks a lot -

I have a tiny request.

After downloading your TW which I've saved for future reference I have to keep
a separate note of where I got it from. It would be very nice if this information
were stored in TW itself

there is an author and url fields in the advanced tab of the Info tab of
the control panel.

What I'd like to know are:

Author : your name
URL: A url where I can get the latest version
Licence: (You choose)
Email : (contact info)

These would allow me to contact you privately and correctly credit your work
if it used in a derivative work (if you licence it to be reused)

Cheers

/Joe


--
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 https://groups.google.com/group/tiddlywikidev.

Jeremy Ruston

unread,
Feb 5, 2019, 10:05:57 AM2/5/19
to TiddlyWikiDev
Hi Joe

Brilliant - thanks a lot -

I have a tiny request.

After downloading your TW which I've saved for future reference I have to keep
a separate note of where I got it from. It would be very nice if this information
were stored in TW itself

One tip that can be useful: on macOS and recent versions of Windows the original URL of a download is tracked in extended file attributes; you can see it by selecting the file and choosing “Show Info” or “Properties". Obviously that information is stripped by many processes (git, most file sync solutions, etc.) but it can still be useful when you’re trying to figure out where yet another “index (362).html” came from...

there is an author and url fields in the advanced tab of the Info tab of
the control panel.

What I'd like to know are:

Author : your name
URL: A url where I can get the latest version
Licence: (You choose)
Email : (contact info)

These would allow me to contact you privately and correctly credit your work
if it used in a derivative work (if you licence it to be reused)

There’s a TW5 ticket about establishing conventions for license information:


Best wishes

Jeremy


Cheers

/Joe


On Sun, Feb 3, 2019 at 2:14 PM Brian Theado <brian....@gmail.com> wrote:
I have a work in progress tutorial for writing TW widgets at https://btheado.github.io/tw-widget-tutorial/. It starts with the simplest widget I could think of and builds from there. I will be adding more over the coming days and weeks.

It uses the innerwiki plugin to provide an interactive playground for the javascript code. In fact I developed it all using a single file tiddlywiki. The immediate feedback provided by the innerwiki widget was most helpful.

Any feedback appreciated, especially if I've misrepresented anything.

Brian

--
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 https://groups.google.com/group/tiddlywikidev.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywikidev/CAO5X8CwX0iYK6f7SCxJRHT9dxJkyHWrOOU0sr8Yve%3D%2BarLLBDg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

--
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 https://groups.google.com/group/tiddlywikidev.

Brian Theado

unread,
Feb 17, 2019, 9:22:14 AM2/17/19
to tiddly...@googlegroups.com
I have been making slow progress with this.

I wrote additional sections:
Widget attributes tutorial part II
3rd party library tutorial part I
3rd party library tutorial part II

I also improved some of the examples of the previous sections.

I still haven't written about child widgets. I also haven't covered the difficult topic of how to get the 3rd party library code suitable for loading into Tiddlywiki. I plan to add a few examples from my experience, but it won't be comprehensive as it is a large topic.
 

Stefano,

> great work and greatly needed. Can't wait to read the 3rd party library tutorial! 

I would guess based on your other threads that you are already past the point where the 3rd party library tutorials would help you. Also based on those threads, I doubt what I've written so far would have helped you much. One difficulty you faced was how to get 3rd party code suitable for loading and I haven't written anything on that yet. Another difficulty was related to arranging files on the file system such that node.js would pick them up as plugins. This topic I don't plan to cover at all as I see that topic being orthogonal to writing widget code.

Brian

stefano franchi

unread,
Feb 17, 2019, 10:25:48 AM2/17/19
to TiddlyWikiDev
On Sun, Feb 17, 2019 at 8:22 AM Brian Theado <brian....@gmail.com> wrote:
I have been making slow progress with this.

I wrote additional sections:
Widget attributes tutorial part II
3rd party library tutorial part I
3rd party library tutorial part II

I also improved some of the examples of the previous sections.

I still haven't written about child widgets. I also haven't covered the difficult topic of how to get the 3rd party library code suitable for loading into Tiddlywiki. I plan to add a few examples from my experience, but it won't be comprehensive as it is a large topic.
 

Stefano,

> great work and greatly needed. Can't wait to read the 3rd party library tutorial! 

I would guess based on your other threads that you are already past the point where the 3rd party library tutorials would help you. Also based on those threads, I doubt what I've written so far would have helped you much. One difficulty you faced was how to get 3rd party code suitable for loading and I haven't written anything on that yet. Another difficulty was related to arranging files on the file system such that node.js would pick them up as plugins. This topic I don't plan to cover at all as I see that topic being orthogonal to writing widget code.



Hi Brian,

thanks for the tutorials, I have already learned a few things from them I didn't know before. You are right that I am almost done with my external library widget plugin, and I am working on a write-up of the process that led me there, but that does not make less of a newbie to this fascinating TW world.

In particular, there is an issue I have not been able to solve yet, and I hope you may help---where do I look to find examples of a callback function that would allow the calling code to tell the external library  to save its data?
I think in a previous exchange you suggested to take a look at the Codemirror plugin, but I could not find where the mechanism is implemented. I guess it is because I am not really sure what I am looking for. Your tutorial on the refresh mechanism does a great job of explaining how a widget manages to keep itself in sync with the underlying tiddler. It is the reverse procedure that is still baffling to me. In particular, is complete sync the only option---sending back a call from the widget back to the tiddler after every single update? That may not be feasible in case the external library works on on  its own internal representation of the underlying tiddler data and it may be expensive to convert back and forth (as it is in my case). I am thinking a simpler "updateTiddlerOnExit" method to call before the widget is destroyed would be more appropriate, but I haven't found out how to manage this kind of tiddler-->widget communication.


Cheers,

Stefano

 

Brian Theado

unread,
Feb 17, 2019, 2:25:36 PM2/17/19
to tiddly...@googlegroups.com


On Sun, Feb 17, 2019 at 10:25 AM stefano franchi <stefano...@gmail.com> wrote:
[...] 
In particular, there is an issue I have not been able to solve yet, and I hope you may help---where do I look to find examples of a callback function that would allow the calling code to tell the external library  to save its data? 

This is backwards from the way I've implemented it and seen it implemented in other widgets. I think the expectation is that the external library provides a way to register a callback will will be called by the library every time anything changes. The widget can register a callback in which the code will ask the library to serialize its data. The resulting data is saved to some tiddler field in order to persist. In this way, the data is always in sync with the tiddler field. The widget does not get notified it is about to be destroyed (that I know of), so having the data always in sync is required.

I think in a previous exchange you suggested to take a look at the Codemirror plugin, but I could not find where the mechanism is implemented. I guess it is because I am not really sure what I am looking for.


// Set up a change event handler
this.cm.on("change",function() {
        self.widget.saveChanges(self.getText());
});

[...]

/*
Get the text of the engine
*/
CodeMirrorEngine.prototype.getText = function() {
return this.cm.getValue();
};

Here's an example I wrote, but it is much more complicated WRT the persisting of data: https://github.com/btheado/tweve/blob/master/src/plugins/btheado/tweve/files/eve-widget.js#L61

Here's another one I wrote, but not well commented and probably not a good example to follow: https://github.com/btheado/jsoneditor/blob/master/jsoneditor-widget.js#L60

 
Your tutorial on the refresh mechanism does a great job of explaining how a widget manages to keep itself in sync with the underlying tiddler. It is the reverse procedure that is still baffling to me. In particular, is complete sync the only option---sending back a call from the widget back to the tiddler after every single update? That may not be feasible in case the external library works on on  its own internal representation of the underlying tiddler data and it may be expensive to convert back and forth (as it is in my case). I am thinking a simpler "updateTiddlerOnExit" method to call before the widget is destroyed would be more appropriate, but I haven't found out how to manage this kind of tiddler-->widget communication.

See this related discussion, I don't think TW currently supports what you are after: https://github.com/Jermolene/TiddlyWiki5/issues/1784

So in your case you are saying the conversion back and forth is too expensive to always keep in sync? Have you already tried it and found it to be too slow?

Brian

stefano franchi

unread,
Feb 17, 2019, 4:29:58 PM2/17/19
to TiddlyWikiDev
On Sun, Feb 17, 2019 at 1:25 PM Brian Theado <brian....@gmail.com> wrote:


On Sun, Feb 17, 2019 at 10:25 AM stefano franchi <stefano...@gmail.com> wrote:
[...] 
In particular, there is an issue I have not been able to solve yet, and I hope you may help---where do I look to find examples of a callback function that would allow the calling code to tell the external library  to save its data? 

This is backwards from the way I've implemented it and seen it implemented in other widgets. I think the expectation is that the external library provides a way to register a callback will will be called by the library every time anything changes. The widget can register a callback in which the code will ask the library to serialize its data. The resulting data is saved to some tiddler field in order to persist. In this way, the data is always in sync with the tiddler field. The widget does not get notified it is about to be destroyed (that I know of), so having the data always in sync is required.

I think in a previous exchange you suggested to take a look at the Codemirror plugin, but I could not find where the mechanism is implemented. I guess it is because I am not really sure what I am looking for.



// Set up a change event handler
this.cm.on("change",function() {
        self.widget.saveChanges(self.getText());
});

[...]

/*
Get the text of the engine
*/
CodeMirrorEngine.prototype.getText = function() {
return this.cm.getValue();
};

Here's an example I wrote, but it is much more complicated WRT the persisting of data: https://github.com/btheado/tweve/blob/master/src/plugins/btheado/tweve/files/eve-widget.js#L61

Here's another one I wrote, but not well commented and probably not a good example to follow: https://github.com/btheado/jsoneditor/blob/master/jsoneditor-widget.js#L60


Hi Brian,

thanks for the pointers---all very useful. I had indeed missed that bit of the codemirror code, which makes perfect sense now that I see it.

 
Your tutorial on the refresh mechanism does a great job of explaining how a widget manages to keep itself in sync with the underlying tiddler. It is the reverse procedure that is still baffling to me. In particular, is complete sync the only option---sending back a call from the widget back to the tiddler after every single update? That may not be feasible in case the external library works on on  its own internal representation of the underlying tiddler data and it may be expensive to convert back and forth (as it is in my case). I am thinking a simpler "updateTiddlerOnExit" method to call before the widget is destroyed would be more appropriate, but I haven't found out how to manage this kind of tiddler-->widget communication.

See this related discussion, I don't think TW currently supports what you are after: https://github.com/Jermolene/TiddlyWiki5/issues/1784


I see, thanks for saving me hours of digging! That's exactly what I was after. Too bad it's not supported yet.

So in your case you are saying the conversion back and forth is too expensive to always keep in sync? Have you already tried it and found it to be too slow?

I did and it is borderline. I will keep looking for solutions. But thanks a lot for the help!

Cheers,

S.

TonyM

unread,
Feb 17, 2019, 7:56:34 PM2/17/19
to TiddlyWikiDev
Brian,

In this thread, Bimlas may get to follow up on a solution to use IntenceDebate as a comment plugin. I thought I would mention it because it may be one of the simpler examples of integrating because its primary model is inclusion of javascript but no libraries. It may be a good example for others to follow your instructions and integrate other solutions out there of this simpler nature.

Regards
Tony

Brian Theado

unread,
Feb 22, 2019, 6:28:07 PM2/22/19
to tiddly...@googlegroups.com
More progress. I wrote the child widget tutorial with lots of parse tree and widget tree examples.  See https://btheado.github.io/tw-widget-tutorial/#Child%20widgets%20tutorial. Best viewed with a wider screen and with the sidebar hidden.
Reply all
Reply to author
Forward
0 new messages