Klient-seitige Sitzungen und Speicherung von dauerhaften Daten
Firefox 2 unterstützt als erster Browser das Storage-System (Client-side session and persistent storage), welches Webentwicklern ermöglicht Daten Klient-seitig zu speichern. Damit hat man weitaus mehr Möglichkeiten als mit Cookies und kann sich damit Zeit und Arbeit sparen.
Dieser Artikel stellt das System vor und enthält ein Paar Beispiele.
Achtung: Dieser Artikel ist inzwischen veraltet! Eine aktuelle Dokumentation befindet sich im Mozilla Developer Center (englisch).
Dem Entwickler wird mit dem Storage-System ein neues Werkzeug in die Hand gegeben, ausgereiftere Web-Applikationen zu entwerfen. Die Sitzungsdaten werden auf die Klient-seite beschränkt, anders als bei Cookies. Der Browser übermittelt diese Daten nicht an den Server, sie sind nur zugreifbar via JavaScript.
Die WHATWG beschreibt das System in der Web Applications 1.0-Spezifikation (auch bekannt als HTML5 bzw. XHTML5). Firefox 2 unterstützt es bereits.
Es wurden einfach zwei neue DOM-Objekte hinzugefügt:
sessionStorage
Hiermit hat man die Möglichkeit Daten über über mehrere Seiten, welche im selben Fenster geöffnet wurden, zu erhalten.
globalStorage
Bietet die Möglichkeit Daten solang für eine betreffende Domain zu erhalten, bis diese wieder gelöscht werden.
Der Zusammenhang zu den Cookies ist ersichtlich:
- Sitzungs-Cookies, die so lang gelten, bis das Browser-Fenster geschlossen wird
- und Cookies, welche über einen bestimmten Zeitraum gelten.
Das Storage-System wird Cookies allerdings nicht ersetzen, Cookies werden vom Server gesetzt und werden auch wieder an diesen gesendet, was sie keineswegs obsolet macht.
Aufgabengebiet des Systems sind also Web-Applikationen und Formulare, wobei hier noch einmal hingewiesen sei, dass (zu mindestens) bei Formularen jene vollständig ohne JavaScript funktionieren sollten, um die Zugänglichkeit zu wahren.
Erste Schritte
Sitzungsdaten (sessionStorage)
Wie einfach es ist Daten für eine Sitzung zu speichern, erläutert folgendes Beispiel:
Zunächst einmal möchten wir Daten speichern: Das geschieht im folgenden Beispiel, wenn der Benutzer etwas in das Feld eingibt. Es wird ein neuer Schlüssel erzeugt mit dem Namen userInput, welche den Wert des Feldes erhält.
<label>Welche Farbe hat Ihre Unterhose?</label>
<input type="text" onchange="sessionStorage.userInput = this.value">So einfach geht es, userInput bleibt nun so lang erhalten, bis alle Fenster (oder Tabs) der selben Domain geschlossen sind oder der Schlüssel wieder gelöscht wird.
Auf der nächsten Seite wird dann der Wert aus userInput in den Text eingefügt:
<p>
Die Farbe Ihrer Unterhose ist: <em id="unterhose">Unbekannt</em>
Sind Sie sicher? Viele Männer wissen das z.B. nicht.
</p>
<script type="text/javascript">
document.getElementById("unterhose").innerHTML = sessionStorage.userInput;
</script>Sehen Sie sich das Beispiel an
Global Daten speichern (gloabalStorage)
Daten global zu speichern ist ein wenig schwieriger, aber auch nicht wahnsinnig tragisch.
Zunächst einmal sollten wir mir globalStorage, welches uns eine Referenz auf das Objekt zurückgibt, welches alle Daten enthält, in einer Variable speichern:
var glob = globalStorage["lubyte.de"];Folgende Möglichkeiten hat man dabei:
- globalStorage[""] – Zugreifbar für alle Webseiten
- globalStorage["de"] – Zugreifbar für alle .de-Webseiten
- globalStorage["foobar.de"] – Zugreifbar nur von der Domain foobar.de
- globalStorage["www.lubyte.de"] – Zugreifbar von www.lubyte.de, aber nicht von lubyte.de bzw. trash.lubyte.de
Bemerkung: die ersten beiden funktionieren nicht mit der Firefox Beta 2.
Jetzt können wir bequem neue Schlüssel für das globale Storage-System hinzufügen:
glob.pageViews = 1;Und das ganze zusammengefasst in einem Beispiel:
<p>Sie sahen diese Seite bereits <span id="foo">unbekannt</span> mal.</p>
<script type="text/javascript">
var glob = globalStorage["lubyte.de"];
if (!glob.pageViews) glob.pageViews = 0;
glob.pageViews = parseInt(glob.pageViews) + 1;
document.getElementById("foo").innerHTML = glob.pageViews;
</script>Methoden und Eigenschaften des Storage-Objekts
Das Storage-System bietet auch Methoden und Eigenschaften, um mit den gespeicherten Daten zu arbeiten, sie sollen nicht unerklärt bleiben:
length
Gibt zurück wie viel Schlüssel bereits gespeichert wurden.
var a = sessionStorage; a.foo = "eins"; a.bar = "zwei"; alert(a.length); // gibt 2 auskey(n)
Gibt den Namen eines Schlüssel mit der Nummer n zurück. n geht dabei von 0 bis length - 1.
Z.B. können wir uns so bequem die Namen der Schlüssel ausgeben lassen:
for (var i = 0, eig = sessionStorage.length; i < eig; i++) { alert("Name: " + sessionStorage.key(i) + " Wert: " + sessionStorage.getItem(sessionStorage.key(i))); }getItem(Schlüssel)
Gibt den Wert zurück und erwartet den Namen des Schlüssels als Parameter.
sessionStorage.blubb = "blah"; alert(sessionStorage.getItem("blubb"));setItem(Schlüssel, Wert)
Erzeugt einen Schlüssel und weist diesem einen Wert zu, wenn der Schlüssel bereits vorhanden ist, wird er geändert.
globalStorage["test.com"].setItem("test", "faellt heute aus"); if (globalStorage["test.com"].test) { alert(globalStorage["test.com"].getItem("test")); }removeItem(Schlüssel)
Löscht einen Schlüssel und dessen Wert.
sessionStorage.removeItem("foo");
Weitere Möglichkeiten
Try...catch für globale Daten.
try {
var glob = globalStorage[""];
// mehr Sachen, die erledigt werden sollen
} catch (e) { // bei einem Fehler:
if (e.code == 1000) {
// Bedeutet, dass man aus Sicherheitsgründen
// nicht darauf zugreifen kann
}
throw e; // wirft den Fehler
}Das selbe ist ohne weiteres auch möglich für Sitzungen.
Testen, ob ein Schlüssel existiert
var session = sessionStorage;
if (session.fooBar) {
// Schlüssel ist existent
} else {
// Schlüssel fehlt
}Wert suchen
// Hilfsfunktion
Storage.prototype.findValue = function (value) {
var re = [];
for (var i = 0, len = this.length; i < len; i++) {
if (this.getItem(this.key(i)) == value) {
re.push(this.key(i));
}
}
return re;
};
// ein paar Schlüssel setzen
globalStorage["lubyte.de"].foo = "test";
globalStorage["lubyte.de"].bar = "test";
var glob = globalStorage["lubyte.de"];
/**
* Unsere neue Funktion ausführen
* Wurde als Prototyp zum Storage-System hinzugefügt
* Sie ist also auf das Storage-Objekt anwendbar
* z.B. sessionStorage.findValue(wert)
* Zurückgegeben wird dabei ein Array, das alle
* Schlüssel mit dem gesuchten Wert enthält
*/
var res = glob.findValue("test");
alert(res.join(":")); // Array zusammenfassen und ausgebenAlle Schlüssel löschen
Storage.prototype.removeAll = function () {
while (this.length > 0) { // so lang immer ein Schlüssel vorhanden ist
// löscht immer den ersten Schlüssel
// der zweite wird dann zum ersten usw.
this.removeItem(this.key(0));
}
}
function removeThisDamnItems () {
alert((sessionStorage.length + globalStorage["lubyte.de"].length)
+ "gespeicherte Schlüssel");
sessionStorage.removeAll();
globalStorage["lubyte.de"].removeAll();
alert("Jetzt sind es: " + (sessionStorage.length
+ globalStorage["lubyte.de"].length)
+ "gespeicherte Schlüssel");
}Ganze Objekte speichern
Folgendes ist nicht möglich:
sessionStorage.foo = { "bar" : "test" };
alert(sessionStorage.foo["bar"]);Allerdings geht das:
sessionStorage.foo.bar = "test";
alert(sessionStroage.foo.bar);Wenn man das Objekt foo mit for in durchgeht wird man merken, dass bereits weitere Objekte dort gespeichert sind: secure und value. Die Bedeutung ist z.Z. unklar.
Wenn man also ganze Objekte speichern möchte, müsste man beim späteren Durchgehen diese zwei Objekte ausklammern. Folgendes ist wiederrum möglich:
// sessionStorage.test muß es vorher geben:
sessionStorage.test = 1;
sessionStorage.test.foo = { 1 : "test", 2 : "bla" };
alert(sessionStorage.test.foo[1]); // gibt test aus
alert(sessionStorage.test); // gibt 1 ausBeispiele
Wunschzettel
// [...]
function addSomeEvents () { // fuegt die Events auf die Felder hinzu
var form = document.getElementById("formular");
for (var i = 0, len = form.elements.length; i < len; i++) {
var elem = form.elements[i];
var name = elem.name;
if (elem.tagName == "INPUT") {
if (elem.type == "radio") {
addEvent(elem, "click", saveToGlobal(elem, name));
} else if (elem.type == "text") {
addEvent(elem, "change", saveToGlobal(elem, name));
}
} else if (elem.tagName == "TEXTAREA") {
addEvent(elem, "change", saveToGlobal(elem, name));
}
}
}
// Funktion die in den globalen Speicher schreibt
function saveToGlobal (elem, name) {
return (function () {
window.globalStorage["www.lubyte.de"].setItem(name, elem.value);
});
}
function addData () { // Daten in Felder einfuegen
var glob = window.globalStorage["www.lubyte.de"];
// alle Werte durchgehen
for (var i = 0, len = glob.length; i < len; i++) {
var key = glob.key(i);
var item = glob.getItem(key);
var elems = document.getElementsByName(key);
// Wenn eine Element mit dem Namen des Schuessels existiert
if (elems) {
// wenn mehr als einer exitiert sind es unsere Radios
if (elems.length > 1) {
for (var i = 0, len = elems.length; i < len; i++) {
// setzt den passenden als checked
if (elems[i].value == item) elems[i].checked = true;
}
} else { // sonst einfach nur die Daten hinzufuegen
elems[0].value = item;
}
}
}
}
addEvent(window, "load", function () {
addData(); // fuegt gespeicherte Daten in die Felder
addSomeEvents(); // Fuegt EventListener auf die Elemente hinzu
// [...]
});Zusammenfassung
Auch wenn das Storage-System noch gänzlich nicht einsetzbar ist, bleibt jedoch abzuwarten, inwieweit andere Browser-Hersteller es auch implementieren werden.
Andere werde nachziehen, schliesslich sind einige namenhafte Browser-Hersteller Mitglied in der WHATWG.
Veröffentlichung: 12. September 2006 – Stand: 12. September 2006
