+1 vote
by (380 points)

I've got a Replace macro in a PassageDone passage:

<<replace "#thing1">>thing2<</replace>>

In this case, because of the way my story is structured, I have no way of knowing when the #thing1 class will appear in the game, it's completely unpredictable. When the #thing1 class is in the passage everything works great, but if it's not, I get errors every passage. Is the only solution to just find some way of controlling the replace macro using if statements? Or is there a way to not get Sugarcube to spit out errors if the class it's looking for isn't there?

1 Answer

0 votes
by (8.6k points)
selected by
 
Best answer

You'll need to use some JavaScript in any case, so my suggestion would be to simply modify the <<replace>> macro itself. It's easy enough; just replace its handler() method in your story's JavaScript portion.

Macro.get("replace").handler = function() {
	if (this.args.length === 0) {
		return this.error('no selector specified');
	}

	if (this.payload[0].contents !== '') {
		const $targets = jQuery(this.args[0]);
		const frag = document.createDocumentFragment();
		new Wikifier(frag, this.payload[0].contents);
		switch (this.name) {
			case 'replace':
				$targets.empty().append(frag);
				break;
			case 'append':
				$targets.append(frag);
				break;
			case 'prepend':
				$targets.prepend(frag);
				break;
		}
	} else if (this.name === 'replace') {
		jQuery(this.args[0]).empty();
	}
};

What it does, in comparison to the original macro handler, is simply removing the check for "no valid targets found", or those three lines:

if ($targets.length === 0) {
	return this.error(`no elements matched the selector "${this.args[0]}"`);
}

I also compressed the code a bit, but that's purely æsthetics.

by (380 points)
Works great, thank you so much! <3
by (380 points)
Hey, quick followup: I'm just now learning that you cannot tag multiple strings within the same passage using the same class id, after the first one none of the others will be recognized by <<replace>>. Any suggestions for using the replace macro on multiple instances of the same string in the same passage? Or do I just have to create different individual classes for each string I'm replacing?
by (8.6k points)

@cakebread You seem to be confusing CSS "classes" and "ids". "#id" is an ID, ".class" (note the dot at the beginning!) is a "class". An ID should be unique, but classes don't have to be. With that in mind, this works.

@@.replacedClass;Text to replace.@@
Text to keep.
@@.replacedClass;More text to replace.@@
<<link "Replace!">><<replace ".replacedClass">>Text replaced.<</replace>><</link>>

 

...