{"id":190,"date":"2010-11-18T13:50:33","date_gmt":"2010-11-18T13:50:33","guid":{"rendered":"https:\/\/blog.ecotronics.ch\/wordpress\/?p=190"},"modified":"2010-11-18T13:50:33","modified_gmt":"2010-11-18T13:50:33","slug":"autocomplete-mit-jquery-und-asp-net","status":"publish","type":"post","link":"https:\/\/blog.ecotronics.ch\/wordpress\/?p=190","title":{"rendered":"AutoComplete mit JQuery und ASP.NET"},"content":{"rendered":"<p>F\u00fcr die Suche in grossen Datenbest\u00e4nden haben wir uns inzwischen ans <strong>AutoComplete<\/strong> gew\u00f6hnt: Kaum tippt man ein paar Buchstaben, da erscheint unter dem Eingabefeld eine Liste mit m\u00f6glichen Suchresultaten.<\/p>\n<p>Dahinter steckt <strong>AJAX und JavaScript<\/strong>. Und um die Sache zu vereinfachen, werde ich nat\u00fcrlich wie andernorts auch zu <strong>JQuery <\/strong>als JavaScript-Framework greifen. F\u00fcr einmal zeige ich das Beispiel nicht mit Groovy und Grails, sondern in <strong>ASP.NET<\/strong> und mit <strong>Visual Web Developer Express Edition<\/strong>.<\/p>\n<p>Das vorliegende Beispiel geht \u00fcber die Standardbeispiele hinaus, indem es zeigt, wie man mit einem AutoComplete-Feld arbeitet, das nicht nur den Wert der Eingabe zur\u00fcckliefert, sondern auch den zugeh\u00f6rigen Schl\u00fcssel.<\/p>\n<h2>Voraussetzungen und Vorbereitung<\/h2>\n<p>Das Beispiel geht davon aus, dass Sie <strong>mit den grundlegenden Mechanismen von AJAX vertraut<\/strong> sind und gewisse<strong> Vorkenntnisse in der Programmierung datenbankgest\u00fctzter Websites<\/strong> haben, insbesondere in Bezug auf <strong>JavaScript<\/strong>, <strong>JQuery <\/strong>sowie <strong>SQL <\/strong>und <strong>ASP.Net<\/strong>.<\/p>\n<p>Bevor Sie diese Aufgabe in Angriff nehmen k\u00f6nnen, gibt es ein paar Vorbedingungen, die erf\u00fcllt sein m\u00fcssen.<\/p>\n<ul>\n<li>Windows mit installiertem und laufendem <strong>IIS<\/strong> (lokal oder bei ihrem Provider)<\/li>\n<li><strong>ASP.NET<\/strong> in Version <strong>3.5<\/strong> auf dem IIS vorhanden<\/li>\n<li><strong>Visual Web Developer Express Edition 2008<\/strong> oder h\u00f6her<strong> <\/strong>lokal auf ihrem PC installiert<\/li>\n<li>eine <strong>webf\u00e4hige Datenbank <\/strong>wie MySQL, Oracle oder Access<\/li>\n<\/ul>\n<p>Eine Anmerkung zu Access: Viele bekommen einen Lachanfall, wenn man <strong>Microsoft Access als webf\u00e4hige Datenbank<\/strong> bezeichnet. Solange sich das Benutzeraufkommen in Grenzen h\u00e4lt und die Applikation sich auf SELECT-Statements begrenzt und Schreiboperationen auf der Datenbank nicht oder nur selten vorkommen, kann man Access durchaus f\u00fcr diesen Zweck einsetzen. Wenn Sie die Webapplikation bei einem Service Provider ver\u00f6ffentlichen m\u00f6chten, bleibt Ihnen oft nicht anderes \u00fcbrig, da Sie, wenn Sie f\u00fcr das Hosting nicht allzuviel ausgeben wollen,\u00a0 auf einem IIS in den meisten F\u00e4llen gar keine andere Datenbank zur Verf\u00fcgung haben.<\/p>\n<p>Als n\u00e4chstes erstellen Sie in Visual Web Developer einen <strong>neuen leeren Website<\/strong>. Achten Sie darauf, dass Sie diesen Site direkt auf dem lokalen IIS oder auf einem Remote Server\u00a0 als virtuellen Server oder als Unterverzeichnis des Root erstellen und nicht auf dem Dateisystem. Das heisst, Sie m\u00fcssen unbedingt <strong>Speicherort HTTP<\/strong> w\u00e4hlen. Dies deshalb, weil <strong>gewisse Men\u00fcs und Optionen <\/strong>in der Entwicklungsumgebung <strong>nicht zur Verf\u00fcgung<\/strong> stehen, wenn man <strong>auf dem Dateisystem<\/strong> arbeitet.<\/p>\n<h2>Downloads<\/h2>\n<p>Des weiteren ben\u00f6tigen Sie nat\u00fcrlich in Ihrem Projekt JQuery und das AutoComplete-Plugin inklusive zugeh\u00f6rigem CSS. Laden Sie also folgende Dateien herunter und versorgen Sie diese in den angegebenen Ordnern:<\/p>\n<ul>\n<li><a href=\"http:\/\/code.jquery.com\/jquery-latest.min.js\" target=\"_blank\"><strong>Neueste JQuery-Version<\/strong><\/a>, im Oktober 2010 ist dies 1.4.2. Diese kommt in ein <strong>Verzeichnis \\js\\<\/strong> unterhalb von Root.<\/li>\n<li><strong><a href=\"http:\/\/dev.jquery.com\/view\/trunk\/plugins\/autocomplete\/jquery.autocomplete.js\" target=\"_blank\">AutoComplete-Plugin<\/a><\/strong> f\u00fcr JQuery, diese Datei kommt ebenfalls in <strong>\\js\\<\/strong><\/li>\n<li>Die <a href=\"http:\/\/dev.jquery.com\/view\/trunk\/plugins\/autocomplete\/jquery.autocomplete.css\" target=\"_blank\"><strong>CSS-Datei<\/strong><\/a> aus der JQuery-Demo stellen Sie in ein Verzeichnis <strong>\\css\\<\/strong><\/li>\n<\/ul>\n<h2>Aufgabenstellung<\/h2>\n<p>Ich zeige das Beispiel anhand meiner <strong>Blumen-Datenbank<\/strong>. In dieser Access-Datenbank finden sich Informationen zu Blumen. F\u00fcr jede Pflanze ist mindestens der wissenschaftliche, d.h. <strong>lateinische Name<\/strong> sowie ein <strong>deutscher Name <\/strong>gespeichert. Das Eingabefeld soll nun, sobald man den ersten Buchstaben eingibt, unterhalb des Eingabefeldes eine <strong>Liste aller Pflanzen zur Auswahl anzeigen, welche die eingegebene Buchstabenkombination im deutschen oder lateinischen Namen aufweisen<\/strong>.<\/p>\n<h2>Webform<\/h2>\n<p>Sobald das Projekt mit den entsprechenden Dateien vorhanden ist, erstellen Sie ein neues Webform. Den Code m\u00fcssen Sie nicht in einer eigenen Datei platzieren, dieses Webform wird keinen serverseitigen Code aufweisen. Bei mir heisst diese Datei<strong> JQueryAutoComplete.aspx<\/strong> und ich arbeite mit C#. Kopieren Sie folgenden Code in die Datei:<\/p>\n<pre>&lt;%@ Page Language=\"C#\" AutoEventWireup=\"true\"\r\n CodeBehind=\"JQueryAutoComplete.aspx.cs\"\r\n Inherits=\"webblumen.aspxversuche.JQueryAutoComplete\" %&gt;\r\n\r\n&lt;!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD XHTML 1.0 Transitional\/\/EN\"\r\n \"http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-transitional.dtd\"&gt;\r\n\r\n&lt;html xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\" &gt;\r\n  &lt;head runat=\"server\"&gt;\r\n    &lt;title&gt;AutoComplete mit JQuery&lt;\/title&gt;\r\n    <strong>&lt;script src=\"\/js\/jquery-1.4.2.min.js\" type=\"text\/javascript\"&gt;\r\n    &lt;\/script&gt;\r\n<\/strong>    <strong>&lt;link rel=\"stylesheet\" href=\"\/css\/jquery.autocomplete.css\"\r\n      type=\"text\/css\" \/&gt;\r\n    &lt;script type=\"text\/javascript\" src=\"\/js\/jquery.autocomplete.js\"&gt;\r\n    &lt;\/script&gt;<\/strong>\r\n    &lt;script type=\"text\/javascript\"&gt;\r\n      $(document).ready(function() {\r\n <strong>       $(\"#fldInput\").autocomplete(\"JQueryAutoCompleteHandler.ashx\", {\r\n          \/\/Daten kommen in der Form\r\n          \/\/ name_l_d | idPflanze | name_d_l\r\n\r\n          \/\/Anzeige in Liste \"1\/5: name_l_d\"\r\n          formatItem: function(row, i, max) {\r\n            return i + \"\/\" + max + \": \" + row[0];\r\n          },\r\n          \/\/Anzeige im Textfeld \"idPflanze name_l_d\"\r\n          formatResult: function(row) {\r\n            return row[1] + \" \" + row[0];\r\n          }\r\n        });\r\n        \/\/Auswahl wird unterhalb Inputfeld angezeigt\r\n        $(\"#fldInput\").result(function(event, data, formatted) {\r\n          if (data) {\r\n            $(\"#resultat\").html(\"Schl&amp;uuml;ssel: \" + data[1]\r\n              + \"&lt;br \/&gt;Wert: \" + data[0]<\/strong> <strong>+ \"&lt;br \/&gt;\" + data[2]));\r\n          }\r\n        });\r\n<\/strong>\r\n      });\r\n    &lt;\/script&gt;\r\n  &lt;\/head&gt;\r\n  &lt;body&gt;\r\n    Blume:\r\n    <strong>&lt;input id=\"fldInput\" type=\"text\" size=\"50\"\/&gt;<\/strong>\r\n    &lt;br \/&gt;\r\n    <strong>&lt;div id=\"resultat\"&gt;&lt;\/div&gt;<\/strong>\r\n  &lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>Der sichtbare Teil der Seite selbst besteht nur aus einem <strong>Input-Feld<\/strong> namens <strong>fldInput <\/strong>und einem <strong>Div-Tag<\/strong> mit der id &#8220;<strong>resultat<\/strong>&#8220;, das sp\u00e4ter die ausgew\u00e4hlten Daten anzeigen wird. Beachten Sie, dass es sich um ein ganz <strong>gew\u00f6hnliches Text-Feld<\/strong> handelt, <strong>nicht <\/strong>um <strong>ein Kombinationsfeld<\/strong>. Die angezeigte Liste wird n\u00e4mlich mit JavaScript automatisch generiert und angezeigt.<\/p>\n<p>Im Header werden erst einmal die oben erw\u00e4hnten <strong>Dateien eingebunden<\/strong>, also jquery-1.4.2.min.js und die zwei Dateien f\u00fcr die AutoComplete-Komponente, d.h. jquery.autocomplete.css und\u00a0 jquery.autocomplete.js.<\/p>\n<p>Das Wichtigste steckt nat\u00fcrlich im <strong>JavaScript-Code.<\/strong> Doch sehen wir uns zuerst den serverseitigen Code an, der die Daten f\u00fcr das AutoComplete-Feld liefert.<\/p>\n<h2>Generischer Handler f\u00fcr die serverseitige DB-Abfrage<\/h2>\n<p>Erzeugen Sie unter Datei &#8211; Neue Datei einen <strong>generischen Handler<\/strong>. Bei mir heisst diese Datei <strong>JQueryAutoCompleteHandler.ashx<\/strong>. Dieser Handler holt aus den \u00fcbergebenen Daten den Suchstring, macht mit diesem eine Datenbank-Abfrage und liefert die gefundenen Datens\u00e4tze in folgendem Format zur\u00fcck:<\/p>\n<p>BezeichnungA1|Schluesselwert1|BezeichnungB1<br \/>\nBezeichnungA2|Schluesselwert2|BezeichnungB2<br \/>\nBezeichnungA3|Schluesselwert3|BezeichnungB3<br \/>\n&#8230;<\/p>\n<p>Anscheinend erkennt das JavaScript-Plugin | automatisch als Trennzeichen, so dass man sp\u00e4ter in JavaScript direkt auf diese zwei Felder zugreifen kann.<\/p>\n<p>Der Code f\u00fcr diesen Handler sieht folgendermassen aus:<\/p>\n<pre>&lt;%@ WebHandler Language=\"C#\" %&gt;\r\n\r\nusing System;\r\nusing System.Web;\r\nusing System.Data.OleDb;\r\n\r\npublic class <strong>JQueryAutoCompleteHandler <\/strong>: IHttpHandler {\r\n\r\n<strong>  public void ProcessRequest (HttpContext context) {\r\n    \/\/ hier wird der eingegebene Wert aus dem Parameter q gelesen\r\n    string input = context.Request.QueryString[\"q\"];\r\n    string sql = \"SELECT top 20 name_l_d, idPflanze, name_d_l \"\r\n      + \"FROM qryNameD where name_l_d like ?\";\r\n    String CONN =\r\n      System.Configuration.ConfigurationManager.ConnectionStrings[\r\n        \"blumenConnectionString\"].ConnectionString;\r\n\r\n    using (OleDbConnection connection = new OleDbConnection(CONN))\r\n    using (OleDbCommand command = new OleDbCommand(sql, connection)) {\r\n      connection.Open();\r\n      command.Parameters.AddWithValue(\"input\", \"%\" + input + \"%\");\r\n      using (OleDbDataReader reader = command.ExecuteReader()) {\r\n        while (reader.Read()) {\r\n          \/\/liefert die Daten in der Form\r\n          \/\/name_l_d | idPflanze | name_d_l\r\n          context.Response.Write(reader.GetString(0) + \"|\"\r\n            + reader.GetInt32(1).ToString() + \"|\"\r\n            + reader.GetString(2) + Environment.NewLine);\r\n        }\r\n      }\r\n    }\r\n  }<\/strong>\r\n\r\n   public bool IsReusable {\r\n     get {\r\n       return false;\r\n     }\r\n   }\r\n\r\n}<\/pre>\n<p>IHttpHandler ist ein ASP.Net-Interface, dass es erm\u00f6glicht, Requests zu bedienen, ohne dass eine ganze HTML-Seite zur\u00fcckgeliefert wird. Typische Anwendungen daf\u00fcr sind AJAX-Requests, welche HTML oder direkt Daten in einem bestimmten Format wie JSON zur\u00fcckerwarten. Daneben ist es mit einem solchen Handler auch m\u00f6glich, Fremdformate zur\u00fcckzuliefern, z.B. eine PDF- Excel- oder Bilddatei, welche direkt aus der Datenbank erzeugt wird.<\/p>\n<p>Der vorliegende Handler holt sich als erstes die Eingabe aus dem vordefinierten <strong>Parameter q<\/strong>.<\/p>\n<pre><strong><strong>    string input = context.Request.QueryString[\"q\"];\r\n<\/strong><\/strong><\/pre>\n<p>Anschliessend macht man eine Datenbankverbindung und holt mit einem parametrisierten <strong>Select-Statement<\/strong> alle Datens\u00e4tze aus der Access-Datenbank, die dem Kriterium entsprechen. Sie erinnern sich, es geht in diesem Beispiel um Blumen. Mit der Parametrisierung werden <strong>SQL-Injection<\/strong>-Versuche abgefangen.<\/p>\n<pre><strong><strong>    string sql = \"SELECT top 20 name_l_d, idPflanze, name_d_l \"\r\n      + \"FROM qryNameD where name_l_d like ?\";\r\n<\/strong><\/strong><\/pre>\n<p>Mit AddWithValue weisst man dem Parameter einen Wert zu:<\/p>\n<pre><strong><strong>      command.Parameters.AddWithValue(\"input\", \"%\" + input + \"%\");\r\n<\/strong><\/strong><\/pre>\n<p>Zur\u00fcckgeliefert wird ein String, der <strong>pro Zeile drei Felder des jeweiligen Datensatzes<\/strong> zur\u00fcckliefert. Als erstes im Feld <strong>name_l_d<\/strong> die Bezeichnung, bei welcher der lateinische Name dem deutschen vorangestellt ist. Als zweites die eindeutige Id der Pflanze in <strong>idPflanze<\/strong>, mit der in einem zweiten Request weitere Informationen zu dieser Pflanze geholt werden k\u00f6nnten. Als drittes finden sich schliesslich im Feld <strong>name_d_l<\/strong> noch die Bezeichnungen in umgekehrter Reihenfolge, d.h. der deutsche Name kommt vor dem lateinischen.<\/p>\n<p>Dieses dritte Feld gebe ich vor allem mit, um zu zeigen, dass man bei dieser JavaScript-L\u00f6sung <strong>nicht wie im HTML-Kombinationsfeld <\/strong><strong>auf das <\/strong><strong>Paar aus Wert und Bezeichnung begrenzt ist<\/strong>, sondern beliebig viele Felder pro Datensatz zur\u00fcckliefern kann.<\/p>\n<pre><strong><strong>          context.Response.Write(reader.GetString(0) + \"|\"\r\n            + reader.GetInt32(1).ToString() + \"|\"\r\n            + reader.GetString(2) + Environment.NewLine);\r\n<\/strong><\/strong><\/pre>\n<p>Der Befehl <strong>context.Response.Write<\/strong> setzt den String in genau dieser Reihenfolge aus den drei Feldern der resultierenden Datens\u00e4tze zusammen und liefert ihn zur\u00fcck an die aufrufende Seite, wo er dann mit den bereits gezeigten JQuery-Routinen verarbeitet wird.<\/p>\n<h2>AJAX mit JQuery<\/h2>\n<p>Damit kommen wir zur\u00fcck zu unserem JavaScript-Code, den wir im Abschnitt Webform bereits gesehen haben. <strong>AJAX <\/strong>kommt insofern ins Spiel, dass die Eingabe von ein paar Buchstaben zwar einen serverseitigen Request ausl\u00f6sen soll, aber nat\u00fcrlich nicht die ganze Seite neu laden darf, sondern nur die vom AJAX-Request zur\u00fcckgelieferten Daten in die Seite einbaut.<\/p>\n<p>Der Aufruf befindet sich innerhalb des in JQuery \u00fcblichen<\/p>\n<pre>$(document).ready(function() {<\/pre>\n<p>und lautet:<\/p>\n<pre>$(\"<strong>#fldInput<\/strong>\").<strong>autocomplete<\/strong>(<strong>\"JQueryAutoCompleteHandler.ashx\"<\/strong>, {\r\n  ...\r\n}<strong><strong>\u00a0<\/strong><\/strong><\/pre>\n<p>Die Methode autocomplete wird dem Eingabefeld mit der Id <strong>fldInput<\/strong> angeh\u00e4ngt. Als erstes Argument \u00fcbergibt man den Handler <strong>JQueryAutoCompleteHandler<\/strong>, der serverseitig den AJAX-Request verarbeitet.<\/p>\n<p>Zwischen den geschweiften Klammern befinden sich nun die <strong>Optionen<\/strong>. Das AutoComplete-Plugin hat eine ganze Anzahl Optionen, von denen man meist nur ein bis zwei verwendet. F\u00fcr speziellere Bed\u00fcrfnisse lohnt es sich allerdings, die <a href=\"http:\/\/docs.jquery.com\/Plugins\/Autocomplete\/autocomplete#toptions\">Dokumentation zu diesen Optionen<\/a> genau anzusehen.<\/p>\n<p>Das vorliegende Beispiel verwendet zwei Optionen:<\/p>\n<ol>\n<li><strong>formatItem<\/strong> definiert, wie die vom Handler zur\u00fcckgelieferten Daten <strong>in der Liste unterhalb des Eingabefeldes<\/strong> aussehen<\/li>\n<\/ol>\n<pre><strong><strong>          formatItem: function(row, i, max) {\r\n            return i + \"\/\" + max + \": \" + row[0];\r\n          },\r\n<\/strong><\/strong><\/pre>\n<ol>\n<li><strong>formatResult<\/strong> dagegen definiert, welche Daten ins <strong>Textfeld <\/strong>selbst geschrieben werden, <strong>sobald <\/strong>die Benutzerin <strong>ein Item aus der Liste ausgew\u00e4hlt<\/strong> hat.<\/li>\n<\/ol>\n<pre><strong><strong>          formatResult: function(row) {\r\n            return row[1] + \" \" + row[0];\r\n          }\r\n<\/strong><\/strong><\/pre>\n<p>In beiden F\u00e4llen erfolgt der Zugriff auf die Information \u00fcber eine Variable row, die in JavaScript ein <strong>0-basierter Array<\/strong> ist. row[0] liefert name_l_d, row[1] liefert den Schl\u00fcssel idPflanze und row[2] liefert name_d_l.<\/p>\n<p>Eine Besonderheit ist nun, dass die AutoComplete-Komponente f\u00fcr die zur\u00fcckgelieferten rows automatisch <strong>zwei Variablen<\/strong> zur Verf\u00fcgung stellt: <strong>i<\/strong> ist eine <strong>Laufnummer <\/strong>und <strong>max <\/strong>gibt die <strong>Anzahl der zur\u00fcckgelieferten Datens\u00e4tze<\/strong> an. Damit die Liste nicht zu lang wird, wurde sie \u00fcbrigens serverseitig im Select-Statement mit dem Access-spezifischen Zusatz &#8221; <strong>Top 20<\/strong>&#8221; willk\u00fcrlich auf 20 Datens\u00e4tze begrenzt.<\/p>\n<p>F\u00fcr die Liste nutze ich die zwei Variablen, indem ich vor der eigentlichen Bezeichnung noch die Laufnummer und die Gesamtzahl angebe. Das sieht dann so aus:<\/p>\n<div id=\"attachment_230\" style=\"width: 408px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/blog.ecotronics.ch\/wordpress?getfile=230\"><img aria-describedby=\"caption-attachment-230\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-230  \" style=\"width: 398px; height: 107px;\" title=\"JQuery AutoComplete-Plugin mit aufgeklappter Liste\" src=\"https:\/\/blog.ecotronics.ch\/wordpress?getfile=230\" alt=\"\" width=\"398\" height=\"107\" \/><\/a><p id=\"caption-attachment-230\" class=\"wp-caption-text\">JQuery AutoComplete-Plugin mit aufgeklappter Liste<\/p><\/div>\n<p>Nach der Auswahl wird das Schl\u00fcsselfeld und die Bezeichnung angezeigt:<\/p>\n<div id=\"attachment_233\" style=\"width: 393px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-233\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-233 \" title=\"AutoCompleteResultat\" src=\"https:\/\/blog.ecotronics.ch\/wordpress?getfile=233\" alt=\"Das Eingabefeld nach der Auswahl\" width=\"383\" height=\"92\" \/><p id=\"caption-attachment-233\" class=\"wp-caption-text\">Das Eingabefeld nach der Auswahl<\/p><\/div>\n<p>Der letzte, mit<strong> $(&#8220;#fldInput&#8221;).result<\/strong> eingeleitete Block im JQuery-Script regelt, was nach Abschluss der Eingabe passiert. Result hat ein Argument, n\u00e4mlich eine Funktion, die wiederum drei Argumente entgegennimmt. In unserem Beispiel interessiert von diesen Drei nur <strong>data<\/strong>, <strong>die gew\u00e4hlte Zeile aus der AutoComplete-Liste<\/strong>. Wenn data etwas zur\u00fcckliefert, dann werden innerhalb des DIV-Tags mit der Id resultat die drei Teile dieser Information angezeigt, allerdings nicht in der urspr\u00fcnglichen Reihenfolge.<\/p>\n<pre>\r\n<pre><strong>        $(\"#fldInput\").result(function(event, data, formatted) {\r\n          if (data) {\r\n            $(\"#resultat\").html(\"Schl&amp;uuml;ssel: \" + data[1]\r\n              + \"&lt;br \/&gt;Wert: \" + data[0]<\/strong> <strong>+ \"&lt;br \/&gt;\" + data[2]));\r\n          }\r\n        });\r\n<\/strong><\/pre>\n<p>Damit sind wir am Ende des Beispiels. Es w\u00e4re nun reizvoll, das gleiche Beispiel mit Grails und mit PHP durchzuspielen. Im Grossen und Ganzen \u00e4nderte sich dabei nur der serverseitige Event-Handler, die Webseite und das JavaScript dagegen blieben in allen drei Frameworks fast dieselben. Aber das ist ein Thema f\u00fcr einen anderen Beitrag.<\/p>\n<h2>Quellen<\/h2>\n<p>Ausgangspunkt f\u00fcr meine eigenen Versuche war die folgende Seite:<\/p>\n<p><a href=\"http:\/\/www.eggheadcafe.com\/tutorials\/aspnet\/18b6a1fa-a7cf-4507-84f2-15056fe65bb7\/autocompletion-with-jque.aspx\">http:\/\/www.eggheadcafe.com\/tutorials\/aspnet\/18b6a1fa-a7cf-4507-84f2-15056fe65bb7\/autocompletion-with-jque.aspx<\/a><\/p>\n<p>Die Dokumentation zum AutoComplete-Plugin findet man hier:<\/p>\n<p><a href=\"http:\/\/docs.jquery.com\/Plugins\/Autocomplete\/autocomplete#toptions\">http:\/\/docs.jquery.com\/Plugins\/Autocomplete\/autocomplete#toptions<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>F\u00fcr die Suche in grossen Datenbest\u00e4nden haben wir uns inzwischen ans AutoComplete gew\u00f6hnt: Kaum tippt man ein paar Buchstaben, da erscheint unter dem Eingabefeld eine Liste mit m\u00f6glichen Suchresultaten.<\/p>\n<p>Dahinter steckt AJAX und JavaScript. Und um die Sache zu vereinfachen, werde ich nat\u00fcrlich wie andernorts auch zu JQuery als JavaScript-Framework greifen. F\u00fcr einmal zeige ich [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[63,34,35,3],"tags":[62,61,28],"_links":{"self":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/190"}],"collection":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=190"}],"version-history":[{"count":35,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/190\/revisions"}],"predecessor-version":[{"id":243,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/190\/revisions\/243"}],"wp:attachment":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}