searchable select: add ajax class

- refactor searchable select
- add partial rerendering
This commit is contained in:
Felix Niklas 2015-08-04 12:43:13 +02:00
parent 9ca8459d19
commit 056ee9906e
4 changed files with 43 additions and 23 deletions

View file

@ -1,16 +1,17 @@
class App.SearchableSelect extends Spine.Controller class App.SearchableSelect extends Spine.Controller
events: events:
'input .js-input': 'filterList' 'input .js-input': 'onInput'
'click .js-value': 'selectItem' 'click .js-option': 'selectItem'
'mouseenter .js-value': 'highlightItem' 'mouseenter .js-option': 'highlightItem'
'shown.bs.dropdown': 'onDropdownShown' 'shown.bs.dropdown': 'onDropdownShown'
'hidden.bs.dropdown': 'onDropdownHidden' 'hidden.bs.dropdown': 'onDropdownHidden'
elements: elements:
'.js-value': 'values' '.js-option': 'option_items'
'.js-input': 'input' '.js-input': 'input'
'.js-shadow': 'shadowInput' '.js-shadow': 'shadowInput'
'.js-optionsList': 'optionsList'
className: 'searchableSelect dropdown dropdown--actions' className: 'searchableSelect dropdown dropdown--actions'
@ -22,12 +23,16 @@ class App.SearchableSelect extends Spine.Controller
@render() @render()
render: -> render: ->
console.log "options", @options
firstSelected = _.find @options.attribute.options, (option) -> option.selected firstSelected = _.find @options.attribute.options, (option) -> option.selected
if firstSelected if firstSelected
@options.attribute.valueName = firstSelected.name @options.attribute.valueName = firstSelected.name
@options.attribute.value = firstSelected.value @options.attribute.value = firstSelected.value
@options.attribute.renderedOptions = App.view('generic/searchable_select_options')
options: @options.attribute.options
@html App.view('generic/searchable_select')( @options.attribute ) @html App.view('generic/searchable_select')( @options.attribute )
@input.on 'keydown', @navigate @input.on 'keydown', @navigate
@ -39,7 +44,7 @@ class App.SearchableSelect extends Spine.Controller
onDropdownHidden: => onDropdownHidden: =>
@input.off 'click', @stopPropagation @input.off 'click', @stopPropagation
@values.removeClass '.is-active' @option_items.removeClass '.is-active'
@isOpen = false @isOpen = false
toggle: => toggle: =>
@ -63,17 +68,17 @@ class App.SearchableSelect extends Spine.Controller
return @toggle() if not @isOpen return @toggle() if not @isOpen
event.preventDefault() event.preventDefault()
visibleValues = @values.not('.is-hidden') visibleOptions = @option_items.not('.is-hidden')
highlightedItem = @values.filter('.is-active') highlightedItem = @option_items.filter('.is-active')
currentPosition = visibleValues.index(highlightedItem) currentPosition = visibleOptions.index(highlightedItem)
currentPosition += direction currentPosition += direction
return if currentPosition < 0 return if currentPosition < 0
return if currentPosition > visibleValues.size() - 1 return if currentPosition > visibleOptions.size() - 1
@values.removeClass('is-active') @option_items.removeClass('is-active')
visibleValues.eq(currentPosition).addClass('is-active') visibleOptions.eq(currentPosition).addClass('is-active')
selectItem: (event) -> selectItem: (event) ->
@input.val event.currentTarget.textContent.trim() @input.val event.currentTarget.textContent.trim()
@ -94,22 +99,22 @@ class App.SearchableSelect extends Spine.Controller
event.preventDefault() event.preventDefault()
@input.val @values.filter('.is-active').text().trim() @input.val @option_items.filter('.is-active').text().trim()
@input.trigger('change') @input.trigger('change')
@shadowInput.val @values.filter('.is-active').attr('data-value') @shadowInput.val @option_items.filter('.is-active').attr('data-value')
@shadowInput.trigger('change') @shadowInput.trigger('change')
@toggle() @toggle()
filterList: (event) => onInput: (event) =>
@toggle() if not @isOpen @toggle() if not @isOpen
query = @input.val() @query = @input.val()
@filterByQuery query @filterByQuery @query
filterByQuery: (query) -> filterByQuery: (query) ->
regex = new RegExp(query.split(' ').join('.*'), 'i') regex = new RegExp(query.split(' ').join('.*'), 'i')
@values @option_items
.addClass 'is-hidden' .addClass 'is-hidden'
.filter -> .filter ->
this.textContent.match(regex) this.textContent.match(regex)
@ -118,8 +123,8 @@ class App.SearchableSelect extends Spine.Controller
@highlightFirst() @highlightFirst()
highlightFirst: -> highlightFirst: ->
@values.removeClass('is-active').not('.is-hidden').first().addClass 'is-active' @option_items.removeClass('is-active').not('.is-hidden').first().addClass 'is-active'
highlightItem: (event) => highlightItem: (event) =>
@values.removeClass('is-active') @option_items.removeClass('is-active')
$(event.currentTarget).addClass('is-active') $(event.currentTarget).addClass('is-active')

View file

@ -0,0 +1,14 @@
class App.SearchableAjaxSelect extends App.SearchableSelect
onInput: (event) =>
super
# send ajax request @query
onAjaxResponse: (data) =>
@optionsList.html App.view('generic/searchable_select_options')
options: data
@refreshElements()
@filterByQuery @query

View file

@ -14,8 +14,6 @@
> >
<svg class="icon-arrow-down"><use xlink:href="#icon-arrow-down" /></svg> <svg class="icon-arrow-down"><use xlink:href="#icon-arrow-down" /></svg>
</div> </div>
<ul class="dropdown-menu dropdown-menu-left" role="menu"> <ul class="dropdown-menu dropdown-menu-left js-optionsList" role="menu">
<% for row in @options: %> <%- @renderedOptions %>
<li role="presentation" class="js-value" data-value="<%= row.value %>"><%= row.name %>
<% end %>
</ul> </ul>

View file

@ -0,0 +1,3 @@
<% for option in @options: %>
<li role="presentation" class="js-option" data-value="<%= option.value %>"><%= option.name %>
<% end %>