[SugarCube 2.29] Run script after an included passage is displayed

Hello.

Is there a way to specify a macro or script to run after an included passage is displayed? I am using the “<>” macro to insert a common passage into another, but there are elements on this passage that need to have event listeners attached to them via JavaScript once they are displayed. However, it doesn’t seem that the “<>” macro generates passage events (i.e. “:passagedisplay”) I’m having difficulty puzzling out a way around this, as simply calling a custom macro in the included passage would run that code before the elements that needed the listeners are actually on the page.

So far, I’ve just been refreshing the entire “parent” passage, but I would really prefer not to do this if at all possible.

Thanks!

TIP: For inline code samples, please use the Preformatted text button on the editor bar or wrap them in backquotes/graves (`), elsewise things like <<foo>> are rendered as <>, which doesn’t tell us much. For blocks, it’s three backquotes/graves (```) on a line by itself, the code, and then three more backquotes/graves on a line by itself.


Before I get into the rest of my reply. Is there some reason you cannot attach the handlers directly? By that I mean, using a custom macro or the built-in output reference of the <<script>> macro you could create the elements and attach the handlers directly.


On to your question. Assuming you meant to show that you’re using <<include>>, then it depends on how you’re using it.

1. Naked within the passage

For example:

Text and more text.

<<include "Some Passage">>

Even more text.

Then you don’t have to do anything as the included passage is transcluded as part of the rendering of the original passage, so your elements will already be there if you use an event like :passagedisplay.

2. Added asynchronously via an interactive macro or similar

For example:

Text and more text.

<<linkreplace "Do the thing!">><<include "Some Passage">><</linkreplace>>

Even more text.

Unfortunately, there’s no event to signal that, so you’ll have to make your code part of the asynchronous payload. For example:

Text and more text.

<<linkreplace "Do the thing!">><<include "Some Passage">><<run setup.addMyHandlers()>><</linkreplace>>

Even more text.

The setup.addMyHandlers() would likely need to run the attachment code on a timer, since there’s no event for you to use in the asynchronous case. For example:

setup.addMyHandlers = function () {
	setTimeout(function () {
		/* attachment code here */
	}, 25);
};
1 Like

Yes, I am using the replace macro to “refresh” the included passage without reloading the “parent” passage, so it seems the timer method would be my best option here. Thank you.