mirror of
https://github.com/atom/atom.git
synced 2026-02-14 08:35:11 -05:00
Clearing the mini editor when closing is something all sub-classes were already doing so it makes sense to pull it up to the base class as the default cancelled() implementation that can still be overridden if needed.
145 lines
3.6 KiB
CoffeeScript
145 lines
3.6 KiB
CoffeeScript
$ = require 'jquery'
|
|
{ View } = require 'space-pen'
|
|
Editor = require 'editor'
|
|
fuzzyFilter = require 'fuzzy-filter'
|
|
|
|
module.exports =
|
|
class SelectList extends View
|
|
@content: ->
|
|
@div class: @viewClass(), =>
|
|
@subview 'miniEditor', new Editor(mini: true)
|
|
@div class: 'error', outlet: 'error'
|
|
@div class: 'loading', outlet: 'loading'
|
|
@ol outlet: 'list'
|
|
|
|
@viewClass: -> 'select-list'
|
|
|
|
maxItems: Infinity
|
|
scheduleTimeout: null
|
|
inputThrottle: 50
|
|
cancelling: false
|
|
|
|
initialize: ->
|
|
requireStylesheet 'select-list.css'
|
|
|
|
@miniEditor.getBuffer().on 'changed', => @schedulePopulateList()
|
|
@miniEditor.on 'focusout', => @cancel() unless @cancelling
|
|
@on 'core:move-up', => @selectPreviousItem()
|
|
@on 'core:move-down', => @selectNextItem()
|
|
@on 'core:confirm', => @confirmSelection()
|
|
@on 'core:cancel', => @cancel()
|
|
|
|
@list.on 'mousedown', 'li', (e) =>
|
|
@selectItem($(e.target).closest('li'))
|
|
e.preventDefault()
|
|
|
|
@list.on 'mouseup', 'li', (e) =>
|
|
@confirmSelection() if $(e.target).closest('li').hasClass('selected')
|
|
e.preventDefault()
|
|
|
|
schedulePopulateList: ->
|
|
clearTimeout(@scheduleTimeout)
|
|
@scheduleTimeout = setTimeout((=> @populateList()), @inputThrottle)
|
|
|
|
setArray: (@array) ->
|
|
@populateList()
|
|
@setLoading()
|
|
|
|
setError: (message) ->
|
|
if not message or message.length == ""
|
|
@error.text("").hide()
|
|
@removeClass("error")
|
|
else
|
|
@setLoading()
|
|
@error.text(message).show()
|
|
@addClass("error")
|
|
|
|
setLoading: (message) ->
|
|
if not message or message.length == ""
|
|
@loading.text("").hide()
|
|
else
|
|
@setError()
|
|
@loading.text(message).show()
|
|
|
|
populateList: ->
|
|
filterQuery = @miniEditor.getText()
|
|
if filterQuery.length
|
|
filteredArray = fuzzyFilter(@array, filterQuery, key: @filterKey)
|
|
else
|
|
filteredArray = @array
|
|
|
|
@list.empty()
|
|
if filteredArray.length
|
|
@setError(null)
|
|
|
|
for i in [0...Math.min(filteredArray.length, @maxItems)]
|
|
element = filteredArray[i]
|
|
item = @itemForElement(element)
|
|
item.data('select-list-element', element)
|
|
@list.append(item)
|
|
|
|
@selectItem(@list.find('li:first'))
|
|
else
|
|
@setError("No matches found")
|
|
|
|
selectPreviousItem: ->
|
|
item = @getSelectedItem().prev()
|
|
item = @list.find('li:last') unless item.length
|
|
@selectItem(item)
|
|
|
|
selectNextItem: ->
|
|
item = @getSelectedItem().next()
|
|
item = @list.find('li:first') unless item.length
|
|
@selectItem(item)
|
|
|
|
selectItem: (item) ->
|
|
return unless item.length
|
|
@list.find('.selected').removeClass('selected')
|
|
item.addClass 'selected'
|
|
@scrollToItem(item)
|
|
|
|
scrollToItem: (item) ->
|
|
scrollTop = @list.scrollTop()
|
|
desiredTop = item.position().top + scrollTop
|
|
desiredBottom = desiredTop + item.height()
|
|
|
|
if desiredTop < scrollTop
|
|
@list.scrollTop(desiredTop)
|
|
else if desiredBottom > @list.scrollBottom()
|
|
@list.scrollBottom(desiredBottom)
|
|
|
|
getSelectedItem: ->
|
|
@list.find('li.selected')
|
|
|
|
getSelectedElement: ->
|
|
@getSelectedItem().data('select-list-element')
|
|
|
|
confirmSelection: ->
|
|
element = @getSelectedElement()
|
|
if element?
|
|
@confirmed(element)
|
|
else
|
|
@cancel()
|
|
|
|
attach: ->
|
|
@storeFocusedElement()
|
|
|
|
storeFocusedElement: ->
|
|
@previouslyFocusedElement = $(':focus')
|
|
|
|
restoreFocus: ->
|
|
@previouslyFocusedElement?.focus()
|
|
|
|
cancelled: ->
|
|
@miniEditor.setText('')
|
|
|
|
cancel: ->
|
|
@list.empty()
|
|
@cancelling = true
|
|
miniEditorFocused = @miniEditor.isFocused
|
|
@cancelled()
|
|
@detach()
|
|
@restoreFocus() if miniEditorFocused
|
|
@cancelling = false
|
|
clearTimeout(@scheduleTimeout)
|