Lösung eines jqGrid Performance Problems

7. August 2013 - JavaScript, PHP

jqGrid ist ein auf JavaScript/ jQuery basierendes Modul für die komfortable und professionelle Darstellung von HTML-Tabellen. Es gibt eine ganz gute Dokumentation, von der man aber nicht immer erwarten darf, dass sie aktuell ist.

Dafür sind die Entwickler von jqGrid in ihrem Blog und auf stackoverflow.com sehr bemüht, Probleme zu lösen und Beispiele zur Verfügung zu stellen. Das ist auch oft notwenig, denn jqGrid ist komplex und  besitzt gefühlte 2 Mio. Optionen.

Beim vorliegenden Fall handelte es sich um eine jqGrid Anwendung, die mit steigender Datenmenge nur noch einen weißen Bildschirm ablieferte.

Der „datatype“ in den Optionen von jqGrid war „local“, d.h. das Grid liest seine Daten von der Seite, auf der es aufgerufen wird. Zur Verringerung der Datenmenge gab es zwei Datumsfelder (von-bis), mit denen die Datenbankabfragen modifiziert werden konnten.

Lösung:

1. Umstellung auf ajax und XML, d.h. die Datenerzeugung und Vorverarbeitung wird auf einer zusätzlichen Seite (‚get_data_from_server.php‘) gemacht

Die neuen Optionen waren dann:

url:’get_data_from_server.php‘,
datatype: „xml“,
mtype: „POST“, …..

Dadurch spart man sich z.B. die im Falle „local“ notwendigen jQuery/ jqGrid Aufrufe, um die lokalen Daten in die entsprechenden Tabellenelemente zu kopieren:

jQuery(‚#………..‘).jqGrid(‚addRowData‘,….

Bei der Umstellung auf XML muss man etwas aufpassen. XML1.0  erlaubt eine Reihe von Zeichen nicht. Diejenigen, über die man in unseren Breiten am häufigsten stolpern wird, sind < und &.

Hier hilft es, < und & zu maskieren ( in PHP mit  htmlspecialchars() ) .
Alternativ können solche Daten auch mit CDATA  getagged werden. Die lässt der XML Parser auch passieren.

Unangenehm sind aber auch Steuerzeichen von 0x00 bis 0x1f. Hier akzeptiert XML nur 0x09 (HT), 0x0a (LF) und 0x0d (CR).

Steuerzeichen können z.B über eine Textbox ins System reinrutschen, in die ein Benutzer einenMS- Word-Text hinein kopiert.

Hier hilft z.B. bei PHP

preg_replace(‚/[\x00-\x08\x0b-\x0c\x0e-\x1f]/‘, ‚ ‚, $string);

oder wieder  CDATA  verwenden.

jqGrid zeigt bei nicht erlaubten Zeichen zwar die Anzahl der Datensätze richtig an, stellt sie aber nicht dar.

Also: schaut euch die js Konsolen eures Webrowsers gut an (bei Firefox sollte man den Firebug benutzen)

2. paging: Limitierung auf x Datensätze

Standardmäßig überträgt jqGrid vier Felder per POST an get_data_from_server.php

– die Sortierreihenfolge ( ab- oder aufsteigend)
– das Feld, nach dem sortiert werden soll (order by)
– die Anzahl der gewünschten Datensätze (limit)
– den Offset (mit welchem Datensatz wird begonnen)

Damit kann man sehr einfach die Datenmenge beschränken und dem Benutzer trotzdem die Möglichkeit geben, sich alle Datensätze ansehen zu können

In den Optionen kann man z.B. dann folgendes eintragen

rowNum: 10,
rowList:[10,20,100],…

rowNum ist der Standard, rowList erzeugt ein kleines Popup, mit dem der Benutzer die Anzahl der anzuzeigenden Datensätze umstellen kann

3. Limitierung auf bestimmte Datumsbereiche

Auch der Datumsbereich läßt sich noch in die neue Lösung einbauen. Dazu benutzt man die postData Option von jqGrid:

postData: {
from: function() { return $(„#von“).val(); },
till: function() { return $(„#bis“).val(); },
},…

#von bzw. # bis sind die IDs zweier Eingabefelder, die hier mit jQuery ausgelesen werden.

Damit werden zwei weitere Felder per POST an get_data_from_server.php gesendet, die man z.B. so auswerten kann:

if (isset ( $_POST [„from“] ) && $_POST [„from“] != „“) {
$from = $_POST [„from“] ;
$till = isset ( $_POST [„till“] ) && $_POST [„till“] != „“ ? $_POST [„till“] : $from;
} else {
$from = date ( „Y-m“ );
$till = date ( „Y-m“ );
}