JavaScript supports a number of techniques for bundling related functions / methods together, some of which are directly supported by Twine & the SugarCube story format.
SugarCube’s uses its own Private Scoped contexts to execute its JavaScript based runtime engine and any JavaScript that is included within the Story HTML file. One Private Scoped context can not access the contents of another such context, however those created by SugarCube itself can access the internals of the runtime engine, which is how you’re able to use the methods you’re defining on the special setup
variable.
A Private Scoped context can also access things outside its own scope if that thing has been defined in a “global” like way. Three of the main techniques used to define something in a “global” like way are:
1: Defining that thing directly on the web-browser’s own window interface.
This is how some third-party JavaScript libraries make their Methods / Classes / Modules available. However, window
is also where the web-browser developers define methods & the like, so there could be potential issues if you override something they define or they override something you defined.
window.doit = function (){
/* code here */
};
Things defined this way can be called directly from code being run by SugarCube…
/* From a Passage */
<<run doit()>>
/* From a SugarCube Event handler */
$(document).one(':passagedisplay', function (ev) {
doit();
});
2: Defining that thing on a Namespace, that is defined on the window
interface.
The name of the Namespace should unique to your project, so it doesn’t conflict with any being used by a third-party library you might want to include.
/* an example using my own personal Namespace */
window.GE = window.GE || {};
GE.doit = function (){
/* code here */
};
Things defined this way are called similar to how things defined on setup
are…
/* From a Passage */
<<run GE.doit()>>
/* From a SugarCube Event handler */
$(document).one(':passagedisplay', function (ev) {
GE.doit();
});
3: Defining things in a JavaScript Class, that is defined on the window
interface.
Again the name being used needs to be something that isn’t likely to be taken by the web-browser itself or by any third-party library you intend to use.
If you intend to use JavaScript classes then you should read the Non-generic object types (classes) guide in the SugarCube documentation, especially if you intend to store instances of those classes in Story variables.