At CodeMirror: f936a70
I'm seeing an issue where if I set the value of an editor twice and call scrollIntoView I'm not getting the scroll position as I would expect it.
Reduction:
<style>.CodeMirror { height: 5em; } /* 5 lines tall */</style>
<button id="button">Change text and reveal line</button>
<textarea id="code"></textarea>
<script>
// Create editor.
var textarea = document.getElementById('code');
var cm = CodeMirror.fromTextArea(textarea, {lineNumbers: true, lineWrapping:true});
// Create 300 lines.
for (var i=0, lines=[]; i<300; ++i) lines.push(i);
// Set the lines and scroll into view line 251.
document.getElementById('button').addEventListener('click', function() {
cm.setValue("abc");
cm.setValue(lines.join("\n"));
cm.setSelection({line: 250, ch:0}, {line: 250});
cm.scrollIntoView({line: 250, ch:0});
});
</script>
After clicking the button twice the editor is at line 1:

First time clicking the button correctly scrolls to line 251. The second time however it scrolls to line 1. It continues to alternate on future clicks between line 251 and line 1. I would always expect the result to be line 251. Note the selection is still correct even though the line is not visible.
Is it expected that we should call refresh somewhere? If we're in an operation, then a refresh doesn't seem to do anything and the scrollIntoView never works. For example replacing the click handler with:
// Set the lines and scroll into view line 251.
document.getElementById('button').addEventListener('click', function() {
cm.setValue("abc");
cm.operation(function() {
cm.setValue(lines.join("\n"));
cm.refresh();
cm.setSelection({line: 250, ch:0}, {line: 250});
cm.scrollIntoView({line: 250, ch:0});
});
});
Thanks for the minimal reproduction case. Problem was that CodeMirror relied on the asynchronous 'scroll' event to update its understanding of its current scroll position. In sync code like the one you had, it would believe that it was still at the right position when scrollIntoView was called, and not update.
Related discussion thread how to set view stay in current position when cm.doc.setValue().
FWIW, this is how I managed to call setValue and not have any scroll modifications:
// Set the value, but do not scroll to the top.
var scrollInfo = this.codeMirror.getScrollInfo();
this.codeMirror.setValue(value);
this.codeMirror.scrollTo(scrollInfo.left, scrollInfo.top);
I wish there were an options object to setValue, similarly to setSelection, so one could say:
this.codeMirror.setValue(value, {scroll: false});
Most helpful comment
Related discussion thread how to set view stay in current position when cm.doc.setValue().
FWIW, this is how I managed to call
setValueand not have any scroll modifications:I wish there were an options object to
setValue, similarly tosetSelection, so one could say: