{"id":2160,"date":"2013-06-30T18:53:43","date_gmt":"2013-06-30T18:53:43","guid":{"rendered":"https:\/\/blog.ecotronics.ch\/wordpress\/?p=2160"},"modified":"2013-06-30T18:53:43","modified_gmt":"2013-06-30T18:53:43","slug":"tutorial-jquery-mobile-ajax-und-asp-net","status":"publish","type":"post","link":"https:\/\/blog.ecotronics.ch\/wordpress\/?p=2160","title":{"rendered":"Tutorial: JQuery Mobile, AJAX und ASP.NET"},"content":{"rendered":"<p><div id=\"attachment_2239\" style=\"width: 192px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2013\/06\/ScreenshotJQueryMobile.jpg\"><img aria-describedby=\"caption-attachment-2239\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2013\/06\/ScreenshotJQueryMobile-182x300.jpg\" alt=\"Blumenfinder mit JQuery Mobile und AJAX\" width=\"182\" height=\"300\" class=\"size-medium wp-image-2239\" srcset=\"https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2013\/06\/ScreenshotJQueryMobile-182x300.jpg 182w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2013\/06\/ScreenshotJQueryMobile-91x150.jpg 91w, https:\/\/blog.ecotronics.ch\/wordpress\/wp-content\/uploads\/2013\/06\/ScreenshotJQueryMobile.jpg 379w\" sizes=\"(max-width: 182px) 100vw, 182px\" \/><\/a><p id=\"caption-attachment-2239\" class=\"wp-caption-text\">Blumenfinder mit JQuery Mobile und AJAX<\/p><\/div>Dieses Tutorial zeigt, wie man mit <a href=\"http:\/\/jquerymobile.com\/\" target=\"_blank\">JQuery Mobile<\/a>, AJAX und ASP.NET datenbasierte Webseiten erstellen kann, die f\u00fcr mobile Ger\u00e4te optimiert sind. Das Ziel ist es, meine <a href=\"https:\/\/www.ecotronics.ch\/blumen.aspx\" target=\"_blank\">Seite mit Kulturanleitungen f\u00fcr Garten- und Wildblumen<\/a> in ein <a href=\"https:\/\/www.ecotronics.ch\/mobile\/Indexm.aspx\" target=\"_blank\">handytaugliches Format<\/a> zu bringen.<br \/>\nIn der ersten Version handelt es sich um eine auf- und zuklappbare Liste mit Blumennamen. Realisiert wird dies mit dem <a href=\"http:\/\/api.jquerymobile.com\/collapsible-set\/\" target=\"_blank\">JQuery-Widget collapsible set<\/a>. Klickt man auf eine Blume, dann \u00f6ffnet sich der Detailbereich mit zus\u00e4tzlichen Informationen und einem Link zur Kulturanleitung im PDF-Format.<br \/>\nAusserdem soll man mit zwei Schaltfl\u00e4chen im Fussbereich zwischen deutschen und lateinischen Blumennamen wechseln k\u00f6nnen. Ein Suchfeld hilft, nach Teilen des deutschen oder lateinischen Namens zu suchen. Die Seite soll m\u00f6glichst deklarativ ohne Programmierung mit Code behind erstellt werden.<br \/>\nDa es bei einer Mobile-Seite von den Tarifen her wichtig ist, dass keine unn\u00f6tigen Bytes geladen werden, baue ich die Seite mit AJAX so um, dass der Detailinhalt erst geladen wird, wenn man auf einen Blumennamen klickt.<\/p>\n<ol>\n<li>Unter <a href=\"http:\/\/jquerymobile.com\/themeroller\/\" target=\"_blank\">http:\/\/jquerymobile.com\/themeroller\/<\/a> ein eigenes Theme mit den gew\u00fcnschten Farben und Stilelementen erstellen und als ZIP-Datei herunterladen<\/li>\n<li>Den Ordner <strong>themes <\/strong>aus der ZIP-Datei auspacken und im gew\u00fcnschten Website als Unterordner des Root-Verzeichnisses speichern<\/li>\n<li>Den Website im Visual Web Developer Express \u00f6ffnen<\/li>\n<li>Ein Unterverzeichnis \/mobile\/ erstellen und darin eine neue Masterseite erstellen<\/li>\n<li>Im Header der Masterseite das eigene Theme und die JQuery-Libraries einbinden<\/li>\n<\/ol>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n  &lt;link rel=&quot;stylesheet&quot; href=&quot;\/themes\/Ecotronics.min.css&quot; \/&gt;\r\n  &lt;link rel=&quot;stylesheet&quot;\r\n    href=&quot;http:\/\/code.jquery.com\/mobile\/1.3.1\/jquery.mobile.structure-1.3.1.min.css&quot; \/&gt;\r\n  &lt;script src=&quot;http:\/\/code.jquery.com\/jquery-1.9.1.min.js&quot;&gt;\r\n  &lt;\/script&gt;\r\n  &lt;script\r\n    src=&quot;http:\/\/code.jquery.com\/mobile\/1.3.1\/jquery.mobile-1.3.1.min.js&quot;&gt;\r\n  &lt;\/script&gt;\r\n<\/pre>\n<ol start=\"6\">\n<li>In die Masterseite Header, Footer und Platzhalter f\u00fcr den Content-Teil f\u00fcr die Mobile-Seite einf\u00fcgen<\/li>\n<\/ol>\n<pre class=\"brush: xml; highlight: [2,8,13]; title: ; notranslate\" title=\"\">\r\n  &lt;div data-role=&quot;page&quot; data-theme=&quot;a&quot;&gt;\r\n    &lt;div data-role=&quot;header&quot; data-position=&quot;fixed&quot;&gt;\r\n      &lt;a href=&quot;Indexm.aspx&quot; data-role=&quot;button&quot; data-icon=&quot;home&quot;\r\n        data-iconpos=&quot;notext&quot; data-inline=&quot;true&quot;&gt;Startseite&lt;\/a&gt;\r\n      &lt;h1&gt;Blumenfinder&lt;\/h1&gt;\r\n    &lt;\/div&gt;\r\n    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;\r\n      &lt;div data-role=&quot;content&quot;&gt;\r\n        &lt;asp:ContentPlaceHolder id=&quot;ContentPlaceHolder1&quot; runat=&quot;server&quot;&gt;\r\n        &lt;\/asp:ContentPlaceHolder&gt;\r\n        &lt;\/div&gt;\r\n    &lt;\/form&gt;\r\n    &lt;div data-role=&quot;footer&quot; class=&quot;ui-bar&quot; data-position=&quot;fixed&quot;&gt;\r\n\t    &lt;a href=&quot;?l=l&quot; data-role=&quot;button&quot; data-mini=&quot;true&quot;&gt;Lateinisch&lt;\/a&gt;\r\n\t    &lt;a href=&quot;?l=d&quot; data-role=&quot;button&quot; data-mini=&quot;true&quot;&gt;Deutsch&lt;\/a&gt;\r\n\t  &lt;\/div&gt;\r\n  &lt;\/div&gt;\r\n<\/pre>\n<ol start=\"7\">\n<li>Ich gehe davon aus, dass die Datenbank, aus welcher Information angezeigt werden soll, bereits existiert und auf dem Webserver publizert ist. F\u00fcr das vorliegende Projekt handelt es sich um einen Auszug aus einer lokalen Datenbank, so dass die gew\u00fcnschten Informationen aus einer einzigen Tabelle stammen. Falls noch nicht vorhanden, tr\u00e4gt man jetzt den Connection String in Web.config unter dem Tag &lt;Connection Strings&gt; ein\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;add name=&quot;myConnectionString&quot;\r\n  connectionString=&quot;Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DATADIRECTORY|\\myDatabaseName.mdb&quot;\r\n  providerName=&quot;System.Data.OleDb&quot;&gt;\r\n<\/pre>\n<\/li>\n<li>Nun erzeugt man eine ASPX-Seite. Die aufklappbare Liste besteht aus einem alles umspannenden Div-Tag mit einem Attribut <strong>data-role=&#8221;collapsible-set&#8221;<\/strong>. Den Inhalt der Liste erzeugen wir mit einem Repeater, da nur diese Komponente Zeilen aus einer Datenbank in beliebigem HTML rendern kann. Die einzelnen Elemente der Liste sind Titel-Elemente, gekennzeichnet mit dem Tag &lt;h3&gt; und ein Paragraph (&lt;p&gt;-Tag) mit dem aufklappbaren Detailbereich.<\/li>\n<li>Vor der eigentlichen Liste steht eine Textbox f\u00fcr die Suche\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;asp:TextBox ID=&quot;txtName&quot; runat=&quot;server&quot; AutoPostBack=&quot;True&quot;&gt;&lt;\/asp:TextBox&gt;\r\n<\/pre>\n<\/li>\n<li>Und nat\u00fcrlich ben\u00f6tigen wir eine Datasource-Komponente, welche mit SQL die gew\u00fcnschten Datens\u00e4tze aus der Datenbank holt. Damit sie die volle Liste liefert, solange nichts im Suchfeld steht, verwendet das SQL LIKE und ist parametrisiert, wobei die Parameter aus dem Suchfeld stammen.\n<\/li>\n<\/ol>\n<p>Alle diese Elemente zusammen ergeben im Body der aspx-Seite den folgenden Code:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    &lt;asp:TextBox ID=&quot;txtName&quot; runat=&quot;server&quot; AutoPostBack=&quot;True&quot;&gt;&lt;\/asp:TextBox&gt;&lt;br \/&gt;\r\n    &lt;asp:SqlDataSource ID=&quot;dsKeimverhalten&quot; runat=&quot;server&quot; \r\n        ConnectionString=&quot;&lt;%$ ConnectionStrings:myConnectionString%&gt;&quot;\r\n        ProviderName=&quot;&lt;%$ ConnectionStrings:myConnectionString.ProviderName %&gt;&quot; \r\n        SelectCommand=&quot;SELECT [lateinischername], [name_d], [pflanzanleitung], \r\n            [bildpfad], [bildurl], [bildautoren], [bildquelle],\r\n            [keimlingBildpfad], [keimlingAutoren], [keimlingUrl]\r\n          FROM [myTableName] \r\n          WHERE ([name_d] LIKE '%' + ? + '%' OR [lateinischername] LIKE '%' + ? + '%' ) \r\n          ORDER BY [lateinischername]&quot;&gt;\r\n        &lt;SelectParameters&gt;\r\n          &lt;asp:ControlParameter ControlID=&quot;txtName&quot; DefaultValue=&quot;%&quot; \r\n            Name=&quot;deutschername&quot; PropertyName=&quot;Text&quot; Type=&quot;String&quot; \/&gt;\r\n          &lt;asp:ControlParameter ControlID=&quot;txtName&quot; DefaultValue=&quot;%&quot; \r\n            Name=&quot;lateinischername&quot; PropertyName=&quot;Text&quot; Type=&quot;String&quot; \/&gt;\r\n        &lt;\/SelectParameters&gt;\r\n    &lt;\/asp:SqlDataSource&gt;\r\n    &lt;div data-role=&quot;collapsible-set&quot;&gt;\r\n      &lt;asp:Repeater ID=&quot;repKeimverhalten&quot; runat=&quot;server&quot; \r\n        DataSourceID=&quot;dsKeimverhalten&quot;&gt;\r\n        &lt;ItemTemplate&gt;\r\n          &lt;div id=&quot;myCollapsible&quot; data-role=&quot;collapsible&quot; data-collapsed=&quot;true&quot;&gt;\r\n            &lt;h3&gt;\r\n              &lt;asp:Label ID=&quot;blumenLateinischerName&quot; runat=&quot;server&quot; Text='&lt;%#Eval(&quot;lateinischername&quot;)%&gt;'&gt;             \r\n              &lt;\/asp:Label&gt;&lt;\/h3&gt;\r\n            &lt;p id=&quot;blumenDetail&quot;&gt;\r\n              &lt;asp:Label ID=&quot;Label2&quot; runat=&quot;server&quot; Text='&lt;%#Eval(&quot;name_d&quot;)%&gt;'&gt;\r\n              &lt;\/asp:Label&gt;&lt;br \/&gt;\r\n              &lt;asp:HyperLink ID=&quot;linkPflanzanleitung&quot; runat=&quot;server&quot; \r\n                NavigateUrl='&lt;%# &quot;\/pdfs\/&quot; + Eval(&quot;pflanzanleitung&quot;) %&gt;'\r\n                Text='&lt;%# Eval(&quot;pflanzanleitung&quot;) %&gt;' Target=&quot;_blank&quot;\r\n                Visible='&lt;%#!DBNull.Value.Equals(Eval(&quot;pflanzanleitung&quot;))%&gt;'&gt;\r\n              &lt;\/asp:HyperLink&gt; \r\n              &lt;br \/&gt;\r\n              &lt;asp:Image ID=&quot;imgBlumenK&quot; runat=&quot;server&quot; \r\n                ImageUrl='&lt;%# imgRoot + &quot;\/imgblumenk\/&quot; + Eval(&quot;bildpfad&quot;) %&gt;' \r\n                Visible='&lt;%#!DBNull.Value.Equals(Eval(&quot;bildpfad&quot;))%&gt;' Height=&quot;80&quot; \/&gt;\r\n            &lt;\/p&gt;\r\n          &lt;\/div&gt;\r\n        &lt;\/ItemTemplate&gt;\r\n      &lt;\/asp:Repeater&gt;\r\n    &lt;\/div&gt;\r\n  &lt;\/div&gt;\r\n<\/pre>\n<p>Damit haben wir zwar bereits eine funktionierende Webapplikation f\u00fcrs Handy, aber vom ersten Request an wird alles geladen, auch die zugeklappten \u00c4ste der Liste mit allen Texten und Bildern. F\u00fcr all jene, die auf dem Handy keine Datenflatrate haben, ist das nat\u00fcrlich unakzeptabel. Jetzt kommt unsere Ausbaustufe ins Spiel: Der Detailbereich soll erst geladen werden, wenn jemand auf einen Titel klickt und den Detailbereich effektiv \u00f6ffnet.<\/p>\n<h1>Ausbau mit AJAX<\/h1>\n<p>In ASP.NET gibt es mehrere M\u00f6glichkeiten, mit AJAX zu arbeiten:<\/p>\n<ol>\n<li>F\u00fcr einfache Seiten gibt es die ASP.NET-Komponente <strong>UpdatePanel<\/strong>. Allerdings hatte ich meine Zweifel, dass diese sehr eingeschr\u00e4nkte Komponente sich zusammen mit JQuery Mobile einsetzen l\u00e4sst.<\/li>\n<li>Die zweite M\u00f6glichkeit besteht darin, <strong>in CSharp einen generischen Handler zu programmieren<\/strong>, der vom AJAX-Request aufgerufen wird. Diese Methode habe ich andernorts verwendet, um die <a href=\"https:\/\/blog.ecotronics.ch\/wordpress\/2010\/autocomplete-mit-jquery-und-asp-net\/\" target=\"_blank\">Daten f\u00fcr ein Autocomplete-Feld<\/a> zu erzeugen. F\u00fcr diesen Anwendungsfall war das sinnvoll, da eine reine Datenliste geliefert wird. Im aktuellen Beispiel m\u00f6chten wir jedoch mit AJAX einen Teil einer Seite mit HTML-Tags f\u00fcr Links und Bilder zur\u00fcckliefern. Dies alles aus CSharp heraus zu erzeugen, ist zwar m\u00f6glich, aber sehr umst\u00e4ndlich. Wer in den Urzeiten vor ASP und JSP je Servlets programmiert hat, weiss, wovon ich rede!<\/li>\n<li>Was ich deshalb suchte, war eine M\u00f6glichkeit, deklarativ erzeugtes HTML zu erzeugen. In ASP.NET habe ich bisher keine M\u00f6glichkeit gefunden, mit ASPX-Seiten Teile von HTML-Seiten zu erzeugen, d.h. ohne Header und Body-Tag. Daf\u00fcr gibt es in <strong>JQuery die Methode load<\/strong>, der man als Argument nicht nur die <strong>URL einer ASPX-Seite<\/strong> mitgeben kann, sondern auch die <strong>ID des Tags, das daraus geladen werden soll<\/strong>. Damit holt sich JQuery das Snippet, das es f\u00fcr die Darstellung des Detailbereichs ben\u00f6tigt.\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n...load('IndexmSnippet.aspx #blumenDetailSource', ...)\r\n<\/pre>\n<p>Man beachte, dass es sich nicht um zwei Argumente handelt, sondern dass die ID mit Leerschlag getrennt direkt im gleichen Argument steht wie die aufzurufende Seite.\n<\/li>\n<\/ol>\n<p>Unsere \u00dcberarbeitung besteht aus den folgenden Schritten<\/p>\n<ol>\n<li>\nDer Detailbereich wird in eine eigene Seite ausgelagert, wobei ein Parameter f\u00fcr den Datensatz mitgegeben wird\n<\/li>\n<li>\nIn der Hauptseite erzeugen wir f\u00fcr jene Tags innerhalb des Repeaters, die wir im JQuery sp\u00e4ter ansprechen m\u00f6chten, eindeutige IDs. Dabei verwenden wir als Nummerierung <strong>Container.ItemIndex<\/strong>, ein Befehl, der innerhalb eines Repeaters zur Verf\u00fcgung steht.\n<\/li>\n<li>\nSchliesslich fehlen noch ein paar Zeilen JavaScript, um das Nachladen des Detailbereichs mit dem <strong>Ereignis expand<\/strong> auszul\u00f6sen.\n<\/li>\n<\/ol>\n<p>Als erstes kopiere ich die urspr\u00fcngliche Aspx-Seite und h\u00e4nge der kopierten Seite das Suffix &#8220;Snippet&#8221; an. Dann l\u00f6sche ich aus dem Body das Suchfeld. Im ItemTemplate des Repeaters l\u00f6sche ich jene Zeile mit dem &lt;h3&gt;-Tag. Den Detailbereich behalte ich nat\u00fcrlich, aber das &lt;p&gt;-Tag ersetze ich mit einem &lt;span&gt;, das die ID &#8220;<strong>blumenDetailSource<\/strong>&#8221; erh\u00e4lt. Diese ID muss nicht eindeutig sein, weil nur der Inhalt des Tags in die Hauptseite geholt wird.<br \/>\nDas SQL in der DataSource-Komponente bleibt dasselbe, aber die Parameter \u00e4ndern sich. Dann im Detailbereich stammt der gesuchte Blumenname nicht mehr aus dem Suchfeld, sondern aus einem Parameter name, der dem AJAX-Request mitgegeben wird.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n      &lt;SelectParameters&gt;\r\n        &lt;asp:QueryStringParameter DefaultValue=&quot;&quot; Name=&quot;deutschername&quot; \r\n          QueryStringField=&quot;name&quot; Type=&quot;String&quot; \/&gt;\r\n        &lt;asp:QueryStringParameter DefaultValue=&quot;&quot; Name=&quot;lateinischername&quot; \r\n          QueryStringField=&quot;name&quot; Type=&quot;String&quot; \/&gt;\r\n      &lt;\/SelectParameters&gt;\r\n\r\n<\/pre>\n<p>Der Vorteil davon, dass wir in ASPX immer vollst\u00e4ndige Seiten machen m\u00fcssen, ist, dass man die Detailseite auch direkt testen kann, vorausgesetzt, man h\u00e4ngt dem Aufruf einen Parameter name= mit einem g\u00fcltigen Namen an, z.B.<br \/>\nhttps:\/\/www.ecotronics.ch\/mobile\/IndexmSnippet.aspx?name=Anthemis tinctoria<\/p>\n<p>F\u00fcr den zweiten Schritt l\u00f6sche ich in der Hauptseite alles, was innerhalb des Tags &lt;p id=&#8221;blumenDetail&#8221;&gt; steht. Das Tag selbst bleibt bestehen, denn in dieses Tag laden wir mit JQuery den von AJAX geholten Inhalt. Damit wir eine eindeutige ID f\u00fcr dieses Tag haben, erg\u00e4nzen wir das Tag folgendermassen:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n          &lt;p id='&lt;%# &quot;blumenDetail&quot; + (Container.ItemIndex) %&gt;'&gt;\r\n          &lt;\/p&gt;\r\n<\/pre>\n<p>Dies ist nicht zwingend notwendig, macht aber den Source-Code \u00fcbersichtlicher. Denn wenn wir innerhalb eines Repeaters statische IDs vergeben, sind diese nicht mehr eindeutig. Das Framework erg\u00e4nzt sie dann selbst\u00e4ndig mit eindeutigen, aber in ihrer L\u00e4nge ausgesprochen un\u00fcbersichtlichen Benennungen.<br \/>\nDie gleiche Erg\u00e4nzung machen wir auch beim &lt;div&gt;-Tag, das das einzelne Listenelement umgibt, und bei den zwei Label-Komponenten, mit denen wir den lateinischen oder deutschen Titel anzeigen. Mit den beschriebenen Modifikationen sieht der Repeater nun so aus:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    &lt;asp:Repeater ID=&quot;repKeimverhalten&quot; runat=&quot;server&quot; DataSourceID=&quot;dsKeimverhalten&quot;&gt;\r\n      &lt;ItemTemplate&gt;\r\n        &lt;div id='&lt;%# &quot;myCollapsible&quot; + (Container.ItemIndex) %&gt;'  \r\n          data-role=&quot;collapsible&quot; data-collapsed=&quot;true&quot;&gt;\r\n          &lt;h3&gt;\r\n            &lt;asp:Label visible='&lt;%#Request.Params.Get(&quot;l&quot;) == &quot;l&quot;%&gt;' \r\n              ID=&quot;blumenLateinischerName&quot; \r\n              name='&lt;%# &quot;blumenLateinischerName&quot; + (Container.ItemIndex) %&gt;' \r\n              runat=&quot;server&quot; Text='&lt;%#Eval(&quot;lateinischername&quot;)%&gt;'&gt;&lt;\/asp:Label&gt;\r\n            &lt;asp:Label ID=&quot;blumenName_d&quot; \r\n              name='&lt;%# &quot;blumenName_d&quot; + (Container.ItemIndex) %&gt;' \r\n              runat=&quot;server&quot; Text='&lt;%#Eval(&quot;name_d&quot;)%&gt;'\r\n              visible='&lt;%#Request.Params.Get(&quot;l&quot;) != &quot;l&quot;%&gt;'&gt;&lt;\/asp:Label&gt;\r\n          &lt;\/h3&gt;\r\n          &lt;p id='&lt;%# &quot;blumenDetail&quot; + (Container.ItemIndex) %&gt;'&gt;\r\n          &lt;\/p&gt;\r\n        &lt;\/div&gt;\r\n      &lt;\/ItemTemplate&gt;\r\n    &lt;\/asp:Repeater&gt;\r\n<\/pre>\n<p>Dieser Code ist auch schon vorbereitet darauf, die Titelanzeige anhand der Buttons in der Fussleiste zwischen deutschen und lateinischen Namen zu wechseln.<br \/>\nNun fehlt noch der dritte Schritt, das JavaScript:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &lt;script type=&quot;text\/javascript&quot;&gt;\r\n      $(document).ready(function () {\r\n        $(&quot;div[id^='myCollapsible']&quot;).bind('expand', function () {\r\n          var blumenName = $(this).find(&quot;span[name^='blumen']&quot;).text();\r\n          $(this).find(&quot;p[id^='blumenDetail']&quot;).load('IndexmSnippet.aspx #blumenDetailSource', \r\n            'name=' + blumenName );\r\n        });\r\n      });\r\n  &lt;\/script&gt;\r\n\r\n<\/pre>\n<p>F\u00fcr alle &lt;div&gt;-Tags, deren Id mit &#8220;Collapsible&#8221; anf\u00e4ngt (das bedeutet id^=..), fangen wir das Event <strong>expand <\/strong>ab. Den Namen der Blume holen wir aus dem Span-Element, dessen Name mit &#8220;blumen&#8221; beginnt. Diesen Namen \u00fcbergebe ich als zweites Argument im <strong>AJAX-Aufruf load<\/strong>. Aufgerufen wird nat\u00fcrlich meine vorbereitete Snippet-Seite. Nun muss ich das HTML, das aus dem load-Aufruf zur\u00fcckkommt, nur noch an das &lt;p&gt;-Tag, dessen Id mit blumenDetail beginnt, innerhalb des aufrufenden Collapsible-Tags h\u00e4ngen und fertig ist die Mobile-Liste.<br \/>\nVon hier aus sind weitere Optimierungen denkbar: Zur Zeit wird von Anfang an die volle Liste angezeigt, obwohl der User m\u00f6glicherweise nur die ersten paar Titel \u00fcberhaupt zu Gesicht bekommt. Eigentlich w\u00e4re es sinnvoll, die Liste erst nachzuladen, wenn der User nach unten scrollt. Aber das kommt vielleicht ein andermal.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><p id=\"caption-attachment-2239\" class=\"wp-caption-text\">Blumenfinder mit JQuery Mobile und AJAX<\/p>\n<p>Dieses Tutorial zeigt, wie man mit JQuery Mobile, AJAX und ASP.NET datenbasierte Webseiten erstellen kann, die f\u00fcr mobile Ger\u00e4te optimiert sind. Das Ziel ist es, meine Seite mit Kulturanleitungen f\u00fcr Garten- und Wildblumen in ein handytaugliches Format zu bringen. In der ersten Version handelt es sich um eine [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":2239,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[63,34,35],"tags":[30,62,28,227,288],"_links":{"self":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2160"}],"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=2160"}],"version-history":[{"count":42,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2160\/revisions"}],"predecessor-version":[{"id":2252,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2160\/revisions\/2252"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/2239"}],"wp:attachment":[{"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ecotronics.ch\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}