Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Einfach lostippen mit Typeahead
Seit jeher verfügen die meisten Webseiten über ein Suchfeld, mit dem Sie schnell nach Inhalten auf der Seite selbst oder auf der gesamten Website suchen können. Bei größeren Websites ist eine gute Suchfunktion unabdinglich. So können Benutzer – auch ohne die Sitemap und den Aufbau zu durchforsten – schnell und einfach das Gesuchte finden.
Beispielsweise ist es auf einer Händlerseite sinnvoll, Abfragestrings für die Suche nach Produkten, Angeboten oder Neuigkeiten und Hinweisen zu verwenden. Bei der Website einer Profi-Sportmannschaft muss die Suchfunktion u. a. Neuigkeiten, Sportergebnisse, Namen sowie Lebensläufe der Sportler ausgeben. Die Datenstruktur, auf der eine Suchfunktion beruht, ist niemals exakt gleich. Vielmehr hängt sie deutlich vom Einsatzbereich ab.
Aber man muss ja nicht gleich bei null beginnen. Stattdessen ist der Einsatz eines Volltext-Suchmoduls zur Unterstützung Ihrer Suchfunktion überlegenswert, z. B. Lucene.Net. Ein Modul wie Lucene.Net indiziert eine Reihe von stringbasierten Dokumenten und analysiert jeden Abfragestring gegen diesen Index. Dabei können Sie im Modul komplexe Kombinationen von Abfragestrings eingeben. Für viele Seiten und Websites wäre Lucene.Net überdimensioniert. Dennoch benötigen Sie eine Suchfunktion, die ein wenig mehr kann als eine Dropdownliste mit endlosen vielen Einträgen.
In diesem Artikel wird ein kleines Framework für die automatische Vervollständigung mit Twitter typeahead.js. vorgestellt. Zwar handelt es sich hierbei um keine Patentlösung, aber die Nutzung der automatischen Vervollständigung auf Websites wird dadurch wesentlich einfacher. Der verlockendste Aspekt des Frameworks besteht darin, dass Sie damit mehrere Datasets miteinander kombinieren können. So können Sie auf derselben Seite unterschiedliche, jedoch miteinander verwandte Informationen abfragen.
Einrichten von Typeahead.js
In diesem Artikel erläutere ich die Grundlagen von "typeahead" anhand eines realistischen Fallbeispiels. Ich verwende die auf NuGet verfügbare Version von "typeahed". Diese erhalte ich, indem ich, wie in Abbildung 1 gezeigt, "typeahead" eingebe. Bei der Suche nach "typeahead" in Google, finden Sie eventuell ältere Verweise, ältere JavaScript-Dateien oder einfach abgeänderte Versionen des Originalprojektcodes. Auch die Dokumentation ist teilweise irreführend.
Abbildung 1: Das NuGet-Paket für Twitter Typeahead.js
Die Paketdatei enthält alle Pakete, aus denen die Bibliothek besteht. Dazu gehört auch das Bloodhound-Modul, das Hinweise im lokalen Browser verwaltet. Wenn Sie typeahead.js für eine Webseite oder Razor-Ansicht verwenden möchten, benötigen Sie lediglich die bekannte jQuery-ähnliche Syntax. Dann aktivieren Sie das Plug-In des ausgewählten Eingabefelds. Im Folgenden finden Sie ein Beispiel:
<form action="@Url.Action("Query", "Home")" method="post">
<input type="hidden" id="queryCode" name="queryCode" />
<input type="text" name="queryString" id="queryString">
<button id="queryButton" type="submit">Get</button>
</form>
<form action="@Url.Action("Query", "Home")" method="post">
<input type="hidden" id="queryCode" name="queryCode" />
<input type="text" name="queryString" id="queryString">
<button id="queryButton" type="submit">Get</button>
</form>
Es sollte unbedingt darauf hingewiesen werden, dass für die sinnvolle Nutzung der automatischen Vervollständigung auf einer Website auch ein verborgenes Buddy-Feld erforderlich ist, welches eine Art eindeutige ID für den ausgewählten Vorschlag erfasst. In vielen Fällen ist die Nutzung eines Eingabefelds mit der automatischen Vervollständigung sinnvoll. Bei meinem Beispiel wird die automatische Vervollständigung genutzt, um eine endlose Dropdownliste zu ersetzen. Es ermöglicht eine ressourcenschonende Suche im Bing-Stil auf Ihrer Website. Dabei sind keine Volltextsuchmaschinen, wie Lucene.Net, erforderlich.
Erstellen von Code für die Ansicht
Für die Nutzung von typeahead.js, müssen Sie Verweise auf jQuery 1.9.1 oder höher und das typeahead-Skript erstellen. Den mindestens erforderlichen Code für diese Ansicht, sehen Sie hier:
$('#queryString').typeahead(
null,
{
displayKey: 'value',
source: hints.ttAdapter()
}
});
Damit übernehmen Sie die Standardeinstellungen und weisen die Suchmaschine an, den Eigenschaftenwert in zurückgegebenen Daten für das Füllen der Dropdownliste zu verwenden. Es wird angenommen, dass in allen zu filternden Daten ein Name für einen Eigenschaftenwert vorhanden ist. Theoretisch können Sie die automatische Vervollständigung in jedem JavaScript-Daten-Array einrichten. In der Praxis ist die automatische Vervollständigung jedoch eher dann sinnvoll, wenn die Daten von einer Remotequelle heruntergeladen werden.
Durch das Herunterladen von einer Remotequelle ergeben sich mehrere Probleme, u. a. die Richtlinieneinschränkung für denselben Ursprung, der Vorabruf und die Zwischenspeicherung. Twitter typeahead.js enthält ein Vorschlagsmodul mit dem Namen Bloodhound. Dieses erledigt ganz praktisch die meiste Arbeit für Sie. Wenn Sie die Paket-JavaScript-Datei von NuGet nutzen, können Sie Bloodhound ganz einfach aufrufen. Das Modul muss weder heruntergeladen noch eingerichtet werden. Die hints-Variable im vorigen Codeausschnitt stammt aus folgendem Code, der sozusagen die Standardinitialisierung von Bloodhound darstellt:
var hints = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: "/hint/s?query=%QUERY"
});
hints.initialize();
Beachten Sie das Remoteattribut. Das ist nur der Serverendpunkt, der die in der Dropdownliste angezeigten Vorschläge zurückgibt. Beachten Sie auch die Syntax %QUERY. Hiermit wird der String im Eingabefeld angegeben, der an den Server gesendet wird, um Vorschläge zu erhalten. Kurz: %QUERY ist ein Platzhalter für den Text im Eingabefeld. Standardmäßig ruft typeahead.js Vorschläge ab, sobald Sie das erste Zeichen eingeben. Wenn Sie warten möchten, bis sich einige Zeichen im Puffer befinden, bevor die automatische Vervollständigung beginnt, sollten Sie ein Einstellungsobjekt als erstes Argument für das Plug-In hinzufügen:
$('#queryString').typeahead(
{
minLength: 2
},
{
displayKey: 'value',
source: hints.ttAdapter()
}
});
Sobald der Puffer voll genug ist, um Remoteabrufe zu starten, beginnt Bloodhound mit der Arbeit. Das Modul lädt JSON-Daten herunter und passt sie für die Anzeige an. Zu diesem Zeitpunkt haben Sie ein nur rudimentär funktionierendes Modul für die automatische Vervollständigung, das auf der Grundlage einer beliebigen, auf Ihrem Server vorhandenen Logik Vorschläge unterbreitet. Es gibt noch viel zu tun, bis Sie die automatische Vervollständigung effizient auf einer echten Seite einsetzen können.
Verwenden von Typeahead.js mit Bootstrap
Jedes einigermaßen komplexe Plug-In sieht mit ein bisschen CSS viel besser aus. Das gilt auch für typeahead.js. Das Plug-In verfügt über eine eigene Standardbenutzeroberfläche. Es ist jedoch empfehlenswert, diese etwas anzupassen, vor allem bei der Nutzung mit Twitter Bootstrap. Sinnvoll ist auch die Anpassung einiger visueller Attribute, u. a. der Farben und Abstände. In Abbildung 2 sehen Sie mehrere CSS-Klassen, mit denen Sie das Erscheinungsbild der Komponente typeahead.js individuell anpassen können.
Abbildung 2: Die für die Anpassung der Komponente Typeahead.js zu bearbeitenden CSS-Klassen
CSS-Klasse | Beschreibung |
twitter-typeahead | Formatiert das Eingabefeld, in das der Benutzer Suchbegriffe eingibt. |
tt-hint | Formatiert den Text, der den Deltawert zwischen der Eingabe und dem ersten Vorschlag darstellt. Diese Klasse wird nur verwendet, wenn die hint-Eigenschaft auf "true" gesetzt wird (standardmäßig ist "false" festgelegt). |
tt-dropdown-menu | Formatiert die Dropdownliste mit den Vorschlägen. |
tt-cursor | Formatiert hervorgehobene Vorschläge in der Dropdownliste. |
tt-highlight | Formatiert den Anteil Text, der mit der Abfragezeichenfolge übereinstimmt. |
In Abbildung 3 sehen Sie ein Beispiel dafür, was mit benutzerdefinierten CSS-Klassen möglich ist. Sie können auch die Funktionsweise des Plug-In-Verhaltens insgesamt anpassen.
Abbildung 3: Mit angepassten CSS-Klassen erzielen Sie bei Ihrer App unterschiedliche Effekte
Clientbasierte Logik hinzufügen
Ein Textfeld mit automatischer Vervollständigung ist schneller als jede lange Dropdownliste. Wenn die Anzahl der auszuwählenden Elemente in die Hunderte geht, ist jede herkömmliche Dropdownliste langsam. Wenn Sie das Eingabefeld mit der automatischen Vervollständigung so nutzen möchten, dass ein bestimmter Wert ausgewählt werden kann, z. B. den Namen eines Produkts oder Kunden, dann ist ein einfaches typeahead.js-Plug-In nicht ausreichend. Es ist zusätzlicher Skriptcode erforderlich, der eine Bindung zum ausgewählten Ereignis des Plug-Ins herstellt:
$('#queryString').on('typeahead:selected',
function (e, datum) {
$("#queryCode").val(datum.id);
});
Der Hauptvorteil der Eingabe mit automatischer Vervollständigung besteht darin, dass das System auch bei einer unverständlichen Eingabe durch den Benutzer, den zugehörigen eindeutigen Code bzw. die ID abruft. Diese Funktion muss jedoch speziell codiert werden. Im ausgewählten Ereignishandler rufen Sie die ID-Informationen aus dem Bezugsobjekt ab und speichern sie sicher in einem verborgenen Feld. Sobald das Formular gesendet wird, zu dem die Eingabefelder mit automatischer Vervollständigung gehören, wird auch die ausgewählte ID gesendet. Das Format des Bezugsobjekts (das in der Dropdownliste ausgewählte Datenelement) hängt ganz vom Format der Daten ab, die Sie serverseitig erhalten.
Was ist mit dem angezeigten Text im Eingabefeld? In diesem Beispiel ist es wahrscheinlich nicht erforderlich, bestimmten Text im Eingabefeld anzuzeigen. Wichtig für alle weiteren Operationen ist der gespeicherte Text im verborgenen Feld. Entscheiden Sie selbst, was Sie hier anzeigen möchten. Beachten Sie: Wenn Sie eine displayKey-Eigenschaft in den Plug-In-Einstellungen angeben, wird der Wert dieser Eigenschaft automatisch im Eingabefeld angezeigt. In jedem Fall können Sie alle Werte programmatisch festlegen:
$("#queryString").val(datum.label);
Manchmal ist das Textfeld mit der automatischen Vervollständigung das einzige Element im HTML-Formular. Das bedeutet, Sie sollten alle ausgewählten Daten gleich nach der Auswahl verarbeiten. Indem Sie die folgende Zeile zum ausgewählten Ereignishandler von typeahead.js hinzufügen, simulieren Sie einen Klick auf die Schaltfläche "Senden" des Formulars:
$("#queryButton").click();
Nehmen wir einmal Folgendes an: Ein Benutzer gibt Text in das Eingabefeld ein. Die Dropdownliste wird angezeigt, aber der Benutzer hört auf zu tippen und trifft keine Auswahl. Was passiert, wenn er weitertippt? Natürlich soll er einfach weitertippen können, bis er eine Auswahl trifft. Sobald er einen Begriff auswählt, wird Code gespeichert. Wenn er also mit der Eingabe fortfährt, muss diese Auswahl abgebrochen werden. Dafür ist eine lokale Variable erforderlich:
var typeaheadItemSelected = false;
$('#queryString').on('typeahead:selected', function (e, datum) {
$("#queryCode").val(datum.id);
typeaheadItemSelected = true;
});
Sie benötigen zudem einen Handler für das Fokusereignis des Eingabefelds, der alle gespeicherten Daten zurücksetzt:
$('#queryString').on('input', function () {
if (typeaheadItemSelected) {
typeaheadItemSelected = false;
$('#queryString').val('');
$("#queryCode").val('');
}
});
Der Zweck dieser zusätzlichen clientseitigen Logik ist letztlich, sicherzustellen, dass das Eingabefeld mit der automatischen Vervollständigung genau wie eine Dropdownliste funktioniert.
Die serverseitige Komponente der automatischen Vervollständigung
Die clientseitigen Möglichkeiten jedes Codes hängen ausschließlich von den vom Server zurückgegebenen Daten ab. Der Serverendpunkt ist mindestens eine URL, die JSON-Daten zurückgibt. Sobald Sie beispielsweise einen Endpunkt nutzen, der als Sammlung von Produktobjekten dient, können Sie mit der displayKey-Eigenschaft von typeahead.js eine Art Datenbindung mit den Dropdownlisten der Vorschläge ausführen. In ihrer einfachsten Form sieht eine Controllermethode, die JSON zurückgibt, wie folgt aus:
public JsonResult P(string query)
{
var productHints = _service.GetMatchingProducts(query);
return Json(productHints, JsonRequestBehavior.AllowGet);
}
Falls das Eingabefeld der automatischen Vervollständigung Vorschläge für homogene Datenelemente anzeigen soll, ist das ein idealer Ansatz. Clientseitig können Sie den Vorlagenmechanismus von typeahead.js ganz einfach nutzen, um die benutzerdefinierten Ansichten für die Vorschläge entsprechend anzuordnen:
$('#queryString').typeahead(
null,
{
templates: {
suggestion: Handlebars.compile('<b>({{Id}}</b>: {{notes}}')
},
source: hints.ttAdapter()
});
Die Vorlageneigenschaft ersetzt "displayKey" und legt ein benutzerdefiniertes Layout für den Inhalt der Dropdownliste an. Die Dropdownliste in Abbildung 3 wird mit dem vorigen Codeausschnitt erzielt. Beim Anordnen einer Vorlage ist es empfehlenswert ein Ad-hoc-Vorlagenmodul zu verwenden, z. B. Handlebars (handlebarsjs.com). Sie müssen Handlebars separat von typeahead.js mit dem Projekt verknüpfen. Die Nutzung von Handlebars ist optional. Sie können eine HTML-Vorlage immer über manuellen JavaScript-Code formatieren oder sogar ein serverseitiges Objekt mit vorformatiertem HTML-Code zurückgeben.
Es wird schwieriger, wenn Sie möchten, dass durch die automatische Vervollständigung heterogene Vorschläge ausgegeben werden, z. B. Produkte oder Angebote. In diesem Fall müssen Sie ein Array mit zwischengeschaltetem Datentyp zurückgeben, das ausreichend Informationen für die Auswahl des Benutzers enthält. Die in diesem Artikel erläuterte automatische Vervollständigung, bietet eine grundlegende AutoCompleteItem-Klasse, wie im Folgenden gezeigt:
public class AutoCompleteItem
{
public String label { get; set; }
public String id { get; set; }
public String value { get; set; }
}
Die ID-Eigenschaft enthält eine eindeutige ID. Wenn diese gesendet wird, ist das für den empfangenden Controller von Bedeutung. Sie besteht für gewöhnlich aus zwei Teilen – der tatsächlichen ID und einer Kennung, die für die eindeutige Übereinstimmung der ID mit einem Datensatz (Produkt oder Angebot) verantwortlich ist, der möglicherweise bei der Abfrage zurückgegeben wird. Der Eigenschaftenwert ist der Zeichenfolgeinhalt, der in der Dropdownliste angezeigt wird. Die andere Eigenschaft ist eine Art "Trägereigenschaft" für eventuelle weitere benötigte Elemente. Der Eigenschaftswert kann auch serverseitig angeordnete HTML-Zeichenfolgen für benutzerdefinierte Vorschlagslayouts enthalten. Der serverseitige Code ist für die Ausführung aller erforderlichen Abfragen verantwortlich sowie für die Integration von Daten in eine Sammlung von AutoCompleteItem-Objekten.
Zusammenfassung
Die Benutzerfreundlichkeit gewinnt heutzutage bei Websites zunehmend an Bedeutung. Das betrifft einerseits das Erscheinungsbild, andererseits aber vor allem die grundlegende Funktionsweise einer Website. Ich hatte auf einer meiner Websites früher eine Dropdownliste mit mehr als 700 Einträgen. Sie funktionierte, war aber sehr langsam. Seit ich sie durch die automatische Vervollständigung ersetzt habe, geht die Nutzung blitzschnell. Für diese und andere Dienstprogramme habe ich ein GitHub-Projekt eingerichtet unter bit.ly/1zubJea.
Dino Esposito ist Mitautor von "Microsoft .NET: Architecting Applications for the Enterprise" (Microsoft Press, 2014) und "Programming ASP.NET MVC 5" (Microsoft Press, 2014). Esposito ist Technical Evangelist für die Microsoft .NET Framework- und Android-Plattformen bei JetBrains und spricht häufig auf Branchenveranstaltungen weltweit. Auf software2cents.wordpress.com und auf Twitter unter twitter.com/despos lässt er uns wissen, welche Softwarevision er verfolgt.
Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Jon Arne Saeteras