Can you get the exact renderization of a passage, but not by extracting and parsing it from html resulting code?

I want to store in a var the exact renderization of the passage the player is visiting including the exact result of vars calculation, inserts, modifiers…
I have seen there is a function engine.render. But if i perform engine.render and give as a param the passage’s source "engine.render(engine.story.passageNamed("Welcome Passage").source)", all vars are calculated again so that if the passage included strength = strength +1, when i execute engine.render strength is incremented again.
I guess i could just parse the resulting html in #page article, but is there another way?

1 Like

Buckle up… :wink:

OPTION #0 <== THAT’S HOW PROGRAMMERS START A LIST!

You can definitely get the innerHTML of the <article id="page"> and put it back in with insertAdjacentHTML (better than setting the innerHTML) to revert what the player sees as if nothing has happened. You maybe need to store the page scroll position before hand as well. Not 100% sure of the scenario you have though.

Edit: I believe I have working code for this as I once made a parser Chapbook engine and dealt with refreshing the page and such. Wrote to the #page, like you speculated.


OPTION #1

When I was working with Harlowe I had some funny stuff happen with certain variables that were set in the prior passage and when I hit refresh they reverted (some did + some didn’t = weirdness). So I made a transition passage that did nothing but calculate variables and then go to the next passage. The user was none the wiser. Perhaps this is a strategy you could take advantage of.

I remember reading about a function called go() being exposed in Chapbook. I think David @Hituro mentioned it at one point. I know it affects the trail because if you call go() with a passage name in the function, it will go to that passage only if you hit refresh, but it doesn’t render the passage on it’s own. So maybe you need to engine.render() that same passage after calling go(). I’m just not familiar enough with that function to understand it yet. Hopefully someone else can provide some insight.

I do wonder about the default cross-fade transition going blank in between the 3 passages though. Harlowe doesn’t have a cross-fade so it was a non-issue. It only goes instantly blank and fades-in the next passage.


OPTION #2

If you are absolutely certain that you want to calculate a set of variables in a passage only once per game, in a [javascript] modifier you could simply wrap the variables in a condition that checks to see if the last passage trail.slice(-1) in the trail array contains the current passage.name. If you prefer using the var section, you could put that condition in front of all variable changes. Definitely make a custom function, to keep it clean looking, that only returns true or false.

Refreshing the page will not alter the trail, thus not recalculate any variables.

Edit: Upon further reflection, this would not work as described. The trail will always have the current passage name as the last passage visited. I was spit-balling and did a face plant. Though the premise could work if you kept a separate trail saved of calculated passages and check that first and only add to it after a page has been rendered. So the premise is sound, but a separate array must be kept and maintained. There is probabley a nifty way to handle this with a listener that fires on any changes to the #page. Again, thinking out loud.


OPTION #3

The state object contains all variables that you change or create. Default “system” Chapbook variables will only exist in the state object if you change them. There might be a way to take advantage of the state object. If you are finding that this “variables climbing” problem is simply a result of refreshing the page (which would cause that), we can keep a backup of the state object with every passage visited (possibly automated with a config.header.center = '{embed passage}'-type of code – which runs the embedded passage code upon redrawing the story passage every time and it would override the backup state variable each time).

The story JavaScript passage only executes once at the beginning, but if the page is refreshed, it will run again. You could then check the last trail array item and if it matches the current passage.name, it will overwrite the current state object with the backup state object. Then the passage will be rendered, recalculating the variables, but from their previous state.

I did some quick tests and the solution seems like it could work. The rendering order of the header versus the main article passage needs to be determined. Objects can be duplicated by a clone method. Not sure what kind of story variables you are storing, but JSON.parse(JSON.stringify(engine.state)) is a pretty robust way to clone an object. It should work perfectly for your story settings and variables.

3 Ways to Clone Objects in JavaScript | SamanthaMing.com for more information


…alright. Let me know if anything I said resonates with your situation and we can figure it out further if need be. I wanna know the best way to handle not recalculating variables too.

I’m curious about why you’re needing to store such?

As it sounds like you’re trying to implement an Endless-page or Stretch-text implementation…
eg. where the content of each newly visited Passage is displayed below the content of earlier visited Passage.

…and if so, how do you intend to handle the need to recreate the entire page again after a web-browser Page-Refresh occurs for any reason.
eg. like when the web-browser app on a Mobile device regains focus again after the end-user takes a call or responds to an SMS/Message.

1 Like

@javiermobile

Just curious, did this not work for you? I thought this code edits a variable and then goes to a passage… or are you putting conditions on how the variable or which variable gets incremented (and keeping it in the passage code is just more maintainable)?