0 votes
by (2.4k points)

Hello everyone!

I have a passage that I have to modify dependind on the player choices. Currently I'm doing it using <<addclass>> and <<removeclass>> to add a css class with "display: none" on it to the passage divs I want to show or hide. So far i works perfectly like this:

<div id="scnAwakening_choices">\
<div class="choice charText playerText">\
<ul>\
<li><<click "I must remain calm">>\
	<<addclass "#scnAwakening_choices" "hidden">>\
	<<removeclass "#scnAwakening_calm" "hidden">>\
	<<set $events.calmAwakening to true>>\
<</click>></li>
<li><<click "Let me out!!">>\
	<<addclass "#scnAwakening_choices" "hidden">>\
	<<removeclass "#scnAwakening_notCalm" "hidden">>\
	<<set $events.calmAwakening to false>>\
<</click>></li>
</ul>\
</div>
</div>\
<div id="scnAwakening_calm" class="hidden">\
	(Some calmed text here)

	[[Continue...|scnAwakening_calm]]
</div>\
<div id="scnAwakening_notCalm" class="hidden">\
	(Some text here)

	[[Continue...|scnAwakening_notCalm]]
</div>\

The problem is that if I reload the game or visit another passage from a link in the StoryCaption and return to this one, the passage goes back to its initial state, before reasigning the "hidden" class. So I decided to use a variable and a bit more of code to track in witch "state" the passage is (wich divs are visible or hidden) like this:

<<switch $state.scnAwakening>>
	<<case 1>>
		<<addclass "#scnAwakening_choices" "hidden">>\
		<<removeclass "#scnAwakening_calm" "hidden">>\
		<<addclass "#scnAwakening_notCalm" "hidden">>
	<<case 2>>
		<<addclass "#scnAwakening_choices" "hidden">>
		<<addclass "#scnAwakening_calm" "hidden">>
		<<removeclass "#scnAwakening_notCalm" "hidden">>
<</switch>>

(The value of $state.scnAwakening is update inside the <<click>> macros)

The problem here is that when this code is loaded, I receive an error saying that none of the <<addclass>> or <<removeclass>> from that part of the code can find any element matching the selector, despite they were found the first time. I've tried using this code both at the begining and at the end of the passage, with the same result.

Anybody knows what I'm doing wrong? (probably a lot of things... ) Thanks!

1 Answer

+2 votes
by (159k points)
selected by
 
Best answer

Your issue is one of "timing", the div elements being referenced by your <<addclass>> and <<removeclass>> macros won't exist until after the entire Passage has been processed and the HTML element it generated have been added to the current page (DOM). This causes the <<addclass>> and <<removeclass>> macros to fail.

You can solve this issue by use one of the Navigation Events & Tasks to delay the execution of your <<switch>> macro until after the related div elements have been added to the page. Because you want this event/task only occur on a single passage you can do one of the following:

1. Use an <<if>> macro within the PassageDone special passage to gate the execution of your <<switch> to a specific Passage.

<<if passage() is "Name of Passage">>
	<<switch $state.scnAwakening>>
		<<case 1>>
			<<addclass "#scnAwakening_choices" "hidden">>\
			<<removeclass "#scnAwakening_calm" "hidden">>\
			<<addclass "#scnAwakening_notCalm" "hidden">>
		<<case 2>>
			<<addclass "#scnAwakening_choices" "hidden">>
			<<addclass "#scnAwakening_calm" "hidden">>
			<<removeclass "#scnAwakening_notCalm" "hidden">>
	<</switch>>
<</if>>


2. Convert your existing <<switch>> to JavaScript and use a single use :passagerender event .
note: The following is added to the end of the Passage that used to include your <<switch>> code.

<<script>>
	/* Execute the handler function exactly once. */
	$(document).one(':passagerender', function (ev) {
		var $content = $(ev.content);
		switch (State.variables.state.scnAwakening) {
			case 1:
				$content.find("#scnAwakening_choices").addClass("hidden");
				$content.find("#scnAwakening_calm").removeClass("hidden");
				$content.find("#scnAwakening_notCalm").addClass("hidden");
				break;
			case 2:
				$content.find("#scnAwakening_choices").addClass("hidden");
				$content.find("#scnAwakening_calm").addClass("hidden");
				$content.find("#scnAwakening_notCalm").removeClass("hidden");
				break;
		}
	});
<</script>>

The above uses jQuery functions like find() to locate the element in the HTML structure that is about to be rendered, and the addClass() and removeClass() functions to add/remove the "hidden" CSS class.

by (2.4k points)
Thanks a lot!

I've been able to fix it using the PassageDone.
by (190 points)

Maybe I'm wrong but I can't find any working solution to use properly <<addclass>> to the #passage-<passage-name> that Sugarcube create at (I guess) the render process. Let me explain:

:: StoryInterface

<div id="passages"></div>

:: Start

Lorem ipsum dolor est

If you inspect the HTML, you found that: 

<div id="passages">
 <div id="passage-start" data-passage="Start" class="passage">
   Lorem ipsum dolor est
 </div>
</div>

But, if you try to add a class name to "#passage-start", I can't wathever I'm using <<if>> macro or :passagerender event

Any clue?

...