You could do this in several ways.
Turbo should fire a turbo:before-fetch-request
and turbo:before-fetch-response
on the document
when lazy loaded frames, or links that trigger a frame reload.
You could do something like:
document.addEventListener("turbo:before-fetch-response", function (e) {
let frame = document.getElementById("messagesFrame");
if (frame.complete) {
frame.scrollTo(0, frame.scrollHeight)
} else {
frame.loaded.then(() => frame.scrollTo(0, frame.scrollHeight))
}
})
Sources:
Turbo events => https://turbo.hotwired.dev/reference/events
Frame.complete and Frame.loaded => https://turbo.hotwired.dev/reference/frames
I suggest the above method because you specified vanilla Javascript. The recommended way for most Turbo related things is to use StimulusJS.
You could write a Stimulus (https://stimulus.hotwired.dev/) controller that you attach to an element in the body that shows inside the TurboFrame, and in the connect
method, do the same.
That way, whenever the content inside the frame is refreshed the Stimulus controller will run, and you don't have to worry about the order of the events being fired.