How to position SelectListView inline


I would like to display a SelectListView next to the cursor.

As far as I’ve understood, this is possible by adding the right stylesheet class. There are lots of possibilities in the styleguide, but so far I couldn’t get it to work.

The styleguide offers:

A .popover-list is a .select-list that is meant to popover the code for something like autocomplete.

But with these two attributes, my View isn’t displayed at all. I’m rather sure that this is not a problem with my code. The classes overlay and from-top display the SelectListView just fine.

How do I position a View inline ?
Maybe it’s the way I’m adding the classes ? By using @addClass() in initialize() . But that’s the way it’s done here:

Here’s my code:

{SelectListView,View} = require 'atom'

module.exports =
class MyPackageView extends SelectListView

  initialize: () ->
    atom.workspaceView.command "my-package:toggle", => @toggle()
    @addClass('select-list popover-list') # with overlay and from-top the list is displayed


    console.log("#{item} was selected")

  toggle: ->
    console.log "MyPackageView was toggled!"
    if @hasParent()

  # Tear down any state and detach
  destroy: ->

And here the link to SO:


I found this code:

Which should do the exact thing I’m looking for: Low-Level description/implementation of a popover-list.

I copied the code and am trying to use it like this:

{$, $$, View} = require "atom"

Keys =
  Escape: 27
  Enter: 13
  Tab: 9

module.exports =
class CustomView extends View
  # Tear down any state and detach
  destroy: ->

  toggle: ->
    console.log "CustomView was toggled!"
    if @hasParent()

  maxItems: 10
  @content: ->
    @div class: "select-list popover-list", =>
      @input class: "hidden-input", outlet: "hiddenInput"
      @ol class: "list-group", outlet: "list"

  # Private: Listens to events, delegates them to instance methods
  initialize: ->
    atom.workspaceView.command "custom:toggle", => @toggle()
    # Core events for keyboard handling
    @on "autocomplete-plus:confirm", => @confirmSelection()

    # List mouse events
    @list.on "mousedown", "li", (e) =>

      @selectItemView $("li")

    @list.on "mouseup", "li", (e) =>

      if $("li").hasClass "selected"

  # Private: Selects the previous item view
  selectPreviousItemView: ->
    view = @getSelectedItemView().prev()
    unless view.length
      view = @list.find "li:last"
    @selectItemView view

    return false

  # Private: Selects the next item view
  selectNextItemView: ->
    view = @getSelectedItemView().next()
    unless view.length
      view = @list.find "li:first"
    @selectItemView view

    return false

  # Private: Sets the items, displays the list
  # items - {Array} of items to display
  setItems: (items=[]) ->
    @items = items

  # Private: Unselects all views, selects the given view
  # view - the {jQuery} view to be selected
  selectItemView: (view) ->
    return unless view.length

    @list.find(".selected").removeClass "selected"
    view.addClass "selected"
    @scrollToItemView view

  # Private: Sets the scroll position to match the given view's position
  # view - the {jQuery} view to scroll to
  scrollToItemView: (view) ->
    scrollTop = @list.scrollTop()
    desiredTop = view.position().top + scrollTop
    desiredBottom = desiredTop + view.outerHeight()

    if desiredTop < scrollTop
      @list.scrollTop desiredTop
      @list.scrollBottom desiredBottom

  # Private: Get the currently selected item view
  # Returns the selected {jQuery} view
  getSelectedItemView: ->
    @list.find "li.selected"

  # Private: Get the currently selected item (*not* the view)
  # Returns the selected {Object}
  getSelectedItem: ->
    @getSelectedItemView().data "select-list-item"

  # Private: Confirms the currently selected item or cancels the list view
  # if no item has been selected
  confirmSelection: ->
    item = @getSelectedItem()
    if item?
      @confirmed item

  # Private: Focuses the hidden input, starts listening to keyboard events
  setActive: ->
    @active = true

  # Private: Re-builds the list with the current items
  populateList: ->
    return unless @items?

    for i in [0...Math.min(@items.length, @maxItems)]
      item = @items[i]
      itemView = @viewForItem item
      $(itemView).data "select-list-item", item
      @list.append itemView

    @selectItemView @list.find "li:first"

  # Private: Creates a view for the given item
  # word - the item
  # Returns the {jQuery} view for the item
  viewForItem: ({word}) ->
    $$ ->
      @li =>
        @span word

  # Private: Clears the list, detaches the element
  cancel: ->
    return unless @active

    @active = false

Still, nothing is displayed. The View is just invisible.

The console logs show that the toggle function is called correctly. I’m really sure that the logic / hookup is set up right. But the View doesn’t work. Which is strange, since this code seems to be the official way to do it.

Ironically with overlay and from-top , the View is displayed just fine - still at the top of the editor-pane.

I’ve now created an issue on Github. Usually I would assume that the error is located in my code. But everything I tried changed nothing, even in code copy/pasted from official packages, the styleclasses just don’t work. And it’s not that the View is completely broken, it just can’t be positioned correctly. Here’s the link to the issue: