Hello, dear friends of the tiddlywiki community.
I’m a beginner and need to listen for some events while developing a plugin, such as tm-new-tiddler. However, I’ve found that neither $tw.wiki.addEventListener nor $tw.rootWidget.addEventListener is working. Why is this? What’s the difference between them? My code is as follows:
/*\
title: EventDemo
type: application/javascript
module-type: startup
\*/
exports.name = 'event-demo';
exports.platforms = ['browser'];
exports.after = ['startup'];
exports.synchronous = true;
exports.startup = () => {
$tw.utils.log("the startup is running."); // log success.
$tw.wiki.addEventListener("tm-new-tiddler", () => $tw.utils.log("the wiki listener is running.")); // not log even though creating new tiddler.
$tw.rootWidget.addEventListener("tm-new-tiddler", () => $tw.utils.log("the rootWidget listener is running.")); // not log even though creating new tiddler.
};
BTW, how can we systematically learn plugin development? The official developer website seems to lack systematic guidance; it doesn’t even have a complete API reference manual. I’m currently relying mainly on reading the plugin source code to learn.
The central structure is the widget (or rendered) tree, which is compiled wikitext, with $tw.rootWidget as the root. messages are passed up the widget tree from children to parent until a widget consumes them. tm-new-tiddler is consumed by the navigator widget.
IMO you should be a bit more specific about what you want to achieve in prose text, instead of presenting some code. As you wrote, the code does not work.
If we can understand, what you try to achieve, we can tell you how it could be done with TW. There are several possibilities to “catch” events.
How do you intend to trigger the tm-* message. Do you want to trigger a TW message, or do you intend to created your own message, that you want to catch.
As buggyj pointed out many TW functions already have hooks, that can be used by developers, to modify the core behaviour.
The hook mechanism has solved my problem perfectly.
However, returning to the original question: since the hook mechanism acts as a form of event listener, what is the purpose of $tw.rootWidget.addEventListener (whereas $tw.wiki.addEventListener operates at the data layer and does not conflict with the hook mechanism)? After examining some of the source code, I noticed an interesting phenomenon: many third-party plugins use $tw.rootWidget.addEventListener to listen for their custom messages, but it seems nobody uses it to listen for Core Messages.
However, if certain messages do not have a hook and are consumed by the navigator widget, such as tm-close-all-tiddlers, how can we listen for them manually?
The point is, that hooks are only implemented if there is a strong demand for a TW plugin or for a 3rd party plugin, where the author can proof that, it absolutely is necessary.
We are pretty certain, that the existing hooks are used “in the wild”. Otherwise we would have a lot of hooks that are never used, but we still need to make sure that they are maintained.
Hooks are for JavaScript developers. So they are only usable by a fraction of a fraction of our user-base.
So it would be much better to allow users to react on certain states of the UI with wikitext, which covers 100% of our user-base.
There are only 2 places in the TW UI that emit tm-close-all-tiddlers
Both of them are short, in terms of lines of code (loc). So it will be much easier to modify them, if you really have to.
If you create a new custom button, you already have control of the flow. So no core help needed.
For some users it may be confusing if they do not see anything after they closed all tiddlers. There are 2 options to show something if the story-river is empty.
With content: {{HelloThere||$:/core/ui/ViewTemplate}}
And you are done. Instead of HelloThere you can use a Dashboard or a giant Home-Button … Whatever you want. The advantage is no JS needed - 100% user base covered.
Add 2)
Background action is a core function that evaluate a filter, that allows users to react on certain wiki states. eg: Story river is empty.
The story river is sensitive to changes of the list-field in the $:/StroyList tiddler. If the list-field is empty, the action may do something.