Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Dati offline, Web storage & Co.

Utilizzare Web storage per memorizzare piccole quantità di dati e sfruttare la serializzazione e deserializzazione in JSON
Utilizzare Web storage per memorizzare piccole quantità di dati e sfruttare la serializzazione e deserializzazione in JSON
Link copiato negli appunti

Nella lezione precedente abbiamo realizzato l'interfaccia grafica per la nostra applicazione utilizzando un po' di HTML e JavaScript e sfruttando il framework jQuery Mobile. Proseguiamo ora nella realizzazione del nostro progetto introducendo la possibilità per l'utente di salvare le schede relative all'immobile visionato.

Opzioni per lo storage offline

Le possibilità offerte da Apache Cordova per la memorizzazione di dati sul dispositivo sono sostanzialmente quelle proposte dalle specifiche che ruotano intorno ad HTML5. In pratica possiamo scegliere fra tre opzioni:

    1. Web storage

    Questa opzione si basa sulla specifica W3C che rappresenta in un certo senso l'evoluzione dei cookie: è prevista la possibilità di memorizzare coppie di stringhe chiave-valore a livello di sessione o permanentemente.

    Questa soluzione è molto semplice e comoda ma ha la limitazione sia del tipo di dato previsto (solo stringhe) sia delle dimensioni massime di memorizzazione, tipicamente 5 MB.

    2. Web SQL Database

    Rappresenta un'API per interfacciarsi con un vero e proprio database SQL locale. Purtroppo il W3C non continuerà il mantenimento delle specifiche dal momento che le implementazioni attuali utilizzano un unico backend, Sqlite, condizione non sufficiente per definire uno standard neutrale.

    3. File Access

    Questo approccio basato sulle specifiche W3C File API consente l'accesso al file system del dispositivo per la manipolazione di file e cartelle.

Indexed Database

Ci sarebbe in realtà un altro approccio, allo stato attuale non supportato ufficialmente da Apache Cordova, ma utilizzabile tramite un apposito polyfill: Indexed Database.

Si tratta di un approccio intermedio tra Web storage e Web SQL Database: consente la memorizzazione di dati strutturati supportando l'indicizzazione per un loro recupero efficiente, come avviene per un database relazionale. Le specifiche sono in corso di definizione per cui è ancora presto per stabilire se e come sarà supportato in futuro dal framework.

Salvataggio dei dati

Per le nostre esigenze adotteremo l'approccio basato sul Web storage, dal momento che non abbiamo necessità di memorizzare grandi quantità di dati e non abbiamo criteri di ricerca complessi. Inoltre la limitazione legata al tipo di dato supportato può essere aggirata tramite la serializzazione e deserializzazione dei dati in JSON.

Iniziamo a vedere come implementare il salvataggio delle nostre schede.

Per prima cosa aggiungiamo all'applicazione una proprietà storage che rappresenta il nostro aggancio al Web storage:

var app = {
	storage: window.localStorage,
	initialize: function() {
		this.bind();
	},
	//...
}

Attenzione ad utilizzare window.localStorage e non window.sessionStorage: il primo consente una memorizzazione permanente, mentre il secondo prevede una memorizzazione legata alla sessione di lavoro.

Aggiungiamo quindi all'oggetto scheda che avevamo creato nella puntata precedente la proprietà data che rappresenta i dati dell'immobile raccolti tramite la scheda:

var scheda = {
	data: {nome: "", indirizzo: "", descrizione: "", prezzo: "0,00"},
	// ...
}

A questo punto modifichiamo la gestione dell'evento tap sul pulsante Salva della scheda dell'immobile come mostrato di seguito:

$("#btnSalva").on("tap", function() {
	scheda.data.nome = $("#txtNome").val();
	scheda.data.indirizzo = $("#txtIndirizzo").val();
	scheda.data.descrizione = $("#txtDescrizione").val();
	scheda.data.prezzo = $("#txtPrezzo").val();
	scheda.save();
	navigator.notification.alert("Salvataggio effettuato!",function() {},"Informazione");
});

Abbiamo assegnato i valori correnti delle caselle di testo dell'interfaccia utente alle rispettive proprietà di scheda.data. Non ci resta che vedere come implementare il salvataggio vero e proprio della scheda:

var scheda = {
	//...
	save: function() {
		if (scheda.data.nome != "") {
			app.storage.setItem(scheda.data.nome, JSON.stringify(scheda.data));
		}
	},
	// ...
}

Il metodo save() verifica che sia stato assegnato un nome alla scheda, che per noi rappresenta una chiave univoca, e salva i dati tramite setItem(). Come possiamo vedere, a setItem() passiamo la chiave di memorizzazione, che ci consentirà di recuperare la scheda in un secondo momento, e la rappresentazione su stringa dell'oggetto scheda.data.

Recupero delle schede

Vediamo ora come recuperare le schede memorizzate tramite Web storage. Consideriamo il recupero dei dati delle schede in due fasi: la prima fase ci consentirà di creare dinamicamente l'elenco delle schede memorizzate mentre nella seconda fase recupereremo i dettagli dell'intera scheda.

Per generare l'elenco delle schede memorizzate interveniamo sull'evento pagebeforeshow della schermata elencoSchede. Si tratta dell'evento jQuery Mobile che si verifica prima della visualizzazione di una pagina.

bind: function() {
	// ...
	$("#elencoSchede").on("pagebeforeshow",
		function(event) {
			var elencoSchede = $("#liElencoSchede");
			elencoSchede.html("");
			for (var i=0; i<app.storage.length; i++) {
				var li = $("<li data-theme='c'>
						    <a href='#' data-transition='slide'>" +
                            app.storage.key(i) +
							"</a></li>");
				elencoSchede.append(li);
			}
			elencoSchede.listview("refresh");
		}
	);
	// ...
}

La prima cosa che facciamo è svuotare l'elenco corrente, quindi eseguiamo un ciclo sulla collection app.storage e per ciascun elemento trovato creiamo un item della listview assegnandogli come testo la chiave dell'elemento, cioè il nome della scheda. Aggiungiamo infine l'item all'elenco delle schede.

Fondamentale è il refresh finale della listview per garantire l'applicazione del tema grafico di jQuery Mobile agli elementi della lista.

Dal codice che abbiamo visto possiamo notare come gli elementi del Web storage non sono altro che elementi di una collection e che il metodo key() consente di recuperare la chiave dell'i-esimo elemento.

La lista così creata, però, mostra soltanto l'elenco delle schede e non da la possibilità di visualizzare i dettagli ed eventualmente modificarli. Per abilitare questa funzionalità dobbiamo gestire l'evento tap su ciascun elemento della listview e recuperare i dettagli della relativa scheda.

Per prima cosa vediamo come recuperare una scheda in base alla relativa chiave, cioè il nome. Implementiamo il metodo load() come mostrato di seguito:

var scheda = {
	// ...
	load: function(nome) {
		if (nome != "") {
			var value = app.storage.getItem($.trim(nome));
			scheda.data = JSON.parse(value);
		}
	},
	// ...
}

Dopo esserci assicurati che la chiave non sia vuota, sfruttiamo il metodo getItem() del Web storage per recuperare la stringa associata alla chiave. L'eliminazione di eventuali spazi iniziali e finali tramite il trim() di jQuery si rende necessaria per assicurarci che non ci siano caratteri estranei che possano compromettere il recupero della scheda. La stringa JSON così ottenuta viene convertita in oggetto ed assegnata alla proprietà data della scheda.

A questo punto ritorniamo nella porzione di codice che generava gli elementi della listview ed adattiamolo nel seguente modo:

// ...
for (var i=0; i<app.storage.length; i++) {
	var li = $("<li data-theme='c'>
	            <a href='#' data-transition='slide'>" +
				app.storage.key(i) +
				"</a></li>");
	li.on("tap", function() {
		scheda.load($(this).text());
		$("#txtNome").val(scheda.data.nome);
		$("#txtIndirizzo").val(scheda.data.indirizzo);
		$("#txtDescrizione").val(scheda.data.descrizione);
		$("#txtPrezzo").val(scheda.data.prezzo);
		$.mobile.changePage($("#scheda"));
	});
	elencoSchede.append(li);
}
// ...

Abbiamo associato all'evento tap di ciascun elemento della listview il caricamento della relativa scheda , l'assegnamento dei valori delle proprietà alle caselle di testo dell'interfaccia utente e la navigazione alla schermata della scheda. In questo modo avremo la possibilità di visualizzare ed eventualmente modificare i dettagli dell'immobile.

Eliminazione delle schede

Vogliamo infine dare la possibilità all'utente di eliminare una scheda precedentemente memorizzata.

Per far questo implementiamo il metodo delete() per l'oggetto scheda:

var scheda = {
	// ...
	delete: function(nome) {
		if (nome != "") {
			app.storage.removeItem($.trim(nome));
		}
	},
	//...
}

Anche in questo caso ci assicuriamo prima che sia stato specificato il nome della scheda e quindi la eliminiamo dal Web storage tramite il metodo removeItem().

Per consentire l'eliminazione della scheda abbiamo scelto di associare la funzionalità alla pressione prolungata sul'elemento della listview. Quindi associamo all'evento taphold il processo di eliminazione della scheda:

// ...
li.on("taphold", function() {
	var key = $(this).text();
	navigator.notification.confirm(
			"Confermi l'eliminazione della scheda?",
			function(buttonIndex) {
				if (buttonIndex == 1) {
					scheda.delete(key);
					$.mobile.changePage($("#elencoSchede"));
				}
			},
			"Conferma eliminazione",
			"Sì,No");
	});
// ...

In sintesi, recuperiamo il valore della chiave rappresentata dal nome della scheda corrente, chiediamo all'utente conferma dell'eliminazione tramite navigator.notification.confirm() e, in caso di conferma, invochiamo il metodo delete() della scheda e ricarichiamo l'elenco delle schede navigando alla schermata elencoSchede.

Con questo abbiamo completato la gestione delle schede memorizzate sul dispositivo. Proseguiremo nella prossima puntata la realizzazione della nostra applicazione implementando l'invio delle schede al server centrale.

Ti consigliamo anche