Parlando di persistenza delle informazioni sui browser, il primo pensiero va ai cookies, ancora indispensabili per preservare dati sul pc. Per migliorare le cose, il W3C ha inserito nella specifica HTML5 una sezione interamente dedicata al Web Storage.
La specifica introduce due meccanismi del tutto simili ai cookies per la memorizzazione di strutture dati lato client:
- localstorage
- sessionstorage
Attualmente i browser che supportano queste specifiche sono:
Browser | Dalla versione |
---|---|
Internet Explorer | 8 |
Firefox | 3.5 |
Chrome | 4 |
Safari | 4 |
Opera | 10.5 |
iPhone | 2.0 |
Android | 2.0 |
Prima di proseguire, è sempre bene effettuare alcuni test di feature detection per verificare che il browser supporti le specifiche che stiamo per utilizzare:
function supports_local_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch(e) {
return false;
}
}
Se il browser che stiamo usando è Firefox o Chrome, oltre al precedente controllo è importante verificare anche che i cookies siano abilitati. Per fare questo, usiamo una funzione come questa:
var cookieOK = (function() {
var id = new Date().getTime();
document.cookie = '__cookieOK=' + id + ';path=/';
if(document.cookie.indexOf(id) !== -1)
alert ("cookies disabilitati");
return ( document.cookie.indexOf(id) !== -1 );
})();
Questa funzione imposta un cookie e prova a leggerlo immediatamente. Se appare il messaggio di errore, non è possibile proseguire a meno di non modificare le impostazioni di sicurezza.
Il principio di funzionamento degli oggetti che stiamo per vedere, è simile a quello dei cookies: si basa sulla memorizzazione di coppie chiave/valore
e ad ogni chiave è associato un valore a cui è possibile accedere tramite la chiave stessa. Le funzioni standard impiegate sono dei getter
e setter
di proprietà, come possiamo vedere dalla specifica stessa:
interface Storage {
readonly attribute unsigned long length;
DOMString key(unsigned long index);
getter DOMString getItem(DOMString key);
setter creator void setItem(DOMString key, DOMString value);
deleter void removeItem(DOMString key);
void clear();
};
Per comprendere meglio il funzionamento, vediamo qualche esempio. È sufficiente creare un link nella pagina HTML ad un file Javascript esterno, oppure scrivere le funzioni direttamente dentro la pagina HTML all'interno del tag <script>
Ad ogni chiave si associa un valore invocando la funzione setItem()
:
localStorage.setItem("Colore","bianco");
Per accedere ai valori, utilizziamo la funzione getItem()
:
var valore = localStorage.getItem("Colore");
Da sottolineare che il valore ritornato da questa funzione è sempre di tipo stringa.
Supponiamo di aver memorizzato un intero:
localStorage.setItem("Age",31);
e di volerlo visualizzare dopo averlo sommato ad un altro numero:
var newAge = localStorage.getItem("Age") + 2;
il risultato ottenuto sarà 312, perché la funzione getItem()
Perché l'operazione sia eseguita correttamente, bisogna ricorrere a funzioni come parseInt()
o parseFloat()
, a seconda del tipo di dato contenuto nella stringa; in questo modo, la seguente operazione:
parseInt(localStorage.getItem("Age")) + 2;
darà il risultato corretto: 33.
Due casi particolari:
- setItem()
- getItem()
null
Come ogni altro oggetto di Javascript, anche localStorage può essere manipolato come un array associativo, pertanto:
var newAge = localStorage["Age"];
var newAge = localStorage.getItem("Age");
sono equivalenti.
Le voci salvate con le precedenti funzioni, rimangono sempre disponibili a meno di un'esplicita cancellazione da parte del programmatore: se non vengono rimosse infatti, essere saranno visibili anche dopo un eventuale riavvio del PC. Per rimuovere le coppi chiave/valore
ci sono due possibili soluzioni:
- localStorage.clear();
- localStorage.removeItem("Age");
Se cerchiamo di eliminare una chiave inesistente, l'operazione sarà ignorata.
La variabile length
infine, permette di visualizzare il totale delle voci memorizzate all'interno di un'istanza di localStorage o di sessionStorage:
var voce;
for( var i = 0; i < localStorage.length; i++) {
voce = localStorage.key(i) + " = " + localStorage.getItem(localStorage.key(i));
}
Otteniamo risultati simili a:
Colore = bianco
Di seguito esaminiamo l'esempio fatto nell'articolo in versione integrale: HTML e Javascript.
<body onload="showStorage()">
<div id="ctrl_storage">
<table>
<tr>
<td colspan="2">HTML5 Storage</td>
</tr>
<tr>
<td>Nome:</td>
<td id="mostra_nome"></td>
</tr>
<tr>
<td>Cognome:</td>
<td id="mostra_cognome"></td>
</tr>
</table>
<table>
<tr>
<td>Nome:<input type="text" id="nome"/></td>
<td><input type="button" value="Imposta nome" onclick="setNome()"/></td>
</tr>
<tr>
<td>Cognome:<input type="text" id="cognome"/></td>
<td><input type="button" value="Imposta cognome" onclick="setCognome()"/></td>
</tr>
</table>
</div>
</body>
Facciamo caso agli id che abbiamo assegnato agli elementi HTML utilizzati per rappresentare le voci conservate nell'istanza di localStorage, ovviamente saranno utilizzati come riferimenti nel codice Javascript:
function setNome() {
var nome = document.getElementById("nome").value;
localStorage.setItem("Nome",nome);
showStorage();
}
function setCognome() {
var cognome = document.getElementById("cognome").value;
localStorage.setItem("Cognome",cognome);
showStorage();
}
function showStorage() {
var nome = localStorage.getItem("Nome");
var cognome = localStorage.getItem("Cognome");
if (nome != null) { document.getElementById("mostra_nome").innerHTML = nome; }
if (cognome != null) { document.getElementById("mostra_cognome").innerHTML = cognome; }
showElem();
}
function showElem(){
var p = document.createElement("p");
for(var i = 0; i < localStorage.length; i++) {
p.innerHTML=localStorage.key(i)+"= "+localStorage.getItem(localStorage.key(i));
}
// volendo: p.innerHTML=localStorage.length;
document.getElementById("ctrl_storage").appendChild(p);
clearAll(); //facciamo pulizia!
}
function clearAll(){ localStorage.clear(); }
Limitazioni
Come indicato sulle specifiche del W3C, i browser limitano lo spazio che ogni istanza di storage ha a disposizione per ciascun sito. La dimensione stabilita è di 5MB per origine. È importante sottolineare che la specifica è ancora in fase "Draft", quindi facciamo attenzione a come la utilizziamo.