0 votes
by (1.3k points)
<span id="sceneList">\
<span id="scene1">//scene as yet unlocked//</span>
<<if $unlockedScenes.includes("scene1")>><<replace "#scene1">>[[Scene 1|Scene1]]<</replace>><</if>>\

So, the idea behind this one is to present the user with a fully locked listing at the start, but to unlock scenes one by one as they get to them. It's a scene recall mechanism. But it's not working. And I don't know why.

If I replace the if statement with a button, using the exact same constructs, it works. Like this:

<<button "show">><<replace "#scene1">>[[Scene 1|Scene1]]<</replace>><</button>>

That works no worries. But, I've looked at some code from the sugarcube docs, and it seems to show that I can use <<replace>> with if statements, as seen with the example under <<silently>>. So, what gives? Am I using this wrongly somehow?

I need to get this sorted out, before I write too many more scenes, because I think I need to design them with this recall feature in mind. I'd like to capture variables at the time, so that the recollections use those, instead of the current ones. The user could conceivable look at the scene near the end of the story, and I'd like them to see the scene as they played throught it, not with the stats they have currently. So, I record them somehow. I preserve them. But, I think I need to sort out what things I need to preserve, and get this functional so I can play with it. Do the first one, and the others will follow from that.

So... what think? The error I get is this: "Error: <<replace>>: no elements matched the selector "#scene1"" I get no such error when I use that stupid button thing.

1 Answer

+1 vote
by (68.6k points)
edited by
Best answer

On my phone so you're getting the short version for now.

You cannot use <<replace>> in that manner because the element you're attempting to target is not yet on the page, as the passage is still rendering.  There are ways to do what you're attempting, however.

That said, you don't need to use <<replace>> here at all.  For example:

<span id="sceneList">\
<span id="scene1">\
<<if $unlockedScenes.includes("scene1")>>\
[[Scene 1|Scene1]]\
<<else>>//scene as yet unlocked//<</if>>\

Hopefully, that's not too screwed up.  I hate replying from phones.

by (63.1k points)

To add a bit to TME's answer: 

Some other similar questions with answers/explanations and work-arounds: 

I suggest reading those for more explanation and ideas. Generally, the solutions are: 

  • Use a <<timed>> macro or otherwise delay the code slightly. 
  • Use a PassageDone special passage or a postdisplay task object to have the code run just after rendering is complete. 
  • Use some form of interaction, like a link, and tie the DOM action to that. 
by (1.3k points)
Thanks guys. I'll go with the more simple method for now, but I will check those other ways, since I have seen them used in other projects. I wondered about they they chose to use <<timed>>. I think I have most of what I want now. The rest can be left for when I have a bit more done.

But, I really appreciate the help!