Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

How to use: "Edit Story JavaScript" menu selection [Snowman]

edited December 2014 in Help! with 2.0
I can't figure out how to get code put into the Edit Story JavaScript text box to do anything. Can anyone provide something simple I can paste into there to get me started on the right track? For example maybe some code to print('tick') when passages are rendered? I've been mostly using Snowman, so I've been trying to make a showpassage:after event handler, but I haven't had any luck.

[Edit: Appended [Snowman] to the thread title to avoid confusion.]

Comments

  • An event listener for Showman should look something like the following:

    $(document).on("showpassage:after", function(e){
    console.log("passage shown: event: " + e);
    });
    Snowman does not seem to use the "Edit Story Javascript" special passage, so instead you can place the above code at the start of the first passage of your story like so:

    <script type="text/javascript">
    $(document).on("showpassage:after", function(e){
    console.log("passage shown: event: " + e);
    });
    </script>

    This is the first passage of the story.
    To test the above, open the Developer Console of your browser, refresh the page and you should see the message in the console.
  • I just tried this out and it's exactly what I needed. I was worried that every time the start passage was revisited it would keep adding additional duplicate event listeners, but it's always just the one. Thanks for the help!
  • One side effect of this code not being in the "Story JavaScript" but instead in the start passage is that the event listener doesn't subscribe until the start passage is first rendered, so you'll miss most  of the start passage's initial event triggers (example: hidepassage and showpassage); The start passage's first showpassage:after can still be caught though.
  • Here's my current kludgy attempt at a Snowman turn counter.

    _startPassage (this passage is flagged as the start passage for variable initialization):
    <% s.turnCounter = 0; %>

    <%= story.passage('StoryStart').render() %>
    _turnEvents (a passage to be triggered at the start of all regular passages):
    <% s.turnCounter = s.turnCounter + 1; console.log(s.turnCounter); %>
    StoryStart:
    <%= story.passage('_turnEvents').render() %>

    <% story.checkpoint(); %>

    The actual story begins here.
    This seems to work, but there's the tedious aspect of pasting the line of code to render() the _turnEvents into the start of every story passage textbox. I first tried implementing it in a "showpassage" event listener defined in _startPassage, but it had the problem of seemingly adding duplicate listeners if the browser back arrowed to the _startPassage.


    [EDIT: On second thought it's probably not a bad thing to specifically mark (with a line of code) which passages I want to trigger the _turnEvents in. For example, I wouldn't want to have it triggered in passages that only exist to be embedded and rendered inside other passages. So perhaps the code above is actually a decent solution for now. ]
  • I think I came up with a couple ways of subscribing to events without having to worry about the end user back arrowing to the passage with the code and then getting duplicate event handlers.

    One possibility is to replace the passage source after it's rendered once.  Here's _startPassage again with that change (it's the last line):
    <%
    $(document).on("showpassage:after", function(e){
    story.passage('_turnEvents').render();
    });
    %>

    <% s.turnCounter = 0; %>

    <%= story.passage('_introPage').render() %>

    <% story.passage('_startPassage').source = "\<% s.turnCounter = 0 %\>\<%= story.passage('_introPage').render() %\>" %>
    Another option is to replace _startPassage's id in the first element of the window.history array with the passage id you actually want to be the start of the story:
    <%
    $(document).on("showpassage:after", function(e){
    story.passage('_turnEvents').render();
    });
    %>

    <% s.turnCounter = 0; %>

    <%
    story.startPassage = story.passage('_introPage').id;
    story.history[0] = story.passage('_introPage').id;
    window.history.replaceState({ state: story.state, history: story.history, checkpointName: story.checkpointName }, '', '');
    %>

    <%= story.passage('_introPage').render() %>
    Also here's an example of the _turnEvents passage where it counts turns on passages you've tagged (in the editor) with "count-turn".

    _turnEvents:
    <%
    var tags = $(story.el[0]).find('tw-passagedata[name=\"' + window.passage.name + '\"]').attr('tags');

    if(tags.match('count-turn'))
    {
    s.turnCounter = s.turnCounter + 1;
    }
    %>
  • Jess wrote:

    I think I came up with a couple ways of subscribing to events without having to worry about the end user back arrowing to the passage with the code and then getting duplicate event handlers.

    Another simple solution is to edit the generated HTML file and add your own <script> tag at the end of the <body> tag.
  • I tried your event listener in Harlowe, copied it into my first passage, but it didn't output anything to the console. I also tried to write simple stuff like alert("lorem ipsum") and that didn't work either. Is there something I'm doing wrong?
  • The internal event systems of the Snowman 2 and Harlowe story formats are totally different.

    Snowman 2 uses jQuery's $.event.trigger() feature to generate custom events that the Author is able to listen for. Some of the events available are: hidepassage; showpassage; showpassage:after; checkpoint; save; restore; restorefailed; restore:after

    The closest thing to an event system in Harlowe I personally was able to find was the newEnchantmentMacroFns function, but I don't know how Leon (the creator if Harlowe) wants the Author to use this feature so I suggest asking him.
  • If anyone wants to enable the "Edit Story Javascript" entry being processed in Snowman, a minor edit to the format file seems to do the trick.

    Browse to /Twine 2.0/storyformats/Snowman/ and backup format.js. Then in your text editor ctrl-F for "twine-javascript". That should bring you to this bit of code:
    el.children('*[type=\"twine-javascript\"]').each(function(el){eval($(this).html())});
    Change it to:
    el.children(\"script\").each(function(el){eval($(this).html())});

    [EDIT: actually, it looks like this was addressed officially with this commit: https://bitbucket.org/klembot/snowman-2/commits/7ac878c70321bf313810eba60f79695808abd9e0 . I'll switch to that instead of the modification I made. ]
  • Will it fixes it also for Harlowe?
  • narF wrote:

    Will it fixes it also for Harlowe?

    No, but you can do a similar thing by doing the following:

    1. Open the HTML file generated by the Publish to File feature in a text editor

    2. Search for "</body>". (without the double quotes)

    3. Add the following code just before the "</body>" text.

    <script>
    $("[role=script]").each(function(i) {try {eval($(this).html());} catch (e) {alert("There is a problem with this story's script (#" + (i + 1) + "):\n\n" + e.message);}});
    $("[role=stylesheet]").each(function(i) {$(document.head).after('<style data-title="Story stylesheet ' + (i + 1) + '">' + $(this).html());});
    </script>
    NOTE: You could do a similar edit in the Harlowe/format.js file instead but I would advise against it as it is easy to get wrong and end up with a broken header file.
  • Thanks! It did fix the problem for Harlowe. It's a bit annoying to have to do that on every exported copy, and we can't preview the story from Twine anymore (otherwise, the javascript still isn't executed obviously). But that temporary fix will do for now. So thanks! :)
  • I downloaded the just released Twine version 2.01 and it looks like Snowman Edit Story JavaScript is now working, by default. So this is entirely resolved now.
  • @narF and anyone else that is interested.

    The new version of the Harlowe story format that comes with Twine 2.0.1 processes the special Stylesheet and Javascript passages, so there should be no need to edit the generated HTML file if you upgrade to 2.0.1.
  • Yayyy!!! :D
Sign In or Register to comment.