How scroll a custom gutter view along with the activePaneView?


#1

I’m working on a package where I add a custom view into the active .editor div as another gutter type of view.

My div is inserted as in the snippet below and all looks great except it doesnt scroll when you scroll the content for the editor pane. Only if you mouse over my div can i scroll it, but only it scrolls.

<div class="pane active">
  ...
  <div class="editor">
    <div class="gutter">...</div>
    <div class="MY_CUSTOM_DIV">...</div>
    <div class="scroll-view">...</div>
    <div class="vertical-scrollbar">...</div>
  </div>
</div>

I want my div to act just like the .gutter that contains the line numbers by staying in sync with the content. When scrolling the active editor, i want to keep my custom view at the same offset.

How can I achieve this?

Normally I’d bind to the scroll event of the scrolling container and sync the offset of my element. I’ve tried binding to scroll event on the active editor pages scroll-view but it does not seem to get any callbacks:

var activePane = atom.workspaceView.getActivePaneView();
var focusedEditor = activePane.find('.editor.is-focused');

focusedEditor.find('.scroll-view').on('scroll', function(e) {
  // this callback never gets called
});

Is there another element that is actually getting the scroll events? Something is missing here and I havent found much helpful in the docs.


#2

The gutter is pretty complicated. It doesn’t actually respond to scroll events. Your best bet is to copy how the gutter updates its line numbers. This will get called whenever the EditorView emits the ‘editor:display-updated’ event.


#3

Thanks for the tip. This is the definitely the right way to do it if I want it to feel as much like the real gutter as possible. This takes time though so I haven’t gotten around to it yet.

In the meantime I was able to achieve the desired scrolling effect binding to scroll event on the scrollbar within the focused editor and using its offset.

This breaks when code blocks are folded and new lines are added / removed but its ok for my use case for now.

For the curious, heres what i did:

function matchScrollPosition(view, target) {
  var targetScrollTop = target.scrollTop();
  view.scrollTop(targetScrollTop);
}

var blameView = new BlameListView(viewData);

// insert this into the dom here...

var activePane = atom.workspaceView.getActivePaneView();
var verticalScrollBar = activePane.find('.editor.is-focused .vertical-scrollbar');

// Bind to scroll event on vertical-scrollbar for now to sync up scroll
// position of blame gutter.
verticalScrollBar.on('scroll', function(e) {
  matchScrollPosition(blameView, $(e.target));
});