JS error after navigating AWAY from passage with <<script>> macro

Twine 2.4.1, Story: Sugarcube 2.36.1

I have one single passage that is meant to simulate a text message exchange. I created a “phone” div which I styled with CSS to look like a phone screen, and set the text messages to pop up “in real time” using ‘timed’ macros.

My last step was getting the “phone screen” to autoscroll to the bottom as each new text came in. I added some JS to my story’s overall Javascript, but since I only have the phone div on one passage, I was getting errors as soon as I opened the game as it tried to run and wasn’t finding the needed attributes (since they only exist in one passage). So I took it out of the game’s JS and added it to the passage itself instead:

<<script>>window.setInterval(function() {
  var elem = document.getElementById('phone');
  elem.scrollTop = elem.scrollHeight;
}, 100);<</script>>

This seemed to have solved my issue. I am now able to play the game up to that passage without errors, and the passage now functions as desired. However, when I navigate AWAY from that passage, I immediately get the error I was previously getting at the start of the game: Error: Cannot read properties of null (reading ‘scrollHeight’).

I’m assuming that my script macro activates the javascript, but it fails to… you know, deactivate it? How do I get this script to ONLY run while I am in this specific passage?

ETA: I also tried implementing this autoscroll macro, but I couldn’t get it affect the scrollbar in the div, it would always just scroll the overall page’s scrollbar instead. If it’s easier to solve for this issue than the error above, I would appreciate that as well!

1 Like

Hi Eli,

So, if I’m understanding what you’re doing right, you use a bunch of <<timed>> passages to add items to your phonebook. Then in the passage you’ve attached a function that, every 100 ms, scrolls your phonebook down.

Okay, so, there are a couple of things you could do. First, one thing I think might work is just adding the scroll your phonebook down code to the <<timed>> passages themselves (if there’s a fade-in maybe schedule the scroll-down for an appropriate amount of time after the number is added) - that way you wouldn’t have to deal with the function.

You could also deactivate the scroll function when leaving the passage by assigning the function to a variable, and then clearing it afterwards. You’d modify the script like so:

<<script>>
State.temporary.scrollFn = YOUR_SCROLL_FUNCTION
window.setInterval(State.temporary.scrollFn, TIMER_INTERVAL);
<</script>>

and then modify the outgoing link/button like this:

<<button "The button to exit the passage">>
  <<run clearInterval(State.temporary.scrollFn)>>
<</button>>

See Window setInterval() Method for more details.

It’s not multiple passages, it’s just one passage with timed text sections, a la:

<div id="phone" class="content1"><p class="messagebody">

<span class="metext"><span class="hide"><b>SPARROW:</b></span>Where the heck are you?</span>

<<timed 1s>><span class="metext"><span class="hide"><b>SPARROW:</b></span>You're going to be grounded for the rest of your life.</span>

<<next 2s>><span class="youtext"><span class="hide"><b>WHIRLWIND:</b></span>thisis not supportive oldr brthr talk</span>

<<next>><span class="metext"><span class="hide"><b>SPARROW:</b></span>Part of being your older brother means kicking your butt when you need it.</span>

etcetc <</timed>></p></div>

I’m not sure what I did wrong, but using your code exactly as provided was causing an error. However, I tried the following:

<<script>>State.temporary.scrollFn = window.setInterval(function() {
  var elem = document.getElementById('phone');
  elem.scrollTop = elem.scrollHeight;
}, 100);<</script>>

With your leave passage link:

<<link "Return" "T4INV">><<run clearInterval(State.temporary.scrollFn)>><</link>>

And I’m no longer experiencing errors!