Why are you not meant to define widgets in StoryInit?

+2 votes
asked Aug 12, 2017 by SleepyFox (220 points)

On the SugarCube v2 wiki, it says that when creating widgets, the passage should have a widget tag and that widgets should never be used in special passages. What is the reason for this? I've tested it and it seems to work fine.

WARNING: Widgets should always be defined within their own separate widget-tagged passage—any widgets that are not may be lost on page reload. Do not add a widget tag to any of the specially named passages and attempt to define your widgets there.

2 Answers

0 votes
answered Aug 14, 2017 by Akjosch (3,950 points)
selected Aug 21, 2017 by SleepyFox
Best answer

There is a certain order in which passages are being parsed and ran.

First, everything in the script and widget passages is being processed (and the stylesheet ones too, but those shouldn't contain any active code anyway). This ensures their contents are available before any actual game passage which might use them.

Then comes some special passages like StoryInterface and possibly StoryAuthor, StoryBanner, StorySubtitle and so on. Those define the UI elements and their contents and shouldn't do anything else.

Then, if and only if you start the game anew, comes StoryInit. If you're already mid-game and hit the browser's "reload" button, this passage isn't run and nothing you put in there will be used.

And then your starting passage is run, along with all the task object code and their corresponding special passages.

You want your widgets and macros to be defined as early as possible and you want them to be defined no matter what the player does with the game, so you should put them in the widget and script tagged passages.

That said ... if you need a macro (doesn't work with widget as well from what I saw) in just a single passage, you can also define it right there. Just make sure you do so before you use it.

    if(!Macro.has("myMacro")) {
        Macro.add("myMacro", { handler() {
            new Wikifier(this.output, "Some more code here.");
        } });


commented Aug 14, 2017 by TheMadExile (35,630 points)

That said ... if you need a macro (doesn't work with widget as well from what I saw) in just a single passage, you can also define it right there. Just make sure you do so before you use it.

It will work with a widget exactly as it does with a normal JavaScript macro—widget macros are internally constructed via the Macro API.  That said, you should never do that.  Always define your macros and widgets in the appropriate places.

The main problem with defining macros and/or widgets within normal passages is how the history and saves interact—which is a topic I've no intention of getting into here.  Save yourself a future headache and just don't do it.

0 votes
answered Aug 12, 2017 by greyelf (65,690 points)

The warning you quoted explains a reason you don't define widgets in specially named passages, because under certain conditions the macros they define may not be re-created if the page is reloaded.

Different special passage types are validated and stored differently, and the different special passage types are executed in a particular order with StoryInit being one of the last special passages to be executed.

But the main reason you don't define widgets within the StoryInit special passage is because the developer's documentation tells you not to, and you would think that the person designing the story format would know how best to do things. Just because something appears to be working correctly doesn't mean it is.

Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.