Releases: marcocasario/codemotion2014
MVC + RequireJS
Nuova release che prevede l'inclusione di RequireJS ed un approccio MVC sulla realizzazione delle pagine del sito web.
Il file js/main.js contiene tutte le informazioni su come inizializzare l'applicazione.
Webstorage & XHR2
Webstorage API - Communication API - Networking API
In questa esercitazione vedremo come funzionano e come applicare le Webstorage API, combinandole con le nuove XHR2 e le Networking API.
Utilizzeremo l'oggetto localstorage per storicizzare dati all'interno del browser.
Vedremo come funziona il caricamento di un'immagine trascinandola all'interno della pagina web dal proprio desktop.
Alla fine utilizzeremo le librerie per controllare lo stato della connessione per capire come prevenire eventuali perdite di dati.
Step 1. Predisposizione
Per avere una situazione stabile e funzionante puoi aggiornare il tuo sorgente direttamente da questo comando:
# !bash
# git checkout webstorage-dev
Git tiene traccia di tutte le modifiche fatte in locale, quindi per cambiare ramo dobbiamo prima annullare tutte le modifiche fatte sui file che abbiamo modificato con il comando:
# !bash
# git checkout *
Se vuoi mantenere le modifiche fatte, fai commit delle tue modifiche oppure clona il progetto in una nuova cartella!
se invece hai creato nuovi file, devi prima cancellarli.
Se non vuoi utilizzare git puoi scaricare l'archivio zip da qui: https://github.com/marcocasario/codemotion2014/tree/webstorage-dev
Webstorage API
Step 1. Utilizziamo le HTML5 Webstorage API
La nostra pagina dei contatti deve contenere nella parte centrale il form per l'inserimento dei dati anagrafici.
Aggiungiamo il form utilizzando i nuovi input type di HTML5:
Elenco dei campi:
- input type text class="input" id="firstname" name="firstname" il deve essere obbligatorio, possiamo eventualmente anche aggiungere l'autofocus
- input type email class="input" id="email" name="email" il campo deve essere obbligatorio
- input type data class="input" id="born" name="born" il campo deve essere obbligatorio
- input type text class="input" id="topic" name="topic" il campo deve essere obbligatorio, in questo caso implementare anche un oggetto di tipo datalist
- textarea class="textarea" id="note" name="note" il campo deve essere obbligatorio
per maggiori informazioni sui nuovi input type di HTML5 puoi consultare questo link http://www.w3.org/html/wg/drafts/html/master/forms.html
<form id="form" class="form_box">
<fieldset class="fieldset">
<ol>
<li class="left">
<label class="label" for="firstname">Name *</label><br>
<!-- input => firstname -->
</li>
<li class="right">
<label class="label" for="email">Email *</label><br>
<!-- input => email -->
</li>
</ol>
</fieldset>
<fieldset class="fieldset">
<ol>
<li class="left">
<label class="label" for="born">Date of birth *</label><br>
<!-- input => born -->
</li>
<li class="right">
<label class="label" for="topic">Topic *</label><br>
<!-- datalist => topic -->
</li>
</ol>
</fieldset>
<fieldset class="fieldset">
<ol>
<li class="left">
<label class="label" for="note">Note *</label><br>
<!-- textarea => note -->
</li>
</ol>
</fieldset>
<fieldset class="fieldset">
<button class="submit" type=submit>Send</button>
</fieldset>
</form>
Aggiorniamo il browser, il risultato dovrebbe essere simile a questo:
Step 2. Implementiamo quindi la nuova funzione saveUser:
/* Gestisce il salvataggio al click dell'utente sul tasto send del form */
function saveUser (e){
e.preventDefault();
//se i dati vengono popolati con successo, inviamo la richiesta al servizio
if ( userModel.setData($(this).serializeArray())){
saveLocalstorageData();
}
}
La funzione saveUser, viene chiamata al click sul tasto send (utilizzando jQuery).
La funzione saveUser() quando invocata richiama le seguenti funzioni:
userModel.setData();
saveLocalStorageData();
e.preventDefault() serve per bloccare il comportamento di default del browser al submit del form.
In alcuni casi (es: IE < 9) potrebbe essere necessario anche un return false;
Step 3. Iplementiamo l'oggetto userModel()
Aggiungiamo la seconda nostra funzione al file contact.js
/* Oggetto UserModel() */
function UserModel() {
//controlla se la variabile data è valorizzata altrimenti la inizializza come oggetto vuoto
if ( !isNotNull( data )){
var data = {};
}
//metodo setData()
this.setData = function ( newData ){
if (newData && newData.length > 0){
//se newData e' di tipo array (serializzato dal form)
//valorizziamo data con tutti gli elementi del form che sono stati inviati
for (var i = 0; i < newData.length; i++){
data[newData[i].name] = newData[i].value;
}
}else if ( isNotNull( newData ) ){
//se newData non e' un array valorizziamo data con newData
data = newData;
}else {
//altrimenti mostriamo un errore in console
console.log('Errore....');
return false;
}
return true;
};
//Restituisce l'oggetto data
this.getData = function (){
return data;
};
return this;
}
Questa funzione utilizza un metodo non nativo di Javascript isNotNull, questo metodo è definito all'interno del file js/main.js.
L'oggetto UserModel espone due metodi:
- setSata
- getData
Il primo valorizza l'oggetto data, il secondo lo restituisce.
Step 4. Aggiungiamo la funzione saveLocalstorageData()
Aggiungiamo la terza funzione al file contact.js, questa funzione scrive i dati all'interno del browser.
//salva i dati nel LocalStorage
function saveLocalstorageData( ){
console.log('Salvataggio dei dati utente', userModel);
//utilizza l'oggetto localStorage per salvare i dati all'interno del browser
localStorage.setItem('userData', JSON.stringify(userModel.getData()))
return true;
}
L'oggetto localStorage espone due metodi usati da questo esercizio:
- setItem
- getItem
In questa funzione, utilizzeremo localStorage.setItem(), è possibile sperimentare cambiando l'oggetto localstorage con sessionStorage.
Per maggiori informazioni sulle API: http://www.w3.org/TR/webstorage/
A questo punto non ci resta che inizializzare il nostro oggetto UserModel ed aggiungere un evento al submit del form.
//inizializziamo il modello
var userModel = new UserModel;
//aggiungiamo l'evento al submit
$('#form').submit(saveUser);
in chrome apriamo i Developer Tools, facciamo click sulla scheda Resources. il risultato dovrebbe essere molto simile a questo:
Step 5. Recupero dei dati
Una volta salvati i dati, quando rientriamo all'interno del form ancora non vengono recuperati.
Per recuperare i dati è molto semplice:
Creiamo una nuova funzione, che sarà richiamata ogni volta al caricamento della pagina:
function getUserInformation (){
//richiediamo i dati all'oggetto e popoliamo il model
var response = localStorage.getItem('userData');
userModel.setData( JSON.parse(response) );
setFormData( userModel );
}
Aggiungiamo la funzione che si occupa quindi di popolare il form direttamente dai localStorage.
function setFormData (){
//recuperiamo le informazioni dal datamodel
var data = userModel.getData();
//se l'oggetto è valorizzato aggiungiamo i valori agli input del nostro form
if (isNotNull( data )) {
$('#firstname').val( data.firstname );
$('#email').val( data.email );
$('#born').val( data.born );
$('#topic').val( data.topic );
$('#note').val( data.note );
}
}
Il metodo getUser() deve essere richiamato subito dopo la creazione del model
//inizializziamo il modello var userModel = new UserModel; //recuperiamo i dati dall'oggetto localStorage getUserInformation(); //aggiungiamo l'evento al submit $('#form').submit(saveUser);
Una volta salvati i dati all'interno dell'oggetto sessionStorage, al caricamento della pagina se questi dati sono presenti, il codice che abbiamo appena implementato li recupera e li inserisce per noi all'interno del form.
Communication API
Step 1. Aggiungiamo i nuovi oggetti all'interno del form:
<fieldset class="fieldset">
<ol>
<li class="left" id="upload">
<label class="label" for="fileupload">Allega la tua foto</label><br>
<div id="holder"></div>
<p id="upload" class="hidden"><label>Drag & drop non supportato, ma puoi comunque inviare la tua foto:<br><input type="file" id="fileupload" name="fileupload"></label></p>
<p id="filereader">File API & FileReader API non supportati</p>
<p id="formdata">XHR2's FormData non è supportato</p>
<p id="progress">XHR2's upload progress non supportato</p>
<p>Trasferimento: <progress id="uploadprogress" min="0" max="100" value="0">0</progress></p>
<p>Trascina e rilascia un'immagine dal tuo desktop nell'area tratteggiata.</p>
</li>
</ol>
</fieldset>
All'interno del codice troviamo un nuovo fieldset che serve per ospitare il drag&drop.
L'elemento più importante è holder, questa sarà l'area visibile dall'utente dove poter rilasciare l'oggetto trascinato dal proprio browser.
Gli altri elementi servono per effettuare dei test lato javascript e mostrare i rispettivi messaggi, diversi in base al browser che stiamo usando.
Ag...
Websocket API
Websocket API
In questa esercitazione vedremo come utilizzare le connessioni Websocket di HTML5 realizzando una chat.
Step 1. Predisposizione
# git checkout webstorage-dev
facciamo partire il server!
per fermare l'istanza precedente, premi 'CTRL+C'.
Step 2. Il modulo nodejs-websocket
La versione del server realizzato in node js, in questo esercizio deve essere modificata.
La prima versione rispondeva alla porta indicata oppure alla porta 8888.
In questo caso dobbiamo creare una nuova porta, che ci consenta di aprire una connessione websocket con il client che apre la pagina web.
Installiamo il nuovo modulo
Per poter funzionare, il server websocket ha bisogno di un nuovo modulo, che non è installato di default da node.js.
Direttamente da command line, installiamolo utilizzando il gestore di pacchetti npm di nodejs:
# npm install nodejs-websocket
Per verificare che tutto sia andato a buon fine, all'interno del nostro progetto è stata creata una nuova cartella node_modules. Al suo interno è stata creata un'altra cartella nodejs-websocket.
Step 3. Il codice HTML
Creiamo una nuova area dove saranno visualizzati i messaggi, sostituiamo l'attuale
<section class="banner_section"></section>
con il seguente codice:
<section id="support_section" class="support_section text_style">
<div class="welcome_message_area">Benvenuto, il supporto tecnico ti fornirà le informazioni necessarie per ogni tua esigenza.</div>
<div class="title_message_area hide">Dashboard</div>
<ul class="message_area"></ul>
</section>
All'interno del nostro
inseriremo invece le informazioni necessarie per dare la possibilità all'utente di scegliere un nickname e una volta effettuato il "login" di inviare un nuovo messaggio.Ecco il codice per fare il login:
<article class="article clearfix nickname_area">
<form id="form_nickname" class="form_box">
<fieldset class="fieldset">
<ol>
<li class="left">
<label class="label" for="nickname">Nickname *</label><br>
<input class="input" id="nickname" name="nickname" type="text" placeholder="Inserisci il tuo nickname" required autofocus>
</li>
<li><br><button class="submit" type=submit>Send</button></li>
</ol>
</fieldset>
</form>
</article>
Aggiungiamo subito dopo anche il codice per scrivere un nuovo messaggio:
<article class="article clearfix send_message_area hide">
<form id="form_message" class="form_box">
<fieldset class="fieldset">
<ol>
<li class="left">
<label class="label" for="message">Inserisci il messaggio</label><br>
<input class="input" id="message" name="message" type="text" placeholder="nuovo messaggio" required autofocus>
</li>
<li><br><button class="submit" type=submit>Send</button></li>
</ol>
</fieldset>
</form>
</article>
I moduli appena inseriti sono dei semplici input type:text con relativo submit per inviare i dati al server.
Effettuati questi passaggi il risultato ottenuto sarà molto simile a questo:
Step 4. Modifichiamo il css
aggiungiamo una nuova regola per il contenitore ed il box che ospiterà i messaggi che arrivano dal server.
.support_section { width: 880px; height: 200px; padding: 0 40px; background: #fff; }
.message_area{ height: 150px }
Aggiungiamo gli stili che devono essere associati ai form nickname e new message:
.support_section .form_box { padding: 0 10px; }
.support_section .form_box .input { width: 268px; }
.support_section .form_box .submit { width: 298px; float: none; }
infine aggiungiamo tre semplici classi per cambiare il colore dei messaggi che appariranno in base al tipo di informazione visualizzata.
.user_message{ list-style: none; margin-bottom: 10px; border-bottom: 1px solid #e8e8e8;}
.in{color: green;}
.out{color: red;}
.msg{ color: #888888; }
Step 4. Implementiamo il nostro codice javascript
Apriamo il file js/helpdesk.js
Cominciamo con il definire l'oggetto che si occuperà di gestire la nostra micro applicazione help-desk:
//inizializziamo app
var app = {
connection: {},
nickname: '',
status: 'closed'
};
In questa occasione, utilizziamo Modernizr per controllare se è disponibile la connessione websocket.
Creiamo quindi una nuova parte di codice che sarà istanziata non appena il documento è pronto utilizzando jQuery:
$(document).ready( function (){
if (!Modernizr.websockets) {
alert("No WebSocket here");
}
});
Aggiungiamo quindi dopo il controllo il codice per intercettare l'evento al submit del form relativo al nickname:
//form event submit
$('#form_nickname').submit(function (event) {
//evitiamo il submit del form
event.preventDefault();
if ( setNickname() ){
hide( $('.nickname_area') );
show( $('.send_message_area') );
setWSConnection();
}
//evitiamo il submit del form
return false;
});
Fatto questo, possiamo aggiungere anche l'evento al submit del form per l'invio del messaggio:
$('#form_message').submit(function (event) {
//evitiamo il submit del form
event.preventDefault();
sendWsMessage();
//evitiamo il submit del form
return false;
});
Se ci concentriamo sul codice scritto per l'invio del form relativo al nickname, possiamo notare come prima della funzione setWSConnection() venga richiamata la setNickname(), vediamo di seguito cosa fa:
//valorizza l'oggetto app.nickname
function setNickname(){
var newNickname = $('#nickname').val();
if ( isNotNull( newNickname ) && newNickname.length > 3){
app.nickname = newNickname;
return true;
}
return false;
}
Valorizza il nostro oggetto app.nickname, con il nickname scelto dall'utente.
A questo punto possiamo occuparci della setWSConnection():
// funzione che si occupa dell'invio dei messaggi al server websocket.
function setWSConnection(){
if (isNotNull( app.nickname )){
clearDomMessages();
app.connection = new WebSocket("ws://"+window.location.hostname+":8890")
app.connection.onopen = function () {
console.log("Connection opened");
app.connection.send(app.nickname);
app.connection.status = 'open';
}
app.connection.onclose = function () {
var newMessage = {"status":"out", "msg": "connection closed", "time": new Date()};
setDomMessage(newMessage);
app.connection.status = 'close';
}
app.connection.onerror = function () {
var newMessage = {"status":"out", "msg": "Connection error", "time": new Date()};
setDomMessage(newMessage);
app.connection.status = 'close';
}
app.connection.onmessage = function (event) {
setDomMessage(event.data);
}
}
}
A questo punto completiamo il nostro script con le funzioni richiamate dalla
//pulisce l'area messaggi alla prima connessione dell'utente.
function clearDomMessages(){
$('.welcome_message_area').hide();
$('.title_message_area').show();
$('.message_area').empty();
}
//scrive i messaggi che arrivano dal server mentre la connessione websocket resta in ascolto
function setDomMessage( message ){
var newMessage = jQuery.parseJSON( message ),
element = document.createElement('li'),
domElement = $('.message_area'),
time = '';
function getTime(){
var newTime = new Date(newMessage.time);
return newTime.getUTCHours()+":"+newTime.getUTCMinutes();
}
time = getTime();
element.className = 'user_message'+' ' + newMessage.status;
element.appendChild (document.createTextNode("["+time+"] " + newMessage.message) );
domElement.append( element );
domElement.animate({'scrollTop': domElement[0].scrollHeight});
}
//chiude la connessione al server webSocket
function closeWSConnection(){
if (app.connection.status === 'open'){
app.connection.close();
app.connection.status = 'closed';
}
}
// funzione per inviare i messaggi al server WS
function sendWsMessage(){
var message = $('#message').val();
if ( isNotNull( message )){
console.log('Invio del messaggio al server: ' + message);
app.connection.send(message);
$('#message').val('');
}
}
Login degli utenti
Nuovo messaggio
Logout degli utenti
RWD - Responsive Web Design
Installare ed usare il mediaBookmarklet
Il mediaQuery Bookmarklet è uno strumento utile in fase di progettazione e di test delle mediaqueries.
Step 1. Installare mediaQuery bookmarklet
Il tool funziona su:
- Chrome 9+
- Safari 5.1.5
- iOS 5.1.1
Aggiungere un nuovo bookmark con il seguente contenuto:
javascript:%20(function%20()%20{var%20jsCode%20=%20document.createElement(%27script%27);jsCode.setAttribute(%27src%27,%20%27http://sparkbox.github.com/mediaQueryBookmarklet/bookmarklet-js/mediaQueryBookmarklet.js%27);document.body.appendChild(jsCode);}());
Oppure, a questo indirizzo trovi la pagina ufficiale per installare il tool.
Una volta aggiunto sulla barra, per utilizzarlo sarà sufficiente cliccare sul link. Così facendo il tool verrà immediatamente eseguito.
Step 2. Usare il bookmarklet
Una volta lanciato il bookmarklet mostrerà una nuova "finestra" sul browser con le informazioni riguardo la dimensione in pixel della finestra del browser, la posizione del mouse in coordinate x e y, e il valore del min-width espresso in em.
Cambiando la dimensione della finestra i valori nel box cambieranno di conseguenza. Questo tool ci permetterà, in fase di progettazione del sito, di capire a che risoluzioni applicare le mediaquery, ed in fase di test di vedere con precisione quando le mediaqueries verranno applicate
Step 3. Ulteriori tool per il responsive
Segue una lista di tool utili per lo sviluppo con le mediaquery:
Analisi della pagina alle basse risoluzioni
L'approccio mobile first (o mobile up) è quello che parte dalla progettazione della pagina alle basse risoluzioni per vedere come si comporta il contenuto.
Step 1. Aprire la pagina
Aprire nel browser la pagina index.html
Aprire il codice sorgente e studiare velocemente la struttura semantica della pagina.
Analizzare come la pagina si comporta all'interno del browser.
Step 3. mediaQuery bookmarklet in azione
Lanciare il bookmarklet. Comparirà un box in alto a sinistra con le informazioni riguardo la dimensione in pixel della finestra del browser, la posizione del mouse in coordinate x e y, e il valore del min-width espresso in em.
Step 4. Analisi del comportamento alle basse risoluzioni
La pagina che stiamo visualizzando non ha nessuna specifica impostata relativa alla media query.
Portiamo alla risoluzione più bassa (almeno 400px) restringendo la finestra del browser e leggendo i valori nel box del mediaQuery tool.
Definiamo quindi i seguenti punti
- cosa deve succedere al sito quando visualizzo la pagina con risoluzioni basse.
- qual'è il suo comportamento.
- come si deve disporre il contenuto.
Step 5. Implementiamo il comportamento desiderato del contenuto alle basse risoluzioni
Una volta definito in che modo pa pagina dovrà visualizzarsi all'interno del browser, si comincia con la progettazione della prima media query, quella che definirà come il contnenuto dovrà disporsi nella viewport del browser.
Applichiamo le media query per smartphone
Stiamo usando l'approccio Mobile First (o Mobile Up) e partiamo quindi dalla risoluzione più bassa.La prima media query che vogliamo intercettare è quella che scatta dalla risoluzione più bassa alla risoluzione massima di 479px.
Step 1. Cominciamo inserendo alla fine del file style.css il blocco che mi permette di definire gli statement CSS per la media query:
/***** Media Queries *****/
/* Small screen */
@media only screen and (max-width: 479px) {
}
Al suo interno cominciamo ad implementare le istruzioni per definire il comportamento dei componenti principali:
- container
- header
- main_section
- aside
- footer
Step 2. Specifichiamo al suo interno le seguenti proprietà
Una volta aggiunta la media query che scatterà non appena la risoluzione andrà sotto i 479px, possiamo comunicare al browser cosa dovrà accadere.
Il layout a questa risoluzione deve svilupparsi verticalmente, con tutti gli elementi renderizzati uno sotto l'altro. Cominciamo nascondendo gli elementi come menù e banner che non devono essere visualizzati da un device come lo smartphone applicando il "display:none;"
#header #nav ul { display: none; }
.banner_section { display: none; }
Modifichiamo quindi anche la dimensione del contenitore della nostra pagina.
#container { width: 320px; box-shadow: none; }
Salva ed aggiorna la pagina per visualizzare i cambiamenti
Il risultato ottenuto dovrebbe essere molto simile a questo:
Step 3. Definiamo per gli elementi la nuova dimensione e gli allineamenti da rispettare:
Diamo le nuove dimensioni al container principale all'header ed al footer:
#header { width: 300px; height: 80px; padding: 0 10px; }
#header .logo {
background: url('../img/logo_small.png') center center no-repeat;
width: 130px;
height: 42px;
text-indent: -9999px;
float: left;
margin: 0 auto;
float: none;
padding-top: 40px;
}
#header #nav .menu {
display: block;
visibility: visible;
width: 34px;
height: 24px;
background: url('../img/menu.png') center center no-repeat;
position: absolute;
top: 30px;
right: 10px;
text-indent: -9999px;
}
Analizziamo nel dettaglio cosa è cambiato:
- #header .logo: cambia la dimensione, il formato del logo, i margini e l'allineamento;
- #header #nav .menu: viene mostrato con i margini e l'allineamento a destra;
Salva ed aggiorna la pagina per visualizzare i cambiamenti
Il risultato ottenuto dovrebbe essere il seguente:
Step 4. Definiamo ora il comportamento che la parte centrale e della parte destra (aside) del sito web.
.main_section {
width: 320px;
float: none;
padding: 20px 0;
}
.main_section .article {
border-bottom: 1px solid #ccc;
margin-bottom: 40px;
padding: 0 10px 40px;
}
.main_section .article .figure { display: none; }
.main_section .article h1 { width: 300px; float: none; }
.main_section .article p { width: 300px; float: none; }
Analizziamo nel dettaglio cosa è cambiato con queste modifiche:
- .main_section: nuove dimensioni, modifica dei margini, ed è stato rimosso l'allineamento.
- .main_section .article: aggiunto il bordo inferiore, sistemati i margini dell'oggetto
- .main_section .article .figure: tutte le immagini non vengono renderizzate
- .main_section .article h1/p: nuova dimensione ed allineamento
Salva ed aggiorna la pagina per visualizzare i cambiamenti
Il risultato dovrebbe essere molto simile a questo:
Step 4. Aside
Fino ad ora abbiamo lavorato sulla parte superiore e centrale della nostra pagina, il prossimo passo è quello di definire il comportamento della barra destra della pagina.
Il contenuto di essa deve scorrere dopo la parte centrale, quindi definiamo allineamenti e margini, anche in questo caso le immagini non devono essere renderizzate:
#aside {
width: 300px;
float: none;
padding: 20px 10px;
border-left: none;
border-top: 1px solid #ccc;
}
#aside .callout_text {
float: none;
width: 300px;
margin-top: 30px;
}
#aside .callout_text li { margin: 30px 10px; }
#aside .callout_images { display: none; }
Step 5.
Come ultimo step non ci resta che modificare anche il footer, in questo casolo solo per le dimensioni ed i margini:
#footer {
width: 300px;
padding: 30px 10px;
text-align: center;
}
#footer .copy { float: none; margin-bottom: 20px; }
#footer .privacy { float: none; }
Salva ed aggiorna la pagina per visualizzare i cambiamenti, in questo modo abbiamo terminato lo sviluppo della versione mobile.
Il risultato del lavoro fatto:
Analisi della pagina per le risoluzioni Tablet e Small Tablet
Come fatto per la sezione smartphone, analizziamo e progettiamo il comportamento della nostra pagina con una risoluzione più grande, decidiamo in che modo il contenuto deve disporsi all'interno della pagina.
Small Tablet
Step.1 Apriamo la pagina
Portiamola alla risoluzione tablet (almeno 600px) restringendo la finestra del browser e leggendo i valori nel box del mediaQuery tool.
Definiamo quindi i seguenti punti:
- cosa deve succedere al sito quando visualizzo la pagina con una risoluzione simile.
- qual'è il suo comportamento.
- come si deve disporre il contenuto.
Step.2 Applichiamo le media query per tablet
Sempre con un approccio Mobile First, la nostra seconda media query che vogliamo intercettare è quella che scatta ad una risoluzione tra 480px e 767px.
/* Small Tablet */
@media only screen and (min-width: 480px) and (max-width: 767px) {
}
Step.3 Applichiamo le modifiche progettate
Come abbiamo già fatto per la parte smartphone, al suo interno implementeremo le istruzioni per definire il comportamento dei componenti pr...
Geolocation API + Google Maps
Obiettivo del lab: lavorare con le informazioni sulla geolocalizzazione.
Step 1. Predisposizione
In questo lab utilizzeremo le Geolocation API, alcuni browser possono bloccare l'accesso a queste informazioni se effettuiamo l'accesso diretto da file system, quindi avremo bisogno di un server http.
Per avere una situazione stabile e funzionante puoi aggiornare il tuo sorgente direttamente da questo comando:
# !bash
# git checkout geolocation-dev
Git tiene traccia di tutte le modifiche fatte in locale, quindi per cambiare ramo dobbiamo prima annullare tutte le modifiche fatte sui file che abbiamo modificato. con il comando:
# !bash
# git checkout *
Se vuoi mantenere le modifiche fatte, clona il progetto in una nuova cartella!
se invece hai creato nuovi file, devi prima cancellarli.
Se non vuoi utilizzare git puoi scaricare l'archivio zip da qui: https://github.com/marcocasario/codemotion2014/tree/responsive-dev
Step 2. Facciamo partire il server!
Con il seguente comando, creeremo un nuovo server http, realizzato direttamente con node.js.
# node server.js
Step 3. Lavoriamo con le HTML5 Geolocation API
Apriamo il file js/company.js, ed aggiungiamo una nuova funzione per la nostra pagina web.
/* @company.js */
/* Comincia la nostra applicazione */
function loadDemo() {
}
Al suo interno aggiungiamo il controllo per verificare che il browser supporti le Geolocation API:
/* @company.js */
if(navigator.geolocation) {
}
Inseriamo all'interno del "if" il codice per caricare le informazioni sulla geolocalizzazione dell'utente che sta visitando la pagina utilizzando la funzione:
/* @company.js */
navigator.geolocation.getCurrentPosition(
function(position) {
//inserire il codice per aggiornare gli elementi della pagina
},
function(error){
alert('error reported' + error);
}, {
enableHighAccuracy: true,
timeout : 30000
}
);
Step 4. Modifichiamo il DOM
A questo punto possiamo cambiare il dom del nostro file company.html per ospitare le informazioni che ci arrivano dall'oggetto geolocation.
All'interno della
aggiungiamo dei div specificando una classe/id per ognuno di questi attributi:- accuracy
- altitude
- altitudeAccuracy
- heading
- latitude
- longitude
- speed
<!-- @company.html -->
<article class="article clearfix">
<div class="left">Accuracy: </div><div class="accuracy right">0</div><br>
<div class="left">Altitude: </div><div class="altitude right">0</div><br>
<div class="left">Altitude Accuracy: </div><div class="altitudeAccuracy right">0</div><br>
<div class="left">Heading: </div><div class="heading right">0</div><br>
<div class="left">Latitude: </div><div class="latitude right">0</div><br>
<div class="left">Longitude: </div><div class="longitude right">0</div><br>
<div class="left">Speed: </div><div class="speed right">0</div>
</article>
A questo punto all'interno della funzione javascript possiamo utilizzare jquery per popolare la nostra pagina web con le informazioni che ci arrivano dall'oggetto position.
/* @company.js */
$('.accuracy').html( position.coords.accuracy );
$('.altitude').html( position.coords.altitude );
$('.altitudeAccuracy').html( position.coords.altitudeAccuracy );
$('.heading').html( position.coords.heading );
$('.latitude').html( position.coords.latitude );
$('.longitude').html( position.coords.longitude );
Quando sei pronto per fare il primo test, ricorda di aggiungere in fondo al tuo company.js il comando per inizializzare tutta la funzione appena creata.
/* @company.js */
/* Inizializzazione del codice */
loadDemo();
Salva ed aggiorna la pagina http://localhost:8888 il risultato dovrebbe essere il seguente:
Cliccando su consenti, daremo tutte le informazioni sulla nostra posizione alla pagina.
Il risultato sarà il seguente:
Integriamo le Google API
Step 1. Includiamo le librerie
Includiamo la libreria nel file company.html
<!-- Google Maps: change key to be your site's ID. -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC3nvub6YdbJZLIKdNjcVDfh2vPbI60vus&sensor=false"></script>
Per funzionare, le api di google hanno bisogno di una APIKey, in questo caso è stata generata una generica che trovi già all'interno del codice.
Step 2. Predisposizione dell'area per far ospitare la mappa
Dobbiamo predisporre la nostra pagina HTML ad ospitare la mappa da visualizzare all'interno della pagina.
Sostituiamo la
<section id="map-canvas" class="map_section"></section>
Aggiungiamo una nuova regola all'interno del nostro css:
.map_section { width: 880px; background: #fff url('../img/loader.gif') center center no-repeat; border-bottom: 1px solid #ccc; padding: 0 40px; height: 440px;}
Step 3. Utilizzo delle librerie
Aggiungiamo una nuova funzione "loadMap" all'interno del nostro file company.js, questa funzione avrà lo scopo di richiedere le informazioni direttamente al servizio google maps e di restituirci la cartina con la nostra posizione direttamente all'interno del div "banner_section".
/* @company.js */
function loadMap(lon,lat){
//definiamo le variabili utilizzate dalla funzione
var myLatlng = new google.maps.LatLng(lat,lon),
bound = new google.maps.LatLngBounds(),
mapOptions = {},
map = {};
//creiamo il nuovo oggeto, che google utilizza per centrare la mappa.
bound.extend( myLatlng ),
//definiamo le opzioni per la creazione della mappa
mapOptions = {
center: bound.getCenter(),
zoom: 12,
};
//Istanziamo il nuovo oggetto google.maps.Map();
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
}
Richiamiamo la nostra funzione con le relative proprietà.
$('.longitude').html( position.coords.longitude );
//richiamiamo la funzione che richiede ed include la mappa passando la posizione attuale.
loadMap(position.coords.longitude, position.coords.latitude);
Aggiorniamo la nostra pagina web e visualizziamo il risultato ottenuto.
A questo punto non ci resta che aggiungere il marker che indica all'interno della mappa dove ci troviamo!
Aggiungendo queste poche righe dopo la ri-definizione dell'oggetto map comparirà il marker nativo di google.
/* @compan.js => loadMap() */
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
new google.maps.Marker({
position: myLatlng,
map: map,
title:"Sono qui!",
animation: 'bounce'
});
Salva ed aggiorna la pagina http://localhost:8888
Il risultato dovrebbe essere molto simile a questo:
Step 4. Aggiungiamo il percorso per raggiungere la sede
Aggiungiamo delle nuove variabili all'interno della funzione loadMap.
Impostiamo nei primi due latitudine e longitudine del punto di arrivo.
La terza è il nostro oggetto google con il punto sulla mappa.
directionsDisplay e directionsService richiamano i servizi google per inizializzare gli oggetti necessari per richiedere la direzione e per effettuare il render sulla mappa.
var locationLatitude = 41.901556, locationLongitude = 12.502005, //Stazione di Roma Termini
locationLatlng = new google.maps.LatLng(locationLatitude,locationLongitude),
directionsDisplay = new google.maps.DirectionsRenderer(),
directionsService = new google.maps.DirectionsService();
Successivamente scriviamo una nuova funzione all'interno della loadMap() che chiama le api di google e chiede il percorso da fare partendo dai due punti.
inserire la funzione dopo la dichiarazione delle variabili
function calcolaPercorso() {
var request = {
origin:myLatlng,
destination:locationLatlng,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
}
});
}
Come ultimo passaggio, dopo la definizione del nostro primo marker, possiamo richiamare la funzione appena definita ed effettuare il render sulla mappa
//add direction information
calcolaPercorso();
//set map to directionsDisplay object
directionsDisplay.setMap(map);
Salva ed aggiorna la pagina http://localhost:8888
Bootstrapping with Yeoman and HTML5Boilerplate
Componenti necessari
Di seguito sono elencati tutti i software necessari per procedere con i LAB
Installare Node JS
scaricare ed installare l'ultima versione di nodejs dal sito http://nodejs.org/ il sito web intuisce il sistema operativo utilizzato.
Tutti i possibili download li trovate a questo indirizzo: http://nodejs.org/download/
Gli utilizzatori di linux o virtual machine con linux (es: ubuntu, debian) possono seguire questa utile guida: https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager
Seguire quindi tutti i passaggi per completare l'installazione.
Installare Yeoman
Installato nodejs avremo a disposizione la gestione dei pacchetti direttamente da nodejs con il comando
For npm versions < 1.2.10.
Il parametro -g installa il pacchetto a livello globale# npm install -g yo
Bower & Grunt
# npm install -g grunt-cli bower
Installare il generatore di template HTML5 Boilerplate
# npm install -g generator-h5bp
Inizializzare il progetto
Ora siamo tutti gli strumenti necessari per inizializzare il progetto con il comando:
Creiamo una nuova cartella "codemotion"
# mkdir codemotion
Spostiamoci al suo interno e lanciamo il comando:
# yo h5bp
Il comando appena eseguito crea un progetto vuoto con tutte le risorse necessarie.
Analizziamo il contenuto del progetto con tutte le librerie scaricate.
Come si può notare aprendo i file css/html scaricati, il contenuto ha tutto il necessario per iniziare un nuovo progetto da zero senza perdere tempo con le classiche impostazioni.
Inizializzare il progetto Codemotion2014
Per tutti i lab eseguiti durante il corso, è possibile utilizzare alcuni comandi di git per clonare e spostarsi all'interno dei vari step che il progetto prevede.
La struttura del progetto che realizzeremo è disponibile al seguente indirizzo: https://github.com/marcocasario/codemotion2014/tree/responsive-dev
e cliccare quindi su Download ZIP
Chi preferisce utilizzare git può clonare il progetto direttamente da questo indirizzo: https://github.com/marcocasario/codemotion2014/tree/responsive-dev
oppure utilizzando il comando da shell:
# git clone https://github.com/marcocasario/codemotion2014.git
spostiamoci dentro la cartella 'codemotion2014' creata automaticamente dal comando 'git clone'.
A questo punto possiamo spostarci all'interno del ramo di sviluppo:
# git checkout responsive-dev
Apriamo la pagina index.html sul nostro browser, il risultato ottenuto deve essere questo: