Event to listen for code folding/unfolding


#1

I’m trying to figure out the best event to listen for when code is folded or unfolded. I’ve tried onDid[Add/Remove]Decoration, onDidUpdateMarkers, and onDidChange filtering for events I care about but all of these methods are too noisy and lead to noticeable editor performance degradation. Any suggestions?


Listening for click event on gutter row
#2

I don’t know if this works at all, but maybe it’s a hint in the right direction?

$('atom-text-editor::shadow').on('click', '.gutter .line-number.foldable .icon-right', function(event) {
  // do something
});

Other than that, there are a few “fold” commands that you can listen to:

atom.commands.add('atom-workspace', 'editor:fold-all', function() {
  // do something
});

etc.


#3

I tried the following to no avail

$('atom-text-editor::shadow').on 'click', '.gutter .line-number.foldable .icon-right', (event) ->
  console.log 'clicked 1'

editor = atom.workspace.getActiveTextEditor()
@editorElement = atom.views.getView editor
$(@editorElement).on 'click', '.gutter .line-number.foldable .icon-right', (event) ->
  console.log 'clicked 2'

I feel like there’s probably some complication here due to the shadow DOM but I’m not familiar enough with DOM, let alone shadow DOM, to understand how to work around it.

Edit:

Actually, yeah. This works

$(@editorElement).on 'click', (event) ->
  console.log 'clicked 3'

but this doesn’t

$(@editorElement).on 'click', '.gutter', (event) ->
  console.log 'clicked 3'

I’m guessing due to shadow DOM something or other. The gutter lives inside an element with the class editor--private, not sure what that means.


#4

Maybe if you try $('atom-text-editor::shadow .gutter').on('click', '.line-number.foldable', function() { ... })? Works fine for me :slight_smile: The problem was that you can’t select a shadowRoot with jquery… But you can select stuff inside it!


#5

Got it!

@editorElement = atom.views.getView editor
gutter = @editorElement.querySelector('::shadow .gutter')
$(gutter).on 'click', '.line-number.foldable .icon-right', (event) ->
  console.log 'clicked'

Also, for anyone else who finds this thread, here’s the full compliment of fold events you’d need to subscribe to to get things done.

@subs = new SubAtom
@subs.add atom.commands.add 'atom-text-editor',
  'editor:fold-all': -> doSomething()
  'editor:unfold-all': -> doSomething()
  'editor:fold-current-row': -> doSomething()
  'editor:unfold-current-row': -> doSomething()
  'editor:fold-selection': -> doSomething()
  'editor:fold-at-indent-level-1': -> doSomething()
  'editor:fold-at-indent-level-2': -> doSomething()
  'editor:fold-at-indent-level-3': -> doSomething()
  'editor:fold-at-indent-level-4': -> doSomething()
  'editor:fold-at-indent-level-5': -> doSomething()
  'editor:fold-at-indent-level-6': -> doSomething()
  'editor:fold-at-indent-level-7': -> doSomething()
  'editor:fold-at-indent-level-8': -> doSomething()
  'editor:fold-at-indent-level-9': -> doSomething()

#6

The above code still works, but the ::shadow pseudo-element is now deprecated so this will have to change in the future. Anyone got any ideas how I can avoid this line of code?

gutter = @editorElement.querySelector('::shadow .gutter')

It’d be nice if the text editor supported something like onDidClickGutter because then I could just use that.


#7

Yes, this is an item of concern for the team. Nothing needs to be done now and I’m sure whatever strategy is chosen will be communicated far and wide since this will be a fairly impactful change.


#8

You can call querySelector on the shadowRoot of @editorElement to avoid the ::shadow selector:

@editorElement.shadowRoot.querySelector('.gutter')