Commit d38ef7b5 authored by Alfredo Sumaran's avatar Alfredo Sumaran

Use new dropdown class for search suggestions

parent dce5e9ce
......@@ -4,6 +4,7 @@ class GitLabDropdownFilter
constructor: (@dropdown, @options) ->
{
@input
@filterInputBlur = true
} = @options
# Key events
......@@ -19,7 +20,7 @@ class GitLabDropdownFilter
blur_field = @shouldBlur e.keyCode
search_text = @input.val()
if blur_field
if blur_field && @filterInputBlur
@input.blur()
if @options.remote
......@@ -89,6 +90,7 @@ class GitLabDropdown
# If no input is passed create a default one
@filterInput = @$(FILTER_INPUT)
@highlight = false
@filterInputBlur = true
} = @options
self = @
......@@ -119,6 +121,7 @@ class GitLabDropdown
# Init filiterable
if @options.filterable
@filter = new GitLabDropdownFilter @dropdown,
filterInputBlur: @filterInputBlur
input: @filterInput
remote: @options.filterRemote
query: @options.data
......
class @SearchAutocomplete
KEYCODE =
ESCAPE: 27
BACKSPACE: 8
TAB: 9
ENTER: 13
constructor: (opts = {}) ->
{
@wrap = $('.search')
@optsEl = @wrap.find('.search-autocomplete-opts')
@autocompletePath = @optsEl.data('autocomplete-path')
@projectId = @optsEl.data('autocomplete-project-id') || ''
@projectRef = @optsEl.data('autocomplete-project-ref') || ''
} = opts
@keyCode =
ESCAPE: 27
BACKSPACE: 8
TAB: 9
ENTER: 13
# Dropdown Element
@dropdown = @wrap.find('.dropdown')
@locationBadgeEl = @$('.search-location-badge')
@locationText = @$('.location-text')
@scopeInputEl = @$('#scope')
@searchInput = @$('.search-input')
@projectInputEl = @$('#search_project_id')
@groupInputEl = @$('#group_id')
......@@ -25,9 +32,7 @@ class @SearchAutocomplete
@saveOriginalState()
# If there's no location badge
if !@locationBadgeEl.children().length
@createAutocomplete()
@searchInput.addClass('disabled')
@bindEvents()
......@@ -37,20 +42,6 @@ class @SearchAutocomplete
saveOriginalState: ->
@originalState = @serializeState()
restoreOriginalState: ->
inputs = Object.keys @originalState
for input in inputs
@$("##{input}").val(@originalState[input])
if @originalState._location is ''
@locationBadgeEl.html('')
else
@addLocationBadge(
value: @originalState._location
)
serializeState: ->
{
# Search Criteria
......@@ -63,70 +54,85 @@ class @SearchAutocomplete
_location: $.trim(@locationText.text())
}
createAutocomplete: ->
@query = "?project_id=" + @projectId + "&project_ref=" + @projectRef
@searchInput.catcomplete
appendTo: 'form.navbar-form'
source: @autocompletePath + @query
minLength: 1
maxShowItems: 15
position:
# { my: "left top", at: "left bottom", collision: "none" }
my: "left-10 top+9"
at: "left bottom"
collision: "none"
close: (e) ->
e.preventDefault()
select: (event, ui) =>
# Pressing enter choses an alternative
if event.keyCode is @keyCode.ENTER
@goToResult(ui.item)
else
# Pressing tab sets the location
if event.keyCode is @keyCode.TAB and ui.item.location?
@setLocationBadge(ui.item)
@searchInput
.val('') # remove selected value from input
.focus()
else
# If option is not a location go to page
@goToResult(ui.item)
# Return false to avoid focus on the next element
return false
@autocomplete = @searchInput.data 'customCatcomplete'
bindEvents: ->
@searchInput.on 'keydown', @onSearchInputKeyDown
@searchInput.on 'focus', @onSearchInputFocus
@searchInput.on 'blur', @onSearchInputBlur
@wrap.on 'click', '.remove-badge', @onRemoveLocationBadgeClick
onRemoveLocationBadgeClick: (e) =>
e.preventDefault()
@removeLocationBadge()
@searchInput.focus()
enableAutocomplete: ->
self = @
@query = "?project_id=" + @projectId + "&project_ref=" + @projectRef
dropdownMenu = self.dropdown.find('.dropdown-menu')
@searchInput.glDropdown(
filterInputBlur: false
filterable: true
filterRemote: true
highlight: true
filterInput: 'input#search'
search:
fields: ['text']
data: (term, callback) ->
$.ajax
url: self.autocompletePath + self.query
data:
term: term
beforeSend: ->
# dropdownMenu.addClass 'is-loading'
success: (response) ->
data = []
# Save groups ordering according to server response
groupNames = _.unique(_.pluck(response, 'category'))
# Group results by category name
groups = _.groupBy response, (item) ->
item.category
# List results
for groupName in groupNames
# Add group header before list each group
data.push
header: groupName
# List group
for item in groups[groupName]
data.push
text: item.label
url: item.url
callback(data)
complete: ->
# dropdownMenu.removeClass 'is-loading'
)
@dropdown.addClass('open')
@searchInput.removeClass('disabled')
@autocomplete = true;
onDropdownOpen: (e) =>
@dropdown.dropdown('toggle')
onSearchInputKeyDown: (e) =>
# Remove tag when pressing backspace and input search is empty
if e.keyCode is @keyCode.BACKSPACE and e.currentTarget.value is ''
if e.keyCode is KEYCODE.BACKSPACE and e.currentTarget.value is ''
@removeLocationBadge()
# @destroyAutocomplete()
@searchInput.focus()
else if e.keyCode is @keyCode.ESCAPE
else if e.keyCode is KEYCODE.ESCAPE
@searchInput.val('')
@restoreOriginalState()
else
# Create new autocomplete if hasn't been created yet and there's no badge
# Create new autocomplete if it hasn't been created yet and there's no badge
if @autocomplete is undefined
if !@locationBadgeEl.children().length
@createAutocomplete()
if !@badgePresent()
@enableAutocomplete()
else
# There's a badge
if @locationBadgeEl.children().length
@destroyAutocomplete()
if @badgePresent()
@disableAutocomplete()
onSearchInputFocus: =>
@wrap.addClass('search-active')
......@@ -135,7 +141,8 @@ class @SearchAutocomplete
@wrap.removeClass('search-active')
# If input is blank then restore state
@restoreOriginalState() if @searchInput.val() is ''
if @searchInput.val() is ''
@restoreOriginalState()
addLocationBadge: (item) ->
category = if item.category? then "#{item.category}: " else ''
......@@ -147,26 +154,28 @@ class @SearchAutocomplete
</span>"
@locationBadgeEl.html(html)
setLocationBadge: (item) ->
@addLocationBadge(item)
restoreOriginalState: ->
inputs = Object.keys @originalState
# Reset input states
@resetSearchState()
for input in inputs
@$("##{input}").val(@originalState[input])
switch item.location
when 'projects'
@projectInputEl.val(item.id)
# @searchCodeInputEl.val('true') # TODO: always true for projects?
# @repositoryInputEl.val('master') # TODO: always master?
when 'groups'
@groupInputEl.val(item.id)
if @originalState._location is ''
@locationBadgeEl.html('')
else
@addLocationBadge(
value: @originalState._location
)
removeLocationBadge: ->
@locationBadgeEl.empty()
@dropdown.removeClass 'open'
# Reset state
@resetSearchState()
# Only add class if there's a badge
if @badgePresent()
@searchInput.addClass 'disabled'
badgePresent: ->
@locationBadgeEl.children().length
resetSearchState: ->
# Remove scope
......@@ -184,10 +193,13 @@ class @SearchAutocomplete
# Remove repository ref
@repositoryInputEl.val('')
goToResult: (result) ->
location.href = result.url
removeLocationBadge: ->
@locationBadgeEl.empty()
# Reset state
@resetSearchState()
destroyAutocomplete: ->
@autocomplete.destroy() if @autocomplete isnt undefined
@searchInput.attr('autocomplete', 'off')
disableAutocomplete: ->
if @autocomplete isnt undefined
@searchInput.addClass('disabled')
@autocomplete = undefined
......@@ -49,12 +49,6 @@
margin: 0;
}
}
.ui-autocomplete-category {
text-transform: uppercase;
font-size: 11px;
color: #7f8fa4;
}
}
.ui-state-default {
......
......@@ -21,7 +21,6 @@
}
}
.search {
margin-right: 10px;
margin-left: 10px;
......@@ -51,7 +50,6 @@
padding: 4px;
width: 350px;
line-height: 24px;
overflow: hidden;
}
.location-text {
......@@ -69,7 +67,7 @@
padding: 0;
margin-left: 5px;
line-height: 25px;
width: 100%;
width: 98%;
}
.location-badge {
......@@ -89,7 +87,7 @@
}
.search-location-badge, .search-input-wrap {
// Fallback if flex is not supported
// Fallback if flexbox is not supported
display: inline-block;
}
......@@ -103,6 +101,7 @@
position: absolute;
right: 5px;
color: #E7E9ED;
top: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
......@@ -114,9 +113,9 @@
}
}
.ui-autocomplete-loading + .search-icon {
@extend .fa-spinner;
@extend .fa-spin;
.dropdown-header {
text-transform: uppercase;
font-size: 11px;
}
}
}
......@@ -4,7 +4,11 @@
.search-location-badge
= render 'shared/location_badge'
.search-input-wrap
= search_field_tag "search", nil, placeholder: 'Search', class: "search-input", spellcheck: false, tabindex: "1", autocomplete: 'off'
.dropdown{ data: {url: search_autocomplete_path } }
= search_field_tag "search", nil, placeholder: 'Search', class: "search-input dropdown-menu-toggle", spellcheck: false, tabindex: "1", autocomplete: 'off', data: { toggle: 'dropdown' }
.dropdown-menu.dropdown-select
= dropdown_content
= dropdown_loading
%i.search-icon
= hidden_field_tag :group_id, @group.try(:id)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment