Skip to content

Instantly share code, notes, and snippets.

@mtrolle
Last active March 24, 2017 11:28
Show Gist options
  • Save mtrolle/5513c8741ce484b2eada7eb7f8e99c14 to your computer and use it in GitHub Desktop.
Save mtrolle/5513c8741ce484b2eada7eb7f8e99c14 to your computer and use it in GitHub Desktop.
# Will apply a jQuery Autocomplete on an input field, given input field has data-autocomplete set to a json object
# with keys:
# - path Being path to autocomplete source, taking ?term=query as search argument
# - target Target field name, e.g. 'id'. Will create a hidden target field where name of autocomplete input field is
# replaced with this `target` name. So if input is autocomplete_name target field will be autocomplete_id.
# It will apply the object value with key of same value as target. So in above example key will be id.
# - params Allows you to append additional params to the final source URL. Formatted key:value;key:value;key:value
# For `value` we'll lookup a input field with the `value` as id and take it's value.
$(document).on 'focus', 'input[data-autocomplete]', ->
settings = $(this).data('autocomplete')
# Normalizing settings['path'] if any params are given
if settings['params']
params = {}
for param in settings['params'].split(';')
argument = param.split(':')
params[argument[0]] = $("##{argument[1]}").val()
real_path = "#{settings['path']}?#{$.param(params)}"
if $(this).hasClass('ui-autocomplete-input')
# Updating source path if params is present (as params might have changed since initializing autocomplete)
if real_path
$(this).autocomplete('option', 'source', real_path)
else
if settings['target']
target_id = $(this).attr('id').replace(/$/, "_#{settings['target']}")
target_name = $(this).attr('name').replace(/\]$/, "_#{settings['target']}]")
$(this).before("<input type=\"hidden\" name=\"#{target_name}\" id=\"#{target_id}\">")
$(this).data('autocomplete-target-id', target_id)
$(this).autocomplete {
minLength: 1,
source: if real_path then real_path else settings['path']
focus: ->
false
select: (event, ui) ->
settings = $(this).data('autocomplete')
if settings['target']
$("##{$(this).data('autocomplete-target-id')}").val(ui.item[settings['target']])
if settings['value']
$(this).val(ui.item[settings['value']])
false
change: ->
if !$(this).val() && $(this).data('autocomplete-target-id')
$("##{$(this).data('autocomplete-target-id')}").val('')
}
if settings['value']
$(this).autocomplete( "instance" )._renderItem = ( ul, item ) ->
$( "<li>" )
.append( "<a>#{item[settings['value']]}</a>" )
.appendTo( ul )
@mtrolle
Copy link
Author

mtrolle commented Mar 23, 2017

In ERB you can now
<%= f.text_field :make, data: {autocomplete: {path: app_autocomplete_makes_path, value: :name, target: :id}} %>
to get an input field that will autocomplete from app_autocomplete_makes_path, show the name field as value and append the id to a new hidden field.

Or even:
<%= f.text_field :model, data: {autocomplete: {path: app_autocomplete_models_path, value: :name, target: :id, params: "make_id:comparison_make_id"}} %>
which will do same as above, but also add ?make_id=[selected make from above autocomplete] as param to the app_autocomplete_models_path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment