Standard HTML5 zdefiniował nowe miejsce do długotrwałego przechowania danych. Zobaczmy czym localStorage różni się od cookies i jak wykorzystać tę przestrzeń na praktycznym przykładzie.
W standardzie HTML5 zdefiniowano jednolite dla wszystkich przeglądarek magazyny danych. Pozwalają one przechowywać informacje po stronie użytkownika, co umożliwia tworzenie aplikacji działających częściowo bez dostępu do Internetu. Najprostszym przykładem może być lista zadań do zrobienia, do której użytkownik ma dostęp również będąc offline.
LocalStorage a cookies
Szczególnie interesujący jest magazyn localStorage (http://dev.w3.org/html5/webstorage/). Ten obszar pamięci jest niedostępny dla serwera, a przechowywane w nim dane nie mają „terminu ważności”, po którym zostałyby usunięte. Można uzyskać łatwy dostęp do nich za pomocą JavaScriptu i Flasha. Dostęp do danych mają jednak tylko skrypty z domeny, z której pochodzą zapisane informacje. Kontrola nad dostępem leży po stronie przeglądarki, a użytkownik ani twórca skryptu nie mogą zmienić „pochodzenia” danego klucza. Zapisane w localStorage obiekty służą do długotrwałego przechowywania danych i pozostają na dysku po zamknięciu przeglądarki.
W przeciwieństwie do cookies, obiekty z localStorage nie są automatycznie odczytywane przez serwer przy połączeniu. Należy je przekazać za pomocą AJAX-u. Ponadto rozmiar przechowywanych w ten sposób danych jest znacznie większy niż w przypadku cookies.
Firefox, Chrome i Opera rezerwują 10MB na domenę, a Internet Explorer 100MB na wszystkie przechowywane dane, przy czym wartość te można zmienić na maksymalnie 20GB. Dane przechowywane są jako tablice asocjacyjne, których kluczem i wartością jest łańcuch znaków. LocalStorage jest obsługiwane przez przeglądarki Chrome 4, Safari 4, Firefox 3.5, Opera 10.5, Internet Explorer 8 i nowsze oraz przeglądarki w smartfonach korzystających z systemów Android, iPhone OS i BlackBerry OS 6. Niestety implementacja standardu w chwili pisania artykułu nie była jeszcze wszędzie taka sama.
SessionStorage
HTML5 definiuje również inne magazyny danych. Jednym z nich jest sessionStorage. To odpowiednik cookies, ale o większym rozmiarze. Dane są wysyłane tylko na żądanie, a nie z każdym zapytaniem wysyłanym do serwera. Ponadto sessionStorage można przypisać do konkretnej karty przeglądarki, co pozwala na pracę w oddzielnych sesjach na tej samej stronie. Obiekty sessionStorage zostają skasowane po zakończeniu sesji.
Web SQL Database
Kolejnym magazynem miało być Web SQL Database. Ta przestrzeń miała przechowywać dane w formie relacyjnej bazy danych po stronie użytkownika. Chrome, Safari i Opera obsługują Web SQL Database, a twórcy stron zaczynali już wdrażać pierwsze projekty wykorzystujące ten mechanizm. Niestety 18 listopada 2010 W3C niespodziewanie ogłosiło, że Web SQL Database nie będzie rozwijane (http://www.w3.org/TR/webdatabase/). Mozilla zaproponowała, aby miejsce Web SQL Database zostało zajęte przez Indexed Database API (http://www.w3.org/TR/IndexedDB/ – obiektową bazę danych działającą po stronie użytkownika.
Tworzymy aplikację z wykorzystaniem ocalStorage
Wykorzystanie localStorage zaprezentujemy na przykładzie. Załóżmy, że tworzymy aplikację, która pozwala księgowej na prowadzenie małej bazy danych. Zawarte są w niej nazwiska pracowników i ich pensje. Księgowa może dodać do bazy nowego użytkownika, zmienić mu pensję albo wykasować go z listy pracowników. Może ponadto wyświetlić listę wszystkich pracowników i ich pensje. Jako że są to informacje poufne, nie chcemy wysyłać ich na serwer. Przechowamy je więc w przestrzeni localStorage.
Zakładamy, że nazwisko jest kluczem głównym, tzn. jeden pracownik może mieć przypisaną co najwyżej jedną wysokość pensji. Aby nie zaciemniać obrazu, zakładamy ponadto, że pensje są zawsze wprowadzane poprawnie (w rzeczywistości należałoby sprawdzić czy są liczbą i poprosić o potwierdzenie w przypadku zmiany), a w firmie pracuje tylko jeden pracownik o danym nazwisku (w rzeczywistości klucz powinien być bardziej złożony, np. NIP albo unikalny identyfikator pracownika). Ponadto nie jest tworzona żadna kopia zapasowa danych – są one przechowywane jedynie w pamięci przeglądarki.
Zaczynamy od utworzenia formularza. Będzie on miał dwa pola odpowiedzialne za wyświetlanie i edycję nazwiska oraz pensji:
Do tego dodamy cztery przyciski:
Dodawanie danych do localStorage
Przyciski wywołują funkcje JavaScriptu odpowiedzialne za konkretne akcje. Przycisk Zapisz doda do bazy nowy wpis o kluczu takim jak zawartość pola Nazwisko i jego wartości takiej jak wartość pola Pensja. Jeśli w bazie istnieje już wpis dotyczący tego nazwiska, wartość jego pensji zostanie zmienione. Odpowiada za to funkcja { html}zapisz(){ /html}.
function zapisz() {
localStorage.setItem(
document.forms.formularz.nazwisko.value ,
document.forms.formularz.pensja.value
);
}
Za pomocą metody { html}setItem( klucz, wartość ){ /html} do localStorage zostaje dodany odpowiedni wpis. Wartości pobierane są za pomocą instrukcji { html}document.forms.NAZWA_FROMULARZA.NAZWA_POLA.value{ /html}.
Odczyt danych z localStorage
Przycisk Odczytaj znajdzie w bazie wpis o kluczu takim jak zawartość pola Nazwisko i wstawi ją do pola Pensja. Do pobrania wartości służy metoda { html}getItem( klucz ){ /html}, którą użyliśmy w funkcji { html}odczytaj(){ /html}. Wartość pola Nazwisko pobierana jest tak jak powyżej, a wartość pola Pensja zapisujemy w podobny sposób: { html}document.forms.NAZWA_FROMULARZA.NAZWA_POLA.value = NOWA_WARTOSC{ /html}.
function odczytaj() {
document.forms.formularz.pensja.value =
localStorage.getItem( document.forms.formularz.nazwisko.value );
}
Usuwanie danych z localStorage
Przycisk Kasuj usuwa z localStorage element o kluczu takim jak wartość wpisana w polu Nazwisko formularza. Do kasowania pojedynczych wpisów służy metoda { html}localStorage.removeItem(klucz){ /html}. Wykorzystaliśmy ją w funkcji { html}skasuj(){ /html}. Odczytywanie i zapisywanie wartości pól formularzy odbywa się tak jak powyżej.
function skasuj() {
document.forms.formularz.data.value =
localStorage.removeItem( document.forms.formularz.nazwisko.value );
}
Przeglądanie wszystkich wpisów
Cała zawartość localStorage przyporządkowana do domeny, pod którą działa nasza aplikacja zostanie wyświetlona za pomocą nieco bardziej skomplikowanej funkcji { html}wyswietl(){ /hrml}.
function wyswietl() {
var zawartosc = '';
for(var klucz in localStorage)
zawartosc += ( klucz + ' ' + localStorage.getItem( klucz ) + 'rn' );
alert ( zawartosc );
}
Funkcja { html}wyswietl(){ /html} tworzy nowy łańcuch znaków o nazwie „zawartosc”, w którym zostaje zapisana liczba kluczy zgromadzonych przez aplikację w localStorage. Odpowiada za to atrybut { html}length{ /html}. Następnie za pomocą funkcji { html}for( klucz in zbiór ){ /html} przeglądane są wszystkie elementy w localStorage utworzone przez naszą aplikację. Aktualnie przeglądany element dostaje tymczasową nazwę „klucz”.
Dla każdego elementu do zmiennej „zawartosc” dopisywana jest nazwa aktualnie przeglądanego klucza i jego wartość. Na samym końcu funkcja wyświetla komunikat zawierający nazwiska i pensje wszystkich pracowników.
Opisaną aplikację zamieściliśmy w pliku przyklad.html. Aby nie zaciemniać obrazu pozwoliliśmy sobie na niezbyt eleganckie, ale za to czytelne, dołączenie funkcji do poszczególnych przycisków za pomocą atrybutu onclick.
Podsumowując, localStorage to narzędzie podobne do cookies, ale różniące się kilkoma szczegółami. Pozwala przechowywać więcej danych, nie są one usuwane po określonym czasie, a użytkownik nie może ich łatwo modyfikować. Ponadto odwołanie się do danych przez JavaScript jest prostsze, a dane nie są wysyłane na serwer. Te cechy zasadniczo zmieniają sposób wykorzystania technologii localStorage i dają zupełnie nowe możliwości tworzenia aplikacji.