Często zachodzi potrzeba zapisania pewnych danych w przeglądarce klienta aby przyśpieszyć działanie serwisu bądź mieć możliwość wykorzystania tych danych po ponownym wejściu odwiedzającego na stronę. Można w tym celu wykorzystać ciasteczka, jednak ze względu na niewielki rozmiar danych, które można tam zapisać nie są one zbyt efektywnym sposobem przechowywania danych po stronie klienta. Znacznie lepszym sposobem jest skorzystanie z obiektów do tego przeznaczonych czyli globalStorage w przeglądarce Firefox 2 i userData w przeglądarce Internet Explorer 5+.

globalStorage w Firefox 2

W przypadku przeglądarki Mozilla Firefox 2 mamy do dyspozycji obiekty sessionStorage i globalStorage. Oba obiekty umożliwiają zapisywanie dowolnych danych z pamięci przeglądarki z tą różnicą, że pierwszy z nich usuwa dane po wygaśnięciu sesji czyli po zamknięciu okna przeglądarki a w przypadku drugiego okres ważności danych jest nieskończony. Ze względu na przydatność zajmę się tylko obiektem drugim czyli globalStorage. Maksymalna ilość danych w nim zapisanych wynosi 5 MB i właśnie tyle mamy do wykorzystania. Dane zapisywane są w pliku webappsstore.sqlite w katalogu profilu Firefoksa. Wykorzystując obiekt globalStorage należy zdefiniować domenę dla jakiej dane mają być dostępne. Można użyć zarówno pełnej nazwy domeny (np. bukox.pl), tylko końcówki domeny (np. pl) lub pustego ciągu oznaczającego, iż dane będą widoczne z każdej domeny. Przykład użycia:

JavaScript:
  1. store = globalStorage['bukox.pl'];
  2. // zapis danych do obiektu
  3. store.addItem('zmienna','wartosc');
  4.  
  5. // odczyt danych z obiektu
  6. alert(store.getItem('zmienna').value);
  7.  
  8. // usuniecie danych z obiektu
  9. store.removeItem('zmienna');

Więcej o obiektach storage w FF można znaleźć na stronie:
http://developer.mozilla.org/pl/docs/DOM:Storage
a specyfikacja DOM obiektu znajduje się pod adresem:
http://www.whatwg.org/specs/web-apps/current-work/#storage.

userData w Internet Explorer

Dla przeglądarki Internet Explorer począwszy od wersji 5 istnieje model userData, który także umożliwia zapisywanie danych użytkownika do pamięci przeglądarki. Rozmiar możliwych do zapisania danych jest zależny od strefy zabezpieczeń. Dla strefy internetu wynosi od 1 MB dla domeny i 128 KB dla dokumentu. Przykład użycia:

Najpierw należy wstawić dowolny znacznik, nadać mu identyfikator i odpowiedni styl:

HTML:
  1. <div id="globalStore" style="behavior: url(#default#userdata)"></div>

Następnie poprzez zwykłe nadanie atrybutu można dodać zmienną i wartość do obiektu:

JavaScript:
  1. // zapis danych do obiektu
  2. globalStore.setAttribute('zmienna','wartosc');
  3. globalStore.save('cache');
  4.  
  5. // odczyt danych z obiektu
  6. globalStore.load('cache');
  7. alert(globalStore.getAttribute('zmienna'));
  8.  
  9. // usuniecie danych z obiektu
  10. globalStore.load('cache');
  11. globalStore.setAttribute('zmienna','');
  12. globalStore.save('cache');

Więcej informacji o obiekcie userData w IE można znaleźć pod adresem:
http://msdn2.microsoft.com/en-us/library/ms531424.aspx.
Przykłady użycia można znaleźć na stronach: http://www.webreference.com/js/column24/userdata.html i http://www.eggheadcafe.com/articles/20010615.asp.

Dla innych przeglądarek póki co nie można wykorzystać podobnych mechanizmów i pozostaje jedynie skorzystanie z ciasteczek lub ograniczenie funkcjonalności tylko do dwóch powyższych. Ze względu na fakt, iż obiekt storage stanowi część specyfikacji DOM można mieć nadzieje, że w najbliższym czasie także pozostałe przeglądarki zostaną wyposażone w obsługę obiektu storage.

Mechanizm cache opisany powyżej umożliwia przechowywanie danych po stronie klienta i ich odczyt nawet po ponownym uruchomieniu przeglądarki. Dzięki temu można stworzyć aplikację internetową, która może działać całkowicie offline. Wystarczy, że podczas normalnej pracy online dynamiczne dane są zapisywane do cache'u a po rozłączeniu z internetem dane są z niego pobierane. Dodatkowo operacje modyfikujące także mogą zostać zapamiętane i po przywróceniu połączenia z internetem dane mogą zostać zsynchronizowane z serwerem.

Poniżej znajduje się kod kompletnej klasy implementującej cache po stronie klienta działający zarówno w IE5+ jak i FF2, który automatycznie tworzy ukrytą warstwę (dla IE) oraz umożliwia kontrolę okresu ważności zapisanych danych.

JavaScript:
  1. var TCache = function(domain) {
  2.     if(typeof globalStorage != "undefined") {
  3.         // jesli FF
  4.         if(typeof domain == "undefined") {
  5.             var domain = location.host;
  6.         }
  7.         this.storage = globalStorage[domain];
  8.     } else {
  9.         // jesli IE
  10.         if(!document.getElementById('globalStore')) {
  11.             // dynamicznie dodanie warstwy dla cache
  12.             var storageObj = document.createElement('DIV');
  13.             storageObj.id = 'globalStore';
  14.             storageObj.style.behavior = 'url(#default#userdata)';
  15.             storageObj.style.display = 'none';
  16.             document.body.appendChild(storageObj);
  17.         }
  18.         this.storage = globalStore;
  19.     }
  20. }
  21. TCache.prototype = {
  22.     /**
  23.      * Magazyn danych
  24.      *
  25.      * @var object
  26.      */
  27.     storage : null,
  28.     /**
  29.      * Funkcja zapisuje cache
  30.      *
  31.      * @param string name   Nazwa zmiennej cache 
  32.      * @param mixed data    Dane do zapisania
  33.      * @param int expires   Okres waznosci danych (w sek., domyslnie bez limitu)
  34.      * @return bool
  35.      */
  36.     save : function(name, data, expires) {
  37.         if(typeof globalStorage != "undefined") {
  38.             // jesli FF
  39.             this.storage.setItem(name, data);
  40.             if(typeof expires != "undefined") {
  41.                 var _this = this;
  42.                 setTimeout(function(){this.remove(name)}, expires*1000);
  43.             }
  44.             return true;
  45.         } else if(typeof this.storage.XMLDocument != "undefined") {
  46.             // jesli IE
  47.             if(typeof expires != "undefined") {
  48.                 var oTimeNow = new Date();
  49.                 oTimeNow.setSeconds(oTimeNow.getSeconds() + expires);
  50.                 this.storage.expires = oTimeNow.toUTCString();
  51.             }
  52.             this.storage.setAttribute(name, data);
  53.             this.storage.save('cache');
  54.             return true;
  55.         } else {
  56.             return false;
  57.         }
  58.     },
  59.     /**
  60.      * Funkcja pobiera dane z cache
  61.      *
  62.      * @param string name   Nazwa zmiennej cache
  63.      * @return mixed
  64.      */
  65.     get : function(name) {
  66.         if(typeof globalStorage != "undefined") {
  67.             // jesli FF
  68.             if(this.storage.getItem(name)) {
  69.                 var result = this.storage.getItem(name).value;
  70.             }
  71.         } else if(typeof this.storage.XMLDocument != "undefined") {
  72.             // jesli IE
  73.             this.storage.load('cache');
  74.             var result = this.storage.getAttribute(name);
  75.         }
  76.         return (result) ? result : null;
  77.     },
  78.     /**
  79.      * Funkcja usuwa zmienna z cache
  80.      *
  81.      * @param string name   Nazwa zmiennej
  82.      */
  83.     remove : function(name) {
  84.         if (typeof globalStorage != "undefined") {
  85.             // jesli FF
  86.             this.storage.removeItem(name);
  87.             return true;
  88.         } else if(typeof this.storage.XMLDocument != "undefined") {
  89.             // jesli IE
  90.             this.storage.load('cache');
  91.             this.storage.setAttribute(name, '');
  92.             this.storage.save('cache');
  93.             return true;
  94.         } else {
  95.             return false;
  96.         }
  97.     }
  98. }

Sposób użycia:

JavaScript:
  1. var cache = new TCache();
  2. cache.save('imie','adam');
  3. alert(cache.get('imie'));

Leave a Reply

You must be logged in to post a comment.