I want to scroll to the end ( EditorView.scrollIntoView(tr.state.doc.length, { x: 'start', y: 'end' }) ) when appending to the document, but only if the User hasn’t scrolled somewhere else.
Is there a way to tell in the state/view if the User has scrolled?
Based on my understanding, it seems like maybe I’ll need to do a domEventHandler extension watching scroll ( EditorView.domEventHandlers({ scroll(event, view) { ... }) ) and update a Facet, but I’m hoping there’s something I missed. Some kind of property in the view.
Additionally, is there a way to know if the user is scrolled to the bottom? Not sure how to use the available properties to detect what’s truly visible in the viewport, or if I should use native JS methods on view.scrollDOM.
Thanks, marijn. That’s the route I started going down. Works decently well.
function isElementScrolledToBottom(el, wiggleRoom = 10) {
return el.scrollHeight - el.scrollTop <= el.clientHeight + wiggleRoom;
}
export const scrollViewPlugin = ViewPlugin.fromClass(
class {
scrolledToBottom = true;
programmaticScroll = false;
update(update) {
if (update.docChanged) {
for (let tr of update.transactions) {
for (let e of tr.effects) {
if ( e.is( myCustomEffect ) && this.scrolledToBottom) {
// Add flag that this was a programmatic scroll.
this.programmaticScroll = true;
// Delay by an animation frame to ensure DOM is ready
requestAnimationFrame(() => {
// Scroll to the bottom of the console.
const el = update.view.scrollDOM;
el.scrollTop = el.scrollHeight;
});
}
}
}
}
}
}
},
{
eventHandlers: {
scroll: function (e, view) {
// Ignore programmatic scroll events.
if (this.programmaticScroll) {
this.programmaticScroll = false;
return;
}
this.scrolledToBottom = isElementScrolledToBottom(view.scrollDOM);
}
}
}
);