Howdy, Stranger!

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

[Snowman] Printing to screen after passage render

edited March 2017 in Help! with 2.0
First things first: my deepest thanks to the whole forum and specially @greyelf and @TheMadExile who have helped me again and again. I've just ported 100% of my Harlowe game to Snowman, despite not knowing Javascript, and it works all right.

Now, one of those stupid questions related to not knowing Javascript.

Sometimes instead of using <%= %> to print a variable I use <% print() %>, if it's in the middle of another block of code (an if for example). However, I don't know how to create a link that prints something after the passage has been rendered. Something like this:
<a id="link">Link</a>
<% 	
	$(function () { 
		$('#link').click(function () { 
			variable = 1;
			print(variable);
		});
	});
%>

When I click this link, statements like variable=1 are executed, but print() does nothing. I have some fuzzy notion that this is because the passage has already finished rendering, but I have zero understanding of why and how to go forward. Any suggestion?

Thanks!

PS: porting the game to Snowman has been more than worth it. The Harlowe version literally killed my mobile browser, while the Snowman version feels like a snappy web app. Now I hope that I get to finally end writing the story and release it, and people can reuse my code if they like.

Comments

  • Snowman uses custom events to indicate when particular things happen, you can monitor for those events to occur and run your own Javascript code when they do.

    An example of one of those events being triggered can been seen on line 383 of the show() function, which is triggering the 'showpassage:after' event you may be interested in.

    The following example show how to monitor for that event in the current Passage, it uses the jQuery one() function to associate an anonymous function to be called when the event fires. It includes your link element and on-click handler except I have changed it to output to the console instead for demonstration purposes.
    <a id="link">Link</a>
    
    <% 	
    $(document).one("showpassage:after", function(event, data) {
    
    	console.log('showpassage:after event fired');
    
    	$('#link').click(function () {
    		console.log('link clicked');
    	});
    });
    %>
    
  • Menti wrote: »
    variable = 1;
    
    First. Don't do that. You're creating an auto-global, thus tainting and possibly clobbering properties on the window object. Always either use Snowman's story variable store or use the var keyword to create a local variable. If you need/want to create an auto-global, then specifically assign to the window object, don't do it by accident.

    For example:
    → Snowman story variable
    story.state.foo = …;
    
    → Snowman story variable alias (only within templates; i.e. within <%…%> & <%=…%>)
    s.foo = …;
    
    → Local variable
    var foo = …;
    
    → Auto-global
    window.foo = …;
    
    TIP: Enabling strict mode will catch errors like that for you. For example:
    <%
    $(function () {
    	'use strict';
    
    	/* The following line is illegal in strict mode and will throw an error. */
    	foo = "something"; // implicitly create an auto-global
    
    	/* The following line is legal in strict mode. */
    	window.foo = "something"; // explicitly create an auto-global
    });
    %>
    
    All in all, I'd suggest staying away from auto-globals as much as possible.


    Menti wrote: »
    When I click this link, statements like variable=1 are executed, but print() does nothing. I have some fuzzy notion that this is because the passage has already finished rendering, but I have zero understanding of why and how to go forward.
    The print() function is part of the template system, so that's exactly why it doesn't work in this instance—template rendering is long complete by the time the player activates the link.

    You need to create a target element, which you may add your content to. For example:
    <a id="link">Link</a>
    <div id="link-target"></div>
    <%
    $(function () {
    	'use strict';
    
    	$('#link').one('click', function () {
    		$('#link-target').text("I'm a little teapot!");
    	});
    });
    %>
    
    That will add the text I'm a little teapot! to the #link-target element when the link is activated.

    Ideally, you'll probably want to leverage Snowman's renderer, so that you may use markup. Happily, if you're using Snowman v1.3.0, you can. For example:
    <%
    $(function () {
    	'use strict';
    
    	$('#link').one('click', function () {
    		$('#link-target').append(Passage.render("I'm a *little* [[teapot]]!"));
    	});
    });
    %>
    


    greyelf wrote: »
    An example of one of those events being triggered can been seen on line 383 of the show() function, which is triggering the 'showpassage:after' event you may be interested in.
    FYI. While greyelf is entirely correct, Snowman's in-template ready function provides the exact same functionality without requiring users to manually handle the showpassage:after event.

    In other words, as long as your code is rendered by Snowman's template renderer—i.e. it's within <%…%> & <%=…%>—then the following code from greyelf's example:
    <%
    $(document).one("showpassage:after", function(event, data) {
    	console.log('showpassage:after event fired');
    
    	$('#link').click(function () {
    		console.log('link clicked');
    	});
    });
    %>
    
    Could be written more simply like so:
    <%
    $(function () {
    	console.log('showpassage:after event fired');
    
    	$('#link').click(function () {
    		console.log('link clicked');
    	});
    });
    %>
    
  • Wow. Thanks again, your examples are extremely exhaustive and I've managed to get what I wanted done.
Sign In or Register to comment.