ClaretPortal wird mobil (Teil 4) - Fokus: Volltextsuche mit jQuery Mobile
In den ersten drei Teilen dieser Blog-Serie [1] [2] [3] habe ich alle Basis-Funktionalitäten gezeigt, die man heutzutage von einer mobilen Web-Applikation erwartet. Hervorzuheben sind dabei das klare und übersichtliche UI-Design über Standard-Komponenten von jQuery Mobile sowie das Scrollen von Listen (Endless / Infinite Scroll) im Gegensatz zu einer Blätterung.
Bei Scrollen von Listen wurde dabei schon die Einbindung eines Backend-Servers betrachtet, denn logischerweise müssen beim Scrollen Daten nachgeladen werden. Dieser Beitrag soll zeigen, wie auf einfache Art und Weise die Standard-Komponente ListView mit Suchfeld dazu benutzt werden kann, um beliebige Daten serverseitig zu durchsuchen, z.B. eine Volltextsuche mit Elasticsearch [4].
jQuery Mobile ListView mit Filterable Widget
In einer jQuery Mobile ListView lässt sich einfach über das Attribut data-filter="true" (bitte die Hinweise im jQuery Mobile 1.4 Upgrade Guide [5] beachten) ein Suchfeld über der Liste anzeigen. Standardmäßig durchsucht dieses Suchfeld automatisch alle Elemente, die in der Liste dargestellt werden. Das ist für eine Filterfunktion bestens geeignet, stößt aber an seine Grenzen sobald Daten durchsucht werden sollen, die noch nicht am Client verfügbar sind. Für diesen Zweck bietet das Widget allerdings einen Event-Mechanismus, mit welchem die vom Benutzer eingetippten Suchanfragen abgefangen und an einen Server weitergeleitet werden können.
Filterable Widget und das filterablebeforefilter-Event
Das filterablebeforefilter-Event ist immer dann geeignet, wenn das ListView-Suchfeld eine andere Datenmenge dursuchen soll als aktuell tatsächlich in der ListView dargestellt wird. Das kann zum einen dafür benutzt werden, um bestimmte Tags zu durchsuchen, die beispielsweise in versteckten DIV-Containern vorgehalten werden. Es lässt sich zum anderen aber auch benutzen, um Suchanfragen an eine Volltextsuche wie Elasticsearch zu schicken und das Ergebnis im Anschluss dann in der ListView anzuzeigen. Das Look & Feel bleibt für den Benutzer dabei unverändert, er "weiß nicht", dass die Daten von einem entfernten Server kommen.
Das folgende Bild zeigt das vom Server über Elasticsearch kommende Suchergebnis im gewohnten jQuery Mobile Design:
Die technische Realisierung
Die Funktionsweise besteht aus zwei grundlegenden Komponenten.
Die ListView mit Filterable Widget
<div id="studyListContainer" data-role="content" data-theme="a">
<g:link action="list" class="search-query-link" style="display:none">Search query</g:link>
<ul class="study-list" data-role="listview" data-filter="true" data-filter-placeholder="Search all studies">
<g:render template="studyList" model="[pageScope.variables]" />
</ul>
</div>
Der Javascript-Aufruf
$("#list").find(".study-list").on("filterablebeforefilter", function (e, data) {
var $ul = $(this);
var $input = $(data.input); // Get user's search input
var value = $input.val();
var html = "";
$ul.html(""); // Clear list
if (value && value.length > 2) {
$.mobile.loading('show'); // Show default loading icon
var theUrl = $('.search-query-link').attr("href");
$.ajax({
url: theUrl,
dataType: "html",
crossDomain: true,
data: {
query: $input.val() // Query param for server
}
})
.then(function (data) {
$.mobile.loading('hide'); // Upon receiving data, hide loading icon
$ul.html($(data).find(".study-list li")); // Insert result into list
$ul.listview("refresh"); // Apply jQuery Mobile Look & Feel
});
}
});
Das Event "filterablebeforefilter" wird bei jeder Änderung des Suchfelds gefeuert und triggert mit obigem Javascript-Aufruf einen Server-Request - in unserem Fall an einen Grails-Controller, der wiederum über einen Service Elasticsearch abfragt. Der Grails-Controller rendert die herkömmliche View, die die ListView mit den zur Suche passenden Ergebnisse erhält. Die List-Items dieser ListView werden im vorletzten Aufruf einfach in die bestehende Liste eingefügt.
Fazit
Dieser Beitrag zeigt, wie einfach sich auf mobilen Endgeräten auch komplexe Aktionen wie eine Volltextsuche darstellen lassen. Dabei muss der Client keine Logik verwalten - er sendet lediglich den Suchbegriff und der Rest wird vom Backend übernommen. Durch entsprechende Ladesymbole ist dieses Vorgehen für den Benutzer transparent.
Das in Teil 3 vorgestellte Endless Scrolling lässt sich auch hier ohne weiteres Zutun in Kombination verwenden. Die perfekte Such-App!
Links
[1] ClaretPortal wird mobil (Teil 1) - Fokus: jQuery Mobile ListViews
[2] ClaretPortal wird mobil (Teil 2) - Fokus: jQuery Mobile Grid & Collapsible Set
[3] ClaretPortal wird mobil (Teil 3) - Fokus: Endless/Infinite Scrolling mit jQuery Mobile
[3] exensio setzt auf Elasticsearch
[4] jQuery Mobile 1.4 Upgrade Guide - Filter