is a Phoenix form helper that utilizes Lea Verou's autocomplete / autosuggest / typeahead / inputsearch Awesomplete widget.

It comes with an AwesompleteUtil javascript library which adds the following features:

  • Dynamic remote data loading; based on what is typed-in it performs an ajax lookup.
  • Allow HTML markup in the shown items. Show value with description. Optionally search in the description text.
  • Show when there is an exact match.
  • Show when there isn't a match.
  • When there is an exact match show related data (supplied in the remote data) in other parts of the page.
  • Select the highlighted item when the tab key is used.

Examples

iTunes artist search
Example demonstrates:
  • Dynamic data loading.
  • Custom search filter.
  • Custom text highlighter.
Obviously we cannot load all artists known by iTunes in the browsers memory, so that's why we use here dynamic data loading. The search starts if 3 characters are entered.
Enter an artist name:
The standard supplied 'starts-with' and 'contains' filters don't exactly match with how iTunes searches. iTunes searches words, you can search for 'Michael Jackson' or 'Jackson Michael' and get the same results. Thats why a custom filter called 'filterWords' is used that filters on the words entered. To highlight the words in the list of suggestions a custom function called 'itemWords' is used.

Javascript

Below the Awesomplete widget is created with the filter and item functions defined above. A limit of 15 is specified; if 15 or more results are returned by the server the code assumes that there are more results, so it will re-query if more characters are typed to get more refined results.

EEx

<%= awesomplete(
  :user,
  :artist1,
  [       # input_text options
    class: "form-control"
  ],                                                                                                                    
  %{                                                                                                                    
    url:    "https://itunes.apple.com/search?entity=musicArtist&attribute=artistTerm&media=music&limit=15&country=gb&sort=artistTerm&term=",
    limit: 15,
    filter: "filterWords",  # javascript functions must be double quoted
    item: "itemWords",
    value: "artistName"
  }
) %>

show/hide generated code

Generated HTML

<input class="form-control" id="user_artist1" name="user[artist1]" type="text" />

Generated javascript

iTunes track search
Example demonstrates:
  • Dynamic data loading.
  • Show related data of selected item.
Enter a song title:
album image
The creation of the Awesomplete object below is almost the same as in the 'iTunes artist search' example.

EEx

<%= copy_to_id(:user, :track1, "collectionName", "#awe-track-album") %>
<%= copy_to_id(:user, :track1, "artistName", "#awe-track-artists") %>
<%= copy_to_id(:user, :track1, "artworkUrl100", "#awe-track-album-img") %>
<%= awesomplete(
 :user,
 :track1,
 [       # input_text options
  class: "form-control",
  autocomplete: "off"
 ],
 %{
    url: "https://itunes.apple.com/search?entity=song&attribute=songTerm&media=music&limit=10&country=gb&sort=songTerm&term=",
    limit: 10,
    maxItems: 10,
    minChars: 4,
    value: "trackName",
    descr: "collectionName",
    filter: "filterWords",
    item: "itemWords"
  }
) %>
Unfortunetly we cannot instruct to iTunes to sort on song title length. If you search for songs with only one or two words, it might be that the desired song is not in the first 10 shown results.

show/hide generated code

Generated HTML

<input id="user_track1" class="form-control" autocomplete="off" 
     name="user[track1]" type="text" />

Generated javascript

Combobox with countries
Example demonstrates:
  • Combobox.
  • Use remote service which returns everything; load all.
Add a combobox button after the awesomplete control:

HTML

<span class="input-group-btn">
   <button class="dropdown-btn" id="awe_btn_user_combocountry" type="button">
      <span class="caret"></span>
   </button>
</span>
The combobox is useful when there are only a few items in the list, or to give the user some examples of expected input. Here we use maxItems:8, so when the combobox is opened, only the first 8 countries are shown. The shortest country names are shown first.

EEx

<%= awesomplete(
  :user,
  :combocountry,
  [       # input_text options
    class: "form-control"
  ],                                                                                                                    
  %{                                                                                                                    
    url: "https://restcountries.eu/rest/v1/all",
    loadall: true,
    prepop: true,
    minChars: 1,
    maxItems: 8,
    value: "name",
    combobox: true
  }
) %>
The prepop:true makes sure that the countries are loaded during page load. The combobox:true will open/close the list when the button is pushed, assuming the id of the button is 'awe_btn_' + id of input-text. Instead of true/false you can also supply the id of the button with the combobox property.

show/hide generated code

Generated HTML

<input class="form-control" id="user_combocountry" name="user[combocountry]" type="text">

Generated javascript

Connect as user to host
Example demonstrates:
  • Type user name and get suggestions for hostnames; autocomplete after a certain character.
  • Show descriptions in the suggestion list.
  • Load suggestions from static json file.
Enter for example 'root@192.168.1.1'

EEx

<%= awesomplete(
 :user,
 :host1,
 [
  class: "form-control"
 ],
 %{
    url:    "/js/host.json",
    loadall: true,
    filter: "Awesomplete.FILTER_STARTSWITH",
    value: "value",
    descr: "label",
    data:   "function (data, input) { var before = (input.slice(0, input.indexOf('@')) + '@').trim(); return {label: before + data.label, value: before + data.value}; }"
  }
) %>

show/hide generated code

Generated HTML

<input id="user_host" class="form-control" 
     name="user[host]" type="text" />

Generated javascript

Country iso code
Example demonstrates:
  • Use remote service that doesn't return a list but a single entry to verify input.
  • Show related data if entry found.
  • Handle HTTP 404 status with custom ajax function.
Enter for example 'usa'
The remote service returns a HTTP status 404 if the searched value is not found. The default ajax function only processes responses with HTTP OK status 200. The ajax404 function below replaces the onload function to set the empty list if a 404 is received.

Javascript

This is actually not an autocomplete, but it does verify the input.

EEx

<%= awesomplete(
 :user,
 :country_iso,
 [
    class: "form-control",
    autocomplete: "off"
 ],
 %{
    url: "https://restcountries.eu/rest/v1/alpha/",
    value: "alpha3Code",
    limit: 0,
    minChars: 3,
    maxItems: 0,
    filter: "Awesomplete.FILTER_STARTSWITH",
    ajax: ajax404
 }
) %>
A limit:1 tells that not more than 1 result is expected, so the json service doesn't have to return an array. With limit:0 it will always re-query if more characters are typed.

show/hide generated code

Generated HTML

<input id="user_country_iso" class="form-control" autocomplete="off"
     name="user[iso-country]" type="text" />
<span  id="awe-country-name"></span>

Generated javascript

Colors
Example demonstrates:
  • Suggestion list with value and label as part of page source.
  • Label with HTML markup.
  • Show related data of initial/autofill value; Prepopulation event during page load
Enter a color:
Input control:

EEx

<%= text_input(:user, :color, [value: "purple" class: "form-control"]) %>
<div><span id="awe-color-result"></span> &#x21B2;</div>
<%= copy_to_id(:user, :color, "label", "#awe-color-result") %> 
<%= awesomplete_script(
 :user, 
 :color, 
 %{ 
    minChars: 1, 
    filter: "AwesompleteUtil.filterContains",
    list: "[
           { label: \"<b style='color:black'>black</b>\",   value: 'black' },
           { label: \"<b style='color:blue'>blue</b>\",     value: 'blue'  },
           { label: \"<b style='color:brown'>brown</b>\",   value: 'brown' },
           { label: \"<b style='color:green'>green</b>\",   value: 'green' },
           { label: \"<b style='color:orange'>orange</b>\", value: 'orange'},
           { label: \"<b style='color:pink'>pink</b>\",     value: 'pink'  },
           { label: \"<b style='color:purple'>purple</b>\", value: 'purple'},
           { label: \"<b style='color:red'>red</b>\",       value: 'red'   },
           { label: \"<b style='color:yellow'>yellow</b>\", value: 'yellow'}
    ]"
  }
) %>
Notice the prepop property and the startCopy function call. The initial/autofilled value of input-control triggers the copy action, and the label is copied to the span-tag with id 'awe-color-result' during page load. The order of the HTML elements and the inline script is important here. The startCopy function must be called before the startAwesomplete function, because the latter can immediately fire the 'awesomplete-prepop' event which should be handled by the former. The startCopy inline script should preferable be placed after the HTML element which is the target. If you do, it only has to lookup the target element once, but if you don't do this it will lookup the target element with each event.

If you use remote data loading and combine prepop:true with loadall:true the remote call will happen during page load. If prepop:false, the loadall will be done lazely, e.g. if the user makes changes and the input size >= minChars.

show/hide generated code

HTML

<input id="user_color" class="form-control" 
     name="user[color]" type="text" value="purple" />
<div><span id="awe-color-result"></span> &#x21B2;</div>

Generated javascript

Country capitals
Example demonstrates:
  • One remote call (load all) resulting in one response list shared by multiple controls.
  • Copy related data of selected item to other input field, in two directions!
Enter either country or capital, and look what happens in the other field.

EEx

<%= copy_to_field(:user, :country, "capital", :user, :capital) %>
<%= copy_to_field(:user, :capital, "name", :user, :country) %>
<%= label(:user, :country, "Country", class: "control-label col-sm-2") %>
<div class="col-sm-4">
  <%= awesomplete(:user, :country, 
      [class: "form-control",
       autocomplete: "off"
      ], 
      [ 
        assign: true,
        minChars: 1, 
        maxItems: 7, 
        value: "name" 
      ]) %>
</div>
<%= label(:user, :capital, "Capital", class: "control-label col-sm-2") %>
<div class="col-sm-4">
  <%= awesomplete(:user, :capital,
      [class: "form-control",
       autocomplete: "off"
      ], 
      [ 
        assign: true,
        minChars: 1, 
        maxItems: 7, 
        value: "capital" 
      ]) %>
</div>

show/hide generated code

Generated HTML

<input id="user_country" class="form-control" name="user[country]" autocomplete="off" type="text" />
<input id="user_capital" class="form-control" name="user[capital]" autocomplete="off" type="text" />

Generated javascript

The script below loads all countries and fills both Awesomplete objects with the result.

Javascript

Seafood toppings
Example demonstrates:
  • Data list in page source.
  • Select multiple items.
Enter for example 'Crayfish, Oysters'
Notice that you can enter multiple toppings, seperated by , or ;

EEx

<%= awesomplete(
 :user,
 :seafood,
 [
    class: "form-control",
   "data-list": "Anchovies, Cajun Prawn, Crayfish, Lobster, Oysters, Prawns, Salmon, Shrimps, Smoked Salmon, Squid, Tuna, Whitebait"
 ],
 %{
    minChars: 1,
    multiple: ",;"
  }
) %>

show/hide generated code

Generated HTML

<input id="user_seafood" class="form-control" 
     name="user[seafood]" type="text" 
  data-list="Anchovies, Cajun Prawn, Crayfish, Lobster,
             Oysters, Prawns, Salmon, Shrimps,
             Smoked Salmon, Squid, Tuna, Whitebait">

Generated javascript

The regular expressions are used to extract the last part of the input from the rest.
Email address
Example demonstrates:
  • In the shown suggestions the email address is shown below the name. The value contains both.
  • Multiple input values.
Enter an email address (they are all from acme.com):
Below the Awesomplete object and input control created

EEx

<%= awesomplete(
  :user,
  :multimail,
  [
   class: "form-control"
  ],
  %{
     url:    "https://uinames.com/api/?amount=100",
     convertResponse: "uinames2contacts",
     loadall : true,
     minChars: 1,
     maxItems: 7,
     multiple: ";,",
     value:  "value",
     label:  "name",
     descr:  "email",
     item:   "AwesompleteUtil.itemMarkAll"
   }
 ) %>
In this example the 'value' field contains both name (label) and email address (descr). By default the description is not highlighted. The itemMarkAll function above highlights all matching text in the suggestion list, including the description. Try for example to search on '@acme.com' to see what it highlights with or without this function.
This examples uses random names from https://uinames.com/api/. The uinames2contacts function below constructs email addresses and a value that contains both name and email address.

Javascript

show/hide generated code

Generated HTML

<input id="user_multimail" class="form-control"
     name="user[multimail]" type="text" />

Generated javascript

Installation

API

License: MIT