Twine Tuesday: Loading External JavaScript

Since I come from a background in web development, I have been finding myself frustrated with Twine more often than not. I keep wanting to use more complex code in my stories and the Twine editor, the current version anyway, doesn’t always make it simple to do that. I often have to turn to complex solutions of mixing functions, macros, and overly complicated loading methods to make things work the way I want.

I’ve also noticed several people have been bypassing all this work by turning to including jQuery in their code. And I’m not going to argue against using it. It’s a great solution to this issue. However, I personally have problems with it in reference to the editor itself. Previously, in order to use libraries like that, you had to edit the file, after working in Twine, to add it to the HTML head manually.

Yes, I did write “previously” there. I have a working solution around this too. (It’s what I used for last week’s Voigt-Kampff project.)

macros['loadJS'] =
{
	handler: function(place, object, parameters)
	{
		var se = document.createElement("script");
		se.type = 'text/javascript';
		se.src = parameters[0];
		var hT = document.getElementsByTagName("HEAD")[0];
		hT.appendChild(se);
		if(se.innerText) {eval(se.innerText);}
		else {eval(se.textContent);}
	}
}

This code will fetch, add, and load an external JavaScript file. However, and I often see very few people adding this when they post similar code, this is a potential security risk. Make sure you trust any code before you add it to your story. There is no checking with this. It will have the browser run the code directly.

The example for this week’s macro requires two separate files.

alertCode.js

alert("You ended the world!\n\nWhy did you do that? Why?\n\n" +
"Did you not like it? Was that why?\n\n" +
"What? The button? Oh. Okay then. Yeah. That's fine.\nCarry on.");

Story Source:

:: Start
You sit before a computer console full of buttons. There are large, small, square, and triangle ones. All different sizes and shapes.

As you scan across them though, one draws your eye. It is big, red, and looks important. You feel you //must// press it.

[[Big Button of Doom]]

:: script [script]
macros['loadJS'] =
{
	handler: function(place, object, parameters)
	{
		var se = document.createElement("script");
		se.type = 'text/javascript';
		se.src = parameters[0];
		var hT = document.getElementsByTagName("HEAD")[0];
		hT.appendChild(se);
		if(se.innerText) {eval(se.innerText);}
		else {eval(se.textContent);}
	}
}

:: Big Button of Doom
<<loadJS "alertCode.js">>

Should anyone think I am against using jQuery, here is the code to load that too from Google’s CDN.

macros['jQueryRemoteLoading'] =
{
	handler: function(place, object, parameters)
	{
		var se = document.createElement("script");
		se.type = 'text/javascript';
		se.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js";
		var hT = document.getElementsByTagName("HEAD")[0];
		hT.appendChild(se);
		if(se.innerText) {eval(se.innerText);}
		else {eval(se.textContent);}
	}
}