Multi-level expandable text

Twine Version: 2.6.2 Sugarcube 2.36.1
Hello,

I’m trying to set up an inventory list in Twine. It should be sort of a nested node structure (like the folder view in Windows Explorer), starting with a single Inventory link in the top right corner of the game window. Clicking on it should display the list of items the player is carrying, clicking on a specific item should display the list of actions for it. I found some examples with expandable/collapsible text, and tried to adopt them to my situation, placing it in the PassageHeader passage to have the inventory everywhere in the game. It basically works, but unfortunately the list shows empty space for hidden actions, which is undesirable. I tried some workarounds (like setting the font size to a very small value for the hidden text style), but in this case, the line breaks go mad, ruining the formatting. Could you help me with that please?

My code in the PassageHeader passage:

<div class="headerright"><<link "Inventory">><<toggleclass "#InvItem1" "hidden InventoryItem">><<toggleclass "#InvItem2" "hidden InventoryItem">><<toggleclass "#InvItem3" "hidden InventoryItem">><</link>></div>
<div id="InvItem1" class="hidden" style="float: right; width: 290px"><<link "Inventory Item 1">><<toggleclass "#InvItem1A1" "hidden InventoryAction">><</link>></div>
<div id="InvItem1A1" class="hidden" style="float: right; width: 280px">[[Action1|passage11]]</div>
<div id="InvItem2" class="hidden" style="float: right; width: 290px"><<link "Inventory Item 2">><<toggleclass "#InvItem2A1" "hidden InventoryAction">><<toggleclass "#InvItem2A2" "hidden InventoryAction">><</link>></div>
<div id="InvItem2A1" class="hidden" style="float: right; width: 280px">[[Action1|passage21]]</div>
<div id="InvItem2A2" class="hidden" style="float: right; width: 280px">[[Action2|passage22]]</div>
<div id="InvItem3" class="hidden" style="float: right; width: 290px"><<link "Inventory Item 3">><<toggleclass "#InvItem3A1" "hidden InventoryAction">><</link>></div>
<div id="InvItem3A1" class="hidden" style="float: right; width: 280px">[[Action1|passage31]]</div>
<BR>

My CSS-sheet styles:

.headerright {
  float: right;
  width: 300px;
}
.hidden {
	display: none;
}
.InventoryAction {
  float: right;
  width: 280px;
}
.InventoryItem {
  float: right;
  width: 290px;
}

Thank you in advance!

I think you’ll show lines for your hidden objects because they are inside a <div></div> element. Have you tried to nestle these inside an <<if something's true>><div></div><</if>> ?
I suppose you have added the nobr tag.

Thank you for the reply, I tried this out, but it doesn’t help.

If anything, it adds issues. First of all, the only place to set the flag variable to be used in <<if>> seems to be the main Inventory link. But the change has effect for evaluation only after the game jumps to another passage. Thus, clicking Inventory doesn’t do anything useful. Second, if I nestle the <div> definition inside the <<if>> macro, the system doesn’t “see” the ID definitions of the respective elements, displaying an error message when it encounters these IDs in the toggleclass macro of the main inventory link. And finally, this doesn’t seem to fix anything in the text output. I finally came up with the following code (here, inventory items text style toggling is removed completely - they are displayed based on the $InvCollapsed flag variable, which is initially set to false and then toggled in the special DummyPassage passage the main Inventory link refers to). Note that the code below shows InventoryItem3 when all other items are hidden - this is done delibirately to test the empty space handling. The behaviour is essentially the same as before - without <<nobr>>, empty lines for missing inventory items and actions are displayed; adding <<nobr>> messes up the list formatting.

<div class="headerright"><<link "Inventory" "DummyPassage">><</link>></div>
<<nobr>>
<<if $InvCollapsed is false>><div id="InvItem1" class="InventoryItem" style="float: right; width: 290px"><<link "Inventory Item 1">><<toggleclass "#InvItem1A1" "hidden InventoryAction">><</link>></div><</if>>
<<if $InvCollapsed is false>><div id="InvItem1A1" class="hidden" style="float: right; width: 280px">[[Action1|passage11]]</div><</if>>
<<if $InvCollapsed is false>><div id="InvItem2" class="InventoryItem" style="float: right; width: 290px"><<link "Inventory Item 2">><<toggleclass "#InvItem2A1" "hidden InventoryAction">><<toggleclass "#InvItem2A2" "hidden InventoryAction">><</link>></div><</if>>
<<if $InvCollapsed is false>><div id="InvItem2A1" class="hidden" style="float: right; width: 280px">[[Action1|passage21]]</div><</if>>
<<if $InvCollapsed is false>><div id="InvItem2A2" class="hidden" style="float: right; width: 280px">[[Action2|passage22]]</div><</if>>
<<if $InvCollapsed is true>><div id="InvItem3" class="InventoryItem" style="float: right; width: 290px"><<link "Inventory Item 3">><<toggleclass "#InvItem3A1" "hidden InventoryAction">><</link>></div><</if>>
<<if $InvCollapsed is false>><div id="InvItem3A1" class="hidden" style="float: right; width: 280px">[[Action1|passage31]]</div><</if>>
<</nobr>>
<BR>

I’m not really at ease with <<toggleclass>> macro, so, instead of offering options I’m not sure it will work I prefer to go with what I know will work, and how to make it work.

The easiest way I’ve ever found to make something instantly update, without change of passage, is by replacing by itself every time I need it to be replaced. The best way is to use the <<replace>><</replace>> macro.

Here’s something that should address your question, though you might dislike some points, more below.

In your PassageHeader passage:

<span id = "inventory"><<include "Inventory">></span>

In a new dedicated Inventory passage:

<div class="headerright"><<link "Inventory">><<if _inventory>><<set _inventory to false>><<else>><<set _inventory to true>><</if>><<replace "#inventory">><<include "Inventory">><</replace>><</link>></div>
<<if _inventory>><br><div class="InventoryItem"><<link "Inventory Item 1">><<if _inventory1>><<set _inventory1 to false>><<else>><<set _inventory1 to true>><</if>><<replace "#inventory">><<include "Inventory">><</replace>><</link>></div>
<<if _inventory1>><br><div class="InventoryAction">[[Action1|passage11]]</div><</if>>
<br><div class="InventoryItem"><<link "Inventory Item 2">><<if _inventory2>><<set _inventory2 to false>><<else>><<set _inventory2 to true>><</if>><<replace "#inventory">><<include "Inventory">><</replace>><</link>></div>
<if _inventory2>><br><div class="InventoryAction">[[Action1|passage21]]</div>
<br><div class="InventoryAction">[[Action2|passage22]]</div><</if>>
<br><div class="InventoryItem"><<link "Inventory Item 3">><<if _inventory3>><<set _inventory3 to false>><<else>><<set _inventory3 to true>><</if>><<replace "#inventory">><<include "Inventory">><</replace>><</link>></div>
<<if _inventory3>><br><div class="InventoryAction">[[Action1|passage31]]</div><</if>>
<</if>>
<BR>

So what will now pose further trouble?

First the inventory automatically collapses each time the Action 1 or Action 2 links are used. It’s mainly because I used temporary variables rather than story variables. If you intend for your inventory not to collapse at this point you might look for story variables, though it will also mean you’ll have to set more variables to false each time you want to collapse your inventory.

Second right now your Action 1 or Action 2 links point to a new passage. It means you need a way to tell the browser where to restart once the inventory action is done. There’s many ways to address this. The easiest is probably to set a variable to register the last passage and send the story back to that passage at the end of passage11, passage21, passage22 or passage31 passages.

Thank you a lot! That seems to solve my issue, after a day’s struggle:). Real magic:).

Collapsing the inventory after using a link is desired behaviour, no trouble:). Getting back to the story after being done with the inventory action is something I’m dealing with already, using basically the same idea of tracking relevant passages by means of a variable.

In fact, your code has a single minor issue - when collapsing the whole inventory, it hides the items but not the actions previously expanded. Come to think of it, though, that’s not an issue but extra pedagogical value:).

Again - thank you so much!

As your Inventory could be considered a “menu” option the Arbitrarily long return section of the SugarCube documentation might be of some help.

1 Like

Thanks! Consulting this splendid documentation all the way:).