Twine: Improved back and forward buttons in Sugarcane

Update: this feature is now built into Twine 1.4! This behaviour is now the default and this page is no longer necessary.

This script allows Sugarcane to use HTML5 history management instead of URL hash strings to alter the browser history. This means that various non-deterministic game state changes (random numbers, player data input, state changes inside <<replace>> macros, etc.) will be properly remembered when you use the browser's Back button. This code also updates <<back>> and <<return>> and the Rewind menu.

Obsolete script removed: use Twine 1.4

Feel free to report any bugs to @webbedspace.


Improved BACK in Sugarcane

This script worked great. Before using it, BACK just gave me the dreaded 'can't find passage "undefined" in history' error. Thank you!

However, I have had one problem. When I start a game with this script, Javascript pops up to complain, "Cannot read property 'interval' of undefined."

Any ideas on how to avoid this error message?

~ Richard

I did a brief tweak that

I did a brief tweak that could fix this. Do tell.

Warning about interval

Thank you for very much for trying to fix this. Unfortunately, I still get that non-fatal-but-annoying Javascript warning on Start. I am using your latest script and transition CSS, with Sugarcane, Twine 1.3.5, Chrome 27.0.1453.116, Mac OSX 10.6.8.

This is part of my story's html:
{try{eval(scripts[i].text)}catch(e){alert("There is a technical problem with this story ("+scripts[i].title+": "+e.message+"). You may be able to continue reading, but all parts of the story may not work properly.")}}

The warning is:
JavaScript Alert
There is a technical problem with this story (Improved back and forward buttons in Sugarcane: Cannot read property 'interval' of undefined). You may be able to continue reading, but all parts of the story may not work properly.

On a personal note . . . I am a still-quite-enthusiastic Twine newbie. But I wish it would just work as advertised. Twine's great promise is that it is easy to use, but some basic things appear to be broken.

Can we update the installation packages so they work?

I eventually solved my BACK problem, and probably others, by replacing my officlal 1.3.5 installation package's Sugarcane header.html with the 1.3.6 alpha Sugarcane header.html.

On the one hand, I'm delighted, but on the other . . . I wonder how many people are giving up on Twine, because the official 1.3.5 installation package does not support BACK or RETURN.

That would be a terrible shame, because Twine could be so empowering. Before adding more bells and whistles, I'd suggest making sure the basics are solid.

Which makes me wonder, could someone update the official 1.3.5 installation packages for Windows and OSX, so the BACK and RETURN macros work? This could prevent new Twine authors from giving up.

I also wonder, could someone post an installable OSX version of the 1.3.6 alpha?

By the way, I think the Twine resources on Glorious Train Wrecks are fabulous. Thank you!

TheMadExile's picture


Hello. I've been playing around with the back/return macros and I found a few bugs, so I figured that I'd report them.

Also, just in case you were unaware, while not a bug, Firefox places a size limit of 640k on the serialization of the state object passed to pushState()/replaceState(). So, stories that generate history states that large will cause this mod to fail.


This code:
if (hasPushState && this.history && this.history.length > 2) {
	window.history.pushState(this.history, document.title);

Should be something like this:
if (hasPushState && this.history) {
	if (this.history.length == 2 && window.history.state === null) {
		window.history.replaceState(this.history, document.title);
	} else {
		window.history.pushState(this.history, document.title);

This code has two this.hash = statements in the same block, one of them is redundant:
if (a != "offscreen") {
	document.title = tale.title + ": " + c.title;
	this.hash =;
	if (!hasPushState) {
		this.hash =;
		window.location.hash = this.hash;
	window.scroll(0, 0);


This code:

Should be something like this:
if (hasPushState) {
} else {
	window.location.hash = "";

OK, I'll put these fixes in.

OK, I'll put these fixes in. Danke!