Come creare un app: realizzare una view di login con il localStorage
I metodi di salvataggio lato-client sono molto utili nel caso di applicazioni mobile sviluppate in HTML5, CSS3 e Javascript, ed è per questo che oggi voglio condividere con te un tutorial incentrato su un’altro sistema di salvataggio dati lato-client, il localStorage.
L’idea di scrivere questo post nasce dalla domanda di uno dei lettori di upCreative.net (a proposito, ringrazio sixdas per lo spunto) su come poter creare l’interfaccia di un’applicazione mobile che mostri all’utente una schermata di login oppure il contenuto dell’app, a seconda se è stato effettuato o meno il login con username e password.
Alle fine dell’articolo potrai trovare il link per il download dei file sorgenti.
Tutorial su come creare un app: l’obiettivo finale
In altre parole, all’avvio dell’applicazione controlleremo se nel localStorage è stata salvata una variabile che identifica l’username dell’utente: se è presente lo rimanderemo ai contenuti dell’applicazione, altrimenti visualizzeremo la schermata attraverso la quale egli potrà inserire i propri dati, che useremo poi per impostare la variabile di controllo nel localStorage.
Come view interna dell’app, quella accessibile solamente una volta effettuato il login, useremo la stessa del tutorial “Semplice Mobile App con Bootstrap Ratchet e Backbone.js” che ti ho mostrato in precedenza, che sarà quindi utilizzato come “base” per questo esperimento (in sostanza, quello che faremo è aggiungere la parte di login).
Il localStorage, di cui avevo parlato in questo articolo che ho scritto per YourInspirationWeb.com, è un sistema di salvataggio dati non-relazionale, che analogamente all’indexedDB, si basa sul concetto di coppia chiave-valore, per cui in corrispondenza di ogni chiave possiamo salvare qualsiasi tipo di variabile javascript: una stringa, un numero, un oggetto JSON e così via.
Noi lo utilizzeremo semplicemente per salvare l’username dell’utente in corrispondenza della chiave “user“, in modo da poter ricontrollare quella variabile ogni volta che l’applicazione viene avviata, ovvero ogni volta che il documento della pagina index.html viene ricaricato.
La view del login
L’esperimento precedente, basato su Backbone.js, era strutturato in questo modo:
Quello che dobbiamo fare è aggiungere la view di login, esattamente allo stesso livello DOM della view principale mostrata nell’immagine con il colore azzurro, ed effettuare il .render() di una o dell’altra, a seconda del contenuto della variabile del locaStorage.
Come prima cosa definiamo l’oggetto Backbone.View all’interno del file demo.js, il file javascript demo.js, in cui sono già presenti tutte le altre view:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
//view per il login che viene mostrata solo quando l'utente non è loggato var LoginView = Backbone.View.extend({ // comunichiamo a backbone che deve inserire il markup del template di questa view all'interno di un oggetto dal tag 'section' tagName: "section", //settiamo la classe che deve avere il tag 'section' className: "page-wrapper login-wrapper", //impostaiamo l'id del template da cui generare il markup di questa view template: "#loginview-template", initialize: function() { //compiliamo il template in una variabile this.template = _.template($(this.template).html()); this.AnimEndEventName = this.getAnimEndEventName(); }, //funzione che genera il markup di questa view render: function () { this.$el.html(this.template()); return this; }, /* Grazie a modernizr riprendo il nome dell'evento di fine animazione, che cambia a seconda del browser */ getAnimEndEventName: function(){ var animEndEventNames = { 'WebkitAnimation' : 'webkitAnimationEnd', 'OAnimation' : 'oAnimationEnd', 'msAnimation' : 'MSAnimationEnd', 'animation' : 'animationend' }; return animEndEventNames[ Modernizr.prefixed( 'animation' ) ]; }, // Deleghiamo gli eventi per la ricerca sull'input di testo events: { //evento //selettore //funzione da eseguire "submit form": "login" }, //funzione che gestosce il login del form login: function (e) { e.preventDefault(); var _this = this, form = $(e.currentTarget); username = $.trim(form.find("[name=username]").val()), password = $.trim(form.find("[name=password]").val()), submitBtn = form.find("button"); //controllo sulla lunghezza di username e password if(username.length==0 || password.length==0){ alert("Username e password sono obbligatori"); return; } //qui andrebbe il controllo username e password (magaro tramite SQLite, Web SQL o su Ajax mediante database) //ma per questo esperimento simuliamo la cosa con un setTimeout di 2 secondi submitBtn.text("Login in corso..."); setTimeout(function(){ submitBtn.text("Login"); //una volta verificate le credenziali di login salvo l'utente in modo persistente sul dispositivo tramite localStorage localStorage.setItem("user", username); //richiamo la funzione che inizializza i dati degli articoli e mostra la view della lista showList(); //nasondo la view di login in modo da mostrare quella degli articoli _this.hide(); }, 2000); }, show: function(callback){ var _this = this; //aggiungendo la classe 'opened' al contenitore di questa view //(elemento 'section.login-wrapper') innesco l'animazione di entrata this.$el.addClass("opened"); //se è stata passata una funzione di callback, la richiamo una volta terminato l'evento di fine animazione if(callback){ _this.$el.one( this.AnimEndEventName, function(){ callback(); }); } }, hide: function(callback){ var _this = this; //aggiungendo la classe 'hidden' al contenitore di questa view //(elemento 'section.login-wrapper') inneschiamo l'animazione di uscita _this.$el.addClass("hidden"); //al termine della'animazione, rimuoviamo l'oggetto DOM dal documento tramite il metodo backbone 'remove()', in modo da alleggerire il lavoro //della memoria centrale del dispositivo, contribuendo a rendere la nostra applicazione più fluida e performante _this.$el.on( this.AnimEndEventName, function(){ _this.remove(); //se è stata passata una funzione di callback, la richiamo una volta terminato l'evento di fine animazione if(callback) callback(); }); } }); |
Nel momento in cui si verifica l’evento submit del form di login, viene richiamato il metodo “login“, all’interno del quale, dopo aver verificato che username e password siano stati inseriti, simuliamo una richiesta al server con un setTimeout di 2 secondi, durante il quale cambiamo il testo del pulsante di login.
Al termine dei due secondi salviamo in corrispondenza della chiave “user” del localStorage l’username fornito dall’utente, mediante il metodo “.setItem()” e richiamiamo la funzione “showList”, che inizializzerà e mostrerà all’utente la view principale, quella che contiene la lista degli articoli (StartView) .
Come la view principale, anche quella di login utilizza come contenitore il tag <section> con con la classe “.page-wrapper“; in più è stata aggiunta la classe “login-wrapper” in modo da poter attribuire a questa view degli stili CSS aggiuntivi.
Grazie ad essi potremo infatti mostrare la view con un’animazione fluida e performante di tipo slideIn dal basso verso l’alto, che sfrutta la tecnica dell’accelerazione hardware.
Se vuoi approfondire il discorso delle animazioni fluide e perfomanti, e quello della tecnica dell’accelerazione hardware, forse potrebbe interessarti il seguente articolo:
Inoltre sono da sottolineare i due metodi “show” e “hide“, i quali aggiungono all’elemento contenitore della view (l’elemento DOM “section.login-wrapper”) le classi “opened” ed “hidden“, che scateno le animazioni CSS di entrata e di uscita.
Grazie a Modernizr, incluso nel documento all’interno del file index.html (nel tag <head>), riusciamo ad “agganciare” all’evento di fine animazione (il cui nome cambia a seconda del browser utilizzato dall’utente) una funzione nel momento in cui l’animazione definita nei CSS giunge al termine (vedi questo articolo per avere maggiori informazioni).
Gli stili CSS
Vediamo gli stili CSS3 utilizzati per definire la dinamica dell’animazione di entrata e di uscita della schermata di login:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
/* codice CSS3 performante per l'animazione della view di login */ section.login-wrapper { /*stili per il posizionamento*/ position: fixed; left: 0; top: 0; right: 0; bottom:0; z-index: 30; visibility: hidden; /* migliora le prestazioni prevenendo il render della parte 'posteriore' dell'elemento */ -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden; /* forziamo l'utilizzo della tecnica dell'accelerazione hardware per avere aniamzioni più fluide e reattive; mpostando come elemento scatenante per l'effetto la proprietà 'translate3d' il processo di rendering per l'elemento sarà delegato alla GPU (memoria grafica) prima, dopo e durante l'animazione */ -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); } section.login-wrapper.opened{ /* nel momento in cui all'elemento 'section.article-wrapper' viene aggiunta la classe 'show-article' innescchiamo l'animazione di entrata specifcandola in corrispondenza dell'attributo 'animation' */ -webkit-animation: showFromBottom .25s ease both; -moz-animation: showFromBottom .25s ease both; animation: showFromBottom .25s ease both; visibility: visible; } section.login-wrapper.hidden{ /* nel momento in cui all'elemento 'section.article-wrapper' viene aggiunta la classe 'hide-article' inneschiamo l'animazione di uscita specificandola in corrispondenza dell'attributo 'animation' */ -webkit-animation: hideToBottom .25s ease both; -moz-animation: hideToBottom .25s ease both; animation: hideToBottom .25s ease both; } /* definizione delle animazioni di entrata e di uscita per la view dell'articolo: muoviamo sempliemente l'elemento in verticale sull'asse delle ordinate */ /*animazione di entrata*/ @-webkit-keyframes showFromBottom { from { -webkit-transform: translateY(100%); } } @-moz-keyframes showFromBottom { from { -moz-transform: translateY(100%); } } @keyframes showFromBottom { from { transform: translateY(100%); } } /*animazione di uscita*/ @-webkit-keyframes hideToBottom { to { -webkit-transform: translateY(100%); } } @-moz-keyframes hideToBottom { to { -moz-transform: translateY(100%); } } @keyframes hideToBottom { to { transform: translateY(100%); } } |
La dinamica e le caratteristiche delle animazioni sono state riprese da uno dei miei precedenti tuorial sull’argomento. Per avere maggiori informazioni visita il relativo link:
Il template
Come prima cosa aggiungiamo il template della view all’interno del tag <body> file index.html, dove sono già presenti quelli della view principale, delle view della lista e della view dell’articolo singolo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!-- template per la view del login (LoginView su demo.js) --> <script type="text/template" id="loginview-template"> <header class="bar bar-nav"> <button class="btn btn-link btn-nav pull-left" onclick="window.location.href='http://www.upcreative.net/iscriviti-alla-newsletter/'"> Altre guide </button> <h1 class="title">Ultimi Articoli</h1> <button class="btn btn-link btn-nav pull-right" onclick="window.location.href='http://www.upCreative.net'"> upCreative.net </button> </header> <div class="content"> <h3>Effettua il login</h3> <form> <input type="text" name="username" placeholder="Username"> <input type="password" name="password" placeholder="Password"> <button class="btn btn-primary btn-block">Login</button> </form> </div> </script> |
Anche questa view, come le altre, è stata realizzata in modo tale che sfrutti gli stili di Ratchet 2, un set di CSS pronti da utilizzare come base per la realizzazione di una mobile app.
Al suo interno abbiamo inserito un semplice form di login con 2 campi per username e password.
Come creare un app: il controllo del login
Nell’esperimento precedente, dove il login non era presente, ci preoccupavamo subito di inizializzare la view princiaple; in questo tutorial dobbiamo invece controllare il contenuto della variabile localStorage per la chiave “user” prima di decidere se mostrare all’utente la view di login piuttosto che quella della lista degli articoli.
Pertanto inseriamo l’inizializzazione della view di iniziale (StartView) all’interno di una funzione denominata “showList“, in modo da poterla richiamare inizialmente oppure dopo che l’utente ha effettuato correttamente l’operazione di login:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
//per poter inizializzaere e mostrare la view della lista degli articoli in più parti dell'applicazione //la inseriamo all'interno di una funzione globale var showList = function(){ //creiamo una nuova istanza per la collection degli articoli con 4 models iniziali var articles = new ArticleList([ { title: "App su upCreative.net", image: "1.jpg", article: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." }, { title: "Secondo articolo su upCreative.net", image: "2.jpg", article: "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur" }, { title: "Articolo senza immagine 3", image: "3.jpg", article: "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat" }, { title: "Quarto articolo sulla lista", image: "4.jpg", article: "Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat" }, { title: "Quinto articolo sulla lista", image: "5.jpg", article: "Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat" }, { title: "Sesto articolo sulla lista", image: "1.jpg", article: "Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat" }, { title: "Settimo articolo sulla lista", image: "2.jpg", article: "Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat" } ]); //creiamo una nuova istanza per la view iniziale //associandogli la collection appena creata e popolata var startView = new StartView({ collection : articles }); $("body").append(startView.render().el); }; |
Una volta fatto ciò, non dovremo far altro che controllare la variabile “user” all’interno del localStorage, nel momento in cui l’applicazione viene lanciata:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$(function(){ //riprendo il contenuto della variabile "user" del localStorage var user = window.localStorage.getItem("user"); if(user){ //se in localStorage è presente un oggetto in corrispondenza della chiave "user", //allora significa che l'utente è già loggato, quindi mostriamo direttamente la view della lista degli articoli showList(); }else{ //se l'utente non è loggato (quindi il contenuto della variabile è vuoto), allora mostriamo la view di login var loginView = new LoginView(); $("body").append(loginView.render().el); loginView.show(); } }); |
Come creare un app: il pulsante di logout
Una volta predisposti la view di login ed il controllo della sessione tramite localStaorage, è buona norma aggiungere un pulsante per effettuare il logout, in modo da dare la possibilità all’utente di riaccedere con un username differente.
Inseriamo quindi nel template della view “StartView” un footer contenente il nuovo pulsante:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<!-- template per la view del contenuto iniziale (StartView su demo.js) --> <script type="text/template" id="startview-template"> <header class="bar bar-nav"> <button class="btn btn-link btn-nav pull-left" onclick="window.location.href='http://www.upcreative.net/iscriviti-alla-newsletter/'"> Altre guide </button> <h1 class="title">Ultimi Articoli</h1> <button class="btn btn-link btn-nav pull-right" onclick="window.location.href='http://www.upCreative.net'"> upCreative.net </button> </header> <div class="bar bar-standard bar-header-secondary"> <input class="search-term" placeholder="Cerca articoli" type="text"/> </div> <div class="content"> <div class="info"> <h4>Benvenuto/a "<%=username%>"</h4> <p>Prova ad aggiornare la pagina, il login non verrà richiesto, a meno che non venga effettuato il logout. ;) </p> </div> </div> <!-- Footer con il pulsante di logout --> <div class="bar bar-standard bar-footer"> <button class="btn btn-primary btn-block logout">Logout</button> </div> </script> |
Il click (o tap) su di esso sarà poi gestito all’interno della view di Backbone:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
var StartView = Backbone.View.extend({ ... // Deleghiamo gli eventi per la ricerca sull'input di testo events: { ... "click .logout": "logout" //gestione del pulsante di logout }, ... logout: function(){ var _this = this; //azzero la variabile del lovalStorage window.localStorage.removeItem("user"); //mostro di unovo la view di login, per poi rimuovere questa view var loginView = new LoginView(); $("body").append(loginView.render().el); loginView.show(function(){ _this.remove(); }); } }); |
Come puoi vedere dal codice, il compito del metodo “logout” è quello di azzerare la variabile di controllo di login e mostrare la view “LoginView“, per poi rimuovere quella corrente al termine dell’animazione di entrata (passando al metodo “show“, definito nella view di login, una funzione di callback).
Il risultato finale
Download dei sorgenti
Aiutami a condividere la risorsa per ottenere il download:
Crea la tua mobile app in HTML, CSS3 e Javascript
Utilizzando questa tecnica insieme a molte altre, ho realizzato più di 10 mobile app in HTML, CSS3 e Javascript (tra cui Tint e Dieta SI o NO?).
Se anche tu vuoi realizzare la tua applicazione in HTML, CSS e javascript da distribuire nei vari store, forse potrebbe interessarti il mio e-book HTML Mobile Accelerato.
Giacomo Freddi
Web Designer Freelance e Developer, si occupa del design e dello sviluppo di applicazioni web dal 2008, come molti freelance è abituato a gestire più ruoli e spaziare su più campi, ma la sua passione principale è quella della creazione di interfacce front-end e back-end utilizzando codice html5 e css3. Adora usare pattern MVC per i suoi Javascript.
Pingback: Come creare un app: la view di login con il loc...()
Pingback: Creare App Con Login - ITACCEDI()
Pingback: Creare App Con Login - Accedi.Biz()
Pingback: Accessi - Schermata Login App 【Updated April 2022】()
Pingback: Creare App Con Login【login Aggiornato August 2022】()