searchableSelect: add autocomplete

This commit is contained in:
Felix Niklas 2015-08-04 17:43:06 +02:00
parent 2cea7d804b
commit e7f4f189e0
3 changed files with 64 additions and 7 deletions

View file

@ -2,6 +2,7 @@ class App.SearchableSelect extends Spine.Controller
events: events:
'input .js-input': 'onInput' 'input .js-input': 'onInput'
'blur .js-input': 'onBlur'
'click .js-option': 'selectItem' 'click .js-option': 'selectItem'
'mouseenter .js-option': 'highlightItem' 'mouseenter .js-option': 'highlightItem'
'shown.bs.dropdown': 'onDropdownShown' 'shown.bs.dropdown': 'onDropdownShown'
@ -12,6 +13,8 @@ class App.SearchableSelect extends Spine.Controller
'.js-input': 'input' '.js-input': 'input'
'.js-shadow': 'shadowInput' '.js-shadow': 'shadowInput'
'.js-optionsList': 'optionsList' '.js-optionsList': 'optionsList'
'.js-autocomplete-invisible': 'invisiblePart'
'.js-autocomplete-visible': 'visiblePart'
className: 'searchableSelect dropdown dropdown--actions' className: 'searchableSelect dropdown dropdown--actions'
@ -79,6 +82,22 @@ class App.SearchableSelect extends Spine.Controller
@option_items.removeClass('is-active') @option_items.removeClass('is-active')
visibleOptions.eq(currentPosition).addClass('is-active') visibleOptions.eq(currentPosition).addClass('is-active')
@clearAutocomplete()
autocomplete: (text) ->
startIndex = text.indexOf(@query)
if !@query or startIndex != 0
return @clearAutocomplete()
console.log "startIndex", startIndex
@invisiblePart.text(@query)
@visiblePart.text(text.slice(@query.length))
clearAutocomplete: ->
@visiblePart.text('')
@invisiblePart.text('')
selectItem: (event) -> selectItem: (event) ->
@input.val event.currentTarget.textContent.trim() @input.val event.currentTarget.textContent.trim()
@ -91,6 +110,8 @@ class App.SearchableSelect extends Spine.Controller
event.preventDefault() event.preventDefault()
onEnter: (event) -> onEnter: (event) ->
@clearAutocomplete()
if not @isOpen if not @isOpen
if @shadowInput.val() is '' if @shadowInput.val() is ''
event.preventDefault() event.preventDefault()
@ -105,6 +126,9 @@ class App.SearchableSelect extends Spine.Controller
@shadowInput.trigger('change') @shadowInput.trigger('change')
@toggle() @toggle()
onBlur: =>
@clearAutocomplete()
onInput: (event) => onInput: (event) =>
@toggle() if not @isOpen @toggle() if not @isOpen
@ -123,7 +147,9 @@ class App.SearchableSelect extends Spine.Controller
@highlightFirst() @highlightFirst()
highlightFirst: -> highlightFirst: ->
@option_items.removeClass('is-active').not('.is-hidden').first().addClass 'is-active' first = @option_items.removeClass('is-active').not('.is-hidden').first()
first.addClass 'is-active'
@autocomplete first.text()
highlightItem: (event) => highlightItem: (event) =>
@option_items.removeClass('is-active') @option_items.removeClass('is-active')

View file

@ -1,9 +1,4 @@
<div class="dropdown-toggle" data-toggle="dropdown"> <div class="dropdown-toggle" data-toggle="dropdown">
<input
class="form-control js-input<%= " #{ @class }" if @class %>"
placeholder="<%= @placeholder %>"
value="<%= @valueName %>"
>
<input <input
class="searchableSelect-shadow form-control js-shadow" class="searchableSelect-shadow form-control js-shadow"
id="<%= @id %>" id="<%= @id %>"
@ -12,6 +7,12 @@
<%= @autofocus %> <%= @autofocus %>
value="<%= @value %>" value="<%= @value %>"
> >
<div class="searchableSelect-autocomplete"><span class="searchableSelect-autocomplete-invisible js-autocomplete-invisible"></span><span class="searchableSelect-autocomplete-visible js-autocomplete-visible"></span></div>
<input
class="searchableSelect-main form-control js-input<%= " #{ @class }" if @class %>"
placeholder="<%= @placeholder %>"
value="<%= @valueName %>"
>
<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 class="small loading icon"></div> <div class="small loading icon"></div>
</div> </div>

View file

@ -5661,8 +5661,19 @@ output {
padding-right: 37px; padding-right: 37px;
} }
.searchableSelect-main {
background: none;
position: relative;
}
.searchableSelect-shadow { .searchableSelect-shadow {
display: none; pointer-events: none;
color: transparent;
position: absolute;
left: 0;
top: 0;
right: 0;
border: none;
} }
&.dropdown li:hover:not(.is-active) { &.dropdown li:hover:not(.is-active) {
@ -5677,6 +5688,25 @@ output {
box-shadow: 0 1px rgba(255,255,255,.13) inset; box-shadow: 0 1px rgba(255,255,255,.13) inset;
} }
.searchableSelect-autocomplete {
position: absolute;
left: 13px;
top: 11px;
right: 37px;
white-space: nowrap;
overflow: hidden;
pointer-events: none;
}
.searchableSelect-autocomplete-invisible {
color: transparent;
}
.searchableSelect-autocomplete-visible {
color: hsl(0,0%,33%);
background: hsl(201,61%,90%);
}
.loading.icon { .loading.icon {
position: absolute; position: absolute;
right: 11px; right: 11px;