[autocomplete] twitter bootstrap 3.0 typeahead ajax example

Here is my step by step experience, inspired by typeahead examples, from a Scala/PlayFramework app we are working on.

In a script LearnerNameTypeAhead.coffee (convertible of course to JS) I have:

$ ->
  learners = new Bloodhound(
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace("value")
    queryTokenizer: Bloodhound.tokenizers.whitespace
    remote: "/learner/namelike?nameLikeStr=%QUERY"
  )
  learners.initialize()
  $("#firstName").typeahead 
    minLength: 3
    hint: true
    highlight:true
   ,
    name: "learners"
    displayKey: "value"
    source: learners.ttAdapter()

I included the typeahead bundle and my script on the page, and there is a div around my input field as follows:

<script [email protected]("javascripts/typeahead.bundle.js")></script>
<script [email protected]("javascripts/LearnerNameTypeAhead.js") type="text/javascript" ></script>
<div>
  <input name="firstName" id="firstName" class="typeahead" placeholder="First Name" value="@firstName">
</div>

The result is that for each character typed in the input field after the first minLength (3) characters, the page issues a GET request with a URL looking like /learner/namelike?nameLikeStr= plus the currently typed characters. The server code returns a json array of objects containing fields "id" and "value", for example like this:

[ {
    "id": "109",
    "value": "Graham Jones"
  },
  {
    "id": "5833",
    "value": "Hezekiah Jones"
} ]

For play I need something in the routes file:

GET /learner/namelike controllers.Learners.namesLike(nameLikeStr:String)

And finally, I set some of the styling for the dropdown, etc. in a new typeahead.css file which I included in the page's <head> (or accessible .css)

.tt-dropdown-menu {
  width: 252px;
  margin-top: 12px;
  padding: 8px 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 8px;
     -moz-border-radius: 8px;
          border-radius: 8px;
  -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
     -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
          box-shadow: 0 5px 10px rgba(0,0,0,.2);
}
.typeahead {
  background-color: #fff;
}
.typeahead:focus {
  border: 2px solid #0097cf;
}
.tt-query {
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.tt-hint {
  color: #999
}
.tt-suggestion {
  padding: 3px 20px;
  font-size: 18px;
  line-height: 24px;
}
.tt-suggestion.tt-cursor {
  color: #fff;
  background-color: #0097cf;
}
.tt-suggestion p {
  margin: 0;
}