(New to the forum, and I only found one mostly-unrelated post mentioning any of this, but if it's already been discussed somewhere, just point me in the right direction.)
So I'm just now starting to work with Twine 2, and I was playing around with adding some UI elements on top of a Harlowe-format story. I ran into an issue with the scripting, and
@twinethreads sent me this direction for some discussion.
The issue I ran into is, if I want to have a custom event handler in the Story Javascript:
<br />function myEventHandler() {<br /> alert('custom handler called'); <br /> //actual work here<br />}<br />
...and then I want to call that from a passage:
<br /><input type="button" value="Testing" onclick="myEventHandler();"><br />
...the event handler isn't called (tested in latest Chrome and Firefox on Win7 x64). A little digging in Chrome's inspector shows that it doesn't think myEventHandler() is defined. A little more digging and I find that my Story Javascript in the Harlowe export is in an element like this:
<br /><script role="script" id="twine-user-script" type="text/twine-javascript"><br />
The "text/twine-javascript" seems to be the issue - if I change it to just "text/javascript" manually in the export, the custom event handler is called, but when I asked on Twitter,
@twinethreads said the different type value is required for proper script execution order.
So I guess what I'm wondering is if this is a known issue/complication, and if I wanted to attach a function in my Story Javascript to an event handler in a passage, is there another way I should be doing that?
Thanks in advance.
Comments
Your function is not visible (in scope) to the passage.
One way you can get around this problem is to use a Namespace to store your functions (which stops you from accidentally overriding an existing one) and then to add your Namespace to the global windows object.
(note: Use a name more meaningful than my Bob, it should be unique so check that the Namespace does not already exist) You can then use the fact that your namespace is now globally visible to solve your issue:
I'm looking at the source for Harlowe now, and if I'm following correctly, instead of the browser executing the script in place (because of the type attribute difference), the main() function looks for scripts and passes them to eval(), so none of it ends up in the global scope? If so, then yeah that makes sense -- anything meaningful I ended up writing for this probably would have ended up in a namespace anyway, but I got nervous when the quick test version didn't work.
Looks like I'm all set for now though, so thanks.
Twine 2 does this by marking the hidden Authors script tag with the text/twine-javascript type so it wont be executed, and Harlowe then locates that hidden script when its ready and merges it into the page using an eval().
In Twine 1 the creators of story formats had the ability to influence how the generated HTML file was assembled thus allowing them to place the Authors javascript at the end of the <head> tag if they wished.