Sidebar code revisited

Greetings all. Last August, mrangel posted some clever JS code (here: in response to a user's request for a hideable sidebar for their game. When I came across that, it turned out to be exactly what the game I'm writing needed, so I stole it wholesale.

Now I find myself relying heavily on passages – but the sidebar only updates when changing sections. Unfortunately, I'm a rank amateur with JS, and have been unable to figure out a way to update the sidebar on demand, either in the sidebar code itself or in a master passage added where necessary. I would be much obliged if anyone can help.

I opened a new topic as the original post is now closed (and finding old forum posts on given topics is, shall we say, a bit of a hassle).

The code there was my first attempt at using Squiffy, so it's very rough. I think there are a few other bugs I've discovered since, and I'm not sure if I remembered to update that.

I hadn't discovered passages at that point, which is probably why I failed to handle them. I'll take a look later and see if I can clean that up at all. If your game is anything like my first attempt, it would probably help to combine the code with my later master section mod, which allows passages under the master section to be accessed from anywhere; this would be a better way to handle stuff like [drink potion] or similar.

OK… rebuilding this off the top of my head, haven't tested yet.

EDIT: Briefly tested, corrected two trivial errors.

@start initialise_interface

    $(function () { = function () {
        squiffy.set('_output', squiffy.ui.output.html());
        squiffy.set('_transition', "squiffy.story.sections['initialise_interface'].js");

      var showSidebar = function () {
        squiffy.ui.write(squiffy.story.sections['sidebar container'].text);
        if ($('.ui-layout-north:visible').length) {
          $('#showinv').css('top', $('#showinv').offset()['top']+92);
          $('#sidebar').css('top', $('#sidebar').offset()['top']+92);
          $('#sidebar').css('bottom', '100px');
          $('<button>', {id: 'killsidebar', style: 'position: absolute; bottom: 4px; right: 4px'}).click(function () {
          }).text('kill sidebar').appendTo('#sidebar');
        $('#showinv').click(e => $('#sidebar').animate({left: 0}));
        $('#hideinv').click(e => $('#sidebar').animate({left: 5-$('#sidebar').width()}));
      var updateSidebar = function() {
        if (!$('#sidebar').length) {
        if ($('#sidebar:visible').length) {
          $('#sidebar').append(squiffy.ui.processText(squiffy.story.sections['sidebar contents'].text));
          if (squiffy.get('gameover')) {
            $('#sidebar a').remove();

      var original_go = squiffy.story.go;
      squiffy.story.go = function (section) {
        if (squiffy.afterText) {
          var after = squiffy.afterText;

      var setSeen = function (sectionName) {
        var seenSections = squiffy.get('_seen_sections');
        if (!seenSections) seenSections = [];
        if (seenSections.indexOf(sectionName) == -1) {
          squiffy.set('_seen_sections', seenSections);
      squiffy.story.passage = function(passageName) {
        var passage = squiffy.story.section.passages[passageName];
        if (passage) setSeen(squiffy.get('_section') + '.' + passageName);
        var masterSection = squiffy.story.sections[''];
        if (!(passage || masterSection)) return;
        if (masterSection) {
          if (!passage) {
            passage = masterSection.passages[passageName];
            if (!passage) return;
          var masterPassage = masterSection.passages[''];
          if (masterPassage) {
        setSeen('.' + passageName);
        var master = squiffy.story.section.passages[''];
        if (master) {

      // any other  JS functions you need to modify will go here

      if (squiffy.get('_output')) {
        // If we're loading a saved game, display the sidebar
      } else {
        // Go to the actual start of the game; change the name as appropriate
        squiffy.story.go('first section');

[[sidebar container]]:
<button style="position: fixed; top: 6px; left: 2px;" id="showinv" type="button">Show sidebar</button>
<div id="sidebar" style="background-color: white; position: fixed; left: 1px; top: 4px; bottom: 4px; width: 20%; overflow-y: auto; border: 1px double blue;"><button style="position: absolute; top: 2px; right: 2px;" id="hideinv"  type="button">Hide sidebar</button></div>

[[sidebar contents]]:

<p style="font-weight: bold;">Inventory</p>

<p>You are {if health=true:healthy}{else: unhealthy}.</p>
{if has_potions:<p>You have {has_potions} potions. [Drink potion]</p>}

[Drink potion]:
@dec has_potions

You drink it. It tastes great!

[[first section]]:
Here's the actual start of the game.

That's off the top of my head, pulling together a few different bits of code from past experiments. This should make the sidebar update for passages as well as sections. Also, if the global section ([[]]:) has passages, they can be visited while in any session.

I've also tweaked seen so that it'll work if you have passages with the same name within different sections.
Now you can use:

{if seen name of section:You have been to [[name of section]]}
{if seen .name of passage: You have seen a passage named "name of passage", but I don't know which section it was in (this is how 'seen' used to work)}
{if seen section name.passage name: You have seen the passage named "passage name" in the section [[section name]].}

I think that makes it a little more useful.

That certainly looks good! (I too had wondered whether something like that wouldn't be better for "seen" notation.)

Unfortunately, there's something wonky with it, and I can't put my finger on it. It probably has something to do with setting the current section, since passage links seem to work erratically. More alarmingly, after I run this code once, after restarting the sidebar refuses to appear at all – and so does the text of the game itself. I have to restart the editor.

Help pls? ^.^

I'll give it a try later if I have time. I was writing off the top of my head there, as I was on my phone without access to Squiffy.

… or now, if it's only a 2-minute fix.

OK… 2 careless typos.
Changing the line

      var setSeen = function (section) {


      var setSeen = function (sectionName) {

and at the end, changing

        squiffy.story.go('First section');


        squiffy.story.go('first section');

(or whatever the name of your actual first section is)

After that it seems to work as planned :)

(I only tested these fixes in the scratchpad, so if it still fails in the editor and/or when published, I'll take another look)

Well I am flabbergasted. I copied the code verbatim, checked to see all section names were called correctly, and still it won't work. (I'm using the editor on Ubuntu Mate.) No sidebar, nor anything else when "Built" and run in a browser. (In the editor's Output tab, it works once, but not a second time without restarting the editor. And the sidebar is still missing.)

But! If I delete the very useful altered master passage code, everything works. So it has to be something to do with that bit. What exactly, I have no clue.

That's weird. Do any errors show up in the console?

I'll take a look when I get back to my computer

I can't understand what _output is doing here.

The attribute should be created every time is called, saving the current contents of the output pane.
So in that script, I tested if that attribute exists to see if the game is already running.

When the game initialises, it uses the exact same test to decide whether to load a saved game or go to the start section.

But it seems like that only works in the editor's test pane… once I publish the game, _output starts as <div id=\"squiffy-section-1\"><div></div><div>.

So… need to use other means to check if we're loading a saved game or starting a new one.

I tried changing:

      if (squiffy.get('_output')) {
        // If we're loading a saved game, display the sidebar
      } else {


      if (squiffy.get('_section') != "initialise_interface") {
        // If we're loading a saved game, display the sidebar
      } else {

and it seems to work in preview.

That's basically testing if we're actually on this section.

Although now I think about it,

      if (squiffy.get('_transition')) {

might have been more logical.

Haven't tried that yet.

Log in to post a reply.