Suche mit Vorschlägen und Autovervollständigung

Bei meiner Web App “FHTW LV-Plan” konnte man seit Anfang an nach dem Stundenplan anderer Leute suchen – wenn man den FH-Usernamen der Person auswendig gekannt hat. Das war natürlich unglaublich umständlich. Dafür habe ich eine Lösung gesucht und mit typeahead.js von Twitter auch gefunden. Hier zeige ich euch wie das funktioniert.

Vorraussetzung dafür war natürlich, dass die FH Technikum Wien einen Service zur Verfügung stellt, mit welchem man nach Namen und Usernamen suchen kann. Glücklicherweise stellt das CIS diese Funktion sogar als REST-API mit JSON Antwort zur Verfügung.

https://cis.technikum-wien.at/cis/private/lvplan/lvplan_autocomplete.php?autocomplete=benutzer&term=Berne

[{"vorname":"Daniel","nachname":"Bernegger","uid":"ic15m001","mitarbeiter_uid":""}]

Genau das was ich brauche! Großartig, nun also zum Suchfeld mit Vorschlägen.

Twitter hat für typeahead.js eine tolle Seite mit Beispielen, an welchen ich mich orientiert habe. Als erstes muss man natürlich die notwendigen JavaScript und CSS Dateien verlinken.

<script src="Scripts/handlebars.min.js" />
<script src="Scripts/typeahead.jquery.min.js"/>
<script src="Scripts/bloodhound.min.js"/>
<link rel="stylesheet" type="text/css" src="Content/typeAhead.css" />

Das hier angegebene CSS File kam leider nicht mit dem NuGet Paket von typeahead.js mit, ihr findet einen Download link dazu ganz unten.

Anhand der Beispiele von Twitter habe ich folgenden Code erarbeitet:

var search1 = new Bloodhound({ //Bloodhound ist die "Suggestion Engine" von typeahead
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), //'value' ist der Wert der in den Vorschlägen angezeigt werden soll
  //mein Webservice gibt für Value Vorname + Nachname + (Userid) zurück - siehe Bild
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: {
    url: app.dataModel.SearchUrl + "/%QUERY?username=" + app.dataModel.username + "&password=" + app.dataModel.password,
    wildcard: '%QUERY'
  }
});

$('.typeahead').typeahead(null, {
  name: 'best-pictures',
  display: 'uid',
  source: search1,
  templates: {
   empty: [
    '<div class="empty-message">',
    'Nichts gefunden...', //Eine Meldung falls keine Treffer gefunden wurden
    '</div>'
  ].join('\n'),
    suggestion: Handlebars.compile('<div>{{value}}</div>')
  }
});

$('.typeahead').on('typeahead:selected', function (e, datum) { 
  //mit diesem Event reagiert man darauf, wenn der User einen Vorschlag auswählt
  console.log(datum);
  app.Views.Home.id(datum.uid);
  $("#searchButton").click();
});
<div id="searchContainer" class="input-group">
  <input id="searchInput" data-bind="value: id" type="text" class="input-lg typeahead" placeholder="Search for...">
  <span  class="input-group-btn">
    <button id="searchButton" class="btn btn-default" data-bind="click: load" type="button"><i class="fa fa-search"></i></button>
  </span>
</div>

Hier ist das Resultat:

typeahead.js Autovervollständigung mit Usernamen
typeahead.js Autovervollständigung mit Usernamen

Das ging fast einfacher als ich erwartet habe und sieht obendrein noch gut aus.

Hier noch das versprochene Stylesheet: typeahead.css