Dec 172012
 

Il metodo di jQuery Mobile change page serve per cambiare pagina, la cosa è banale se non fosse per il meccanismo ajax che governa il passaggio.

Prepariamo dunque la nostra solita pagina e invece di incorporare il link nell’html lo gestiamo da programmazione.


<!DOCTYPE html>
<html>
<head>
<title>Change Page</title>
<meta name="viewport"
content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
<script>
...
</script>
</head>
<body>
<div data-role="page">
<div data-role="header"><h1>Change page</h1></div>
<div data-role="content"><a href="#" id="change" data-role="button">Change Page</a></div>
</div>
</body>
</html>

Il binding dell’evento per gestire tutto da programmazione lo facciamo con javascript:

$(document).ready(function() {
$(‘#change’).on(‘click’, function(event) {
$.mobile.changePage(’43b-change-page.html’,{transition: ‘fade’});
});
});

usiamo il metodo on che è quello da preferire.

Per visualizzare il meccanismo ajax la pagina di destinazione conterrà solo l’html senza i link alle librerie:


<!DOCTYPE html>
<html>
<head>
<title>Linked Page</title>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Linked File</h1>
</div>

<div data-role="content">
<p><a href="43-change-page.html">Link to an original
file</a></p>
</div>

</div>
</body>
</html>

Tramite l’esempio si può vedere come venga applicato il parsing di jquery mobile e di conseguenza come ci sia un’iniezione di contenuti via ajax.

Dec 142012
 

Nello scenario di un massiccio ricorso ad ajax da parte di jQuery Mobile, è opportuno considerare lla necessità di visualizzare un messaggio che avverta del caricamento in corso delle nostra pagina chiamata, in modo che anche chi accederà con connessioni lente non abbia  il dubbio che la pagina non stia funzionando debitamente.

jQuery Mobile dispone già di tutto il necessario perché questo avvenga e sarà quindi necessario solamente intercettare l’evento e utilizzare la funziona opportuna.

Nella pagina predisporremo dunque due bottoni uno per mostrare il messaggio e l’altro per nasconderlo:

<a href="#" id="show" data-role="button">Show</a>
<a href="#" id="hide" data-role="button">Hide</a>

e mediante il metodo on andremo ad associare al click sui bottoni la visualizzazone del messaggio di attesa oppure la sua rimozione:

$('#show').on('click', function(){$.mobile.showPageLoadingMsg();})
$('#hide').on('click', function(){$.mobile.hidePageLoadingMsg();})

Questo link per fare il test.

Dec 122012
 

jQuery Mobile usa ajax come scelta preferienzale per caricare altri contenuti.

Usiamo come esempio questa semplice pagina:

<!DOCTYPE html>
<html>
<head>
<title>Linking AJAX</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header"><h1>Linking AJAX</h1></div>
<div data-role="content">
<p><a href="04b-link.html">Link to an external file</a></p>
<p><a href="04b-link.html" data-prefetch>Prefetch the external file</a></p>
</div>
</div>
</body>
</html>

Come si può vedere esaminadno il codice sorgente della pagina caricata, che non porta con sé il caricamento agli script necessari e al css, effettivamente lo schema utilizzato è ajax, il secondo link procede anche a un precaricamento, tecnica utile per velocizzare la fruizione dei contenuti ma della quale è bene non abusare.

Il codice della 04b-link.html:

<!DOCTYPE html>
<html>
<head>
<title>Linked Page</title>
</head>
<body>
<div data-role="page">
<div data-role="header"><h1>File linkato</h1></div>
<div data-role="content">
<p><a href="04-linking-ajax.html">Link al file originale</a></p>
</div>
</div>
</body>
</html>

Accedendo direttamente a questa pagina apparirà appunto completamente non formatta a riprova di quanto detto.

L’esempio

Dec 022012
 

una seconda possibilità di gestire i form in jQuery Mobile è adottare delle soluzioni one page basandosi su ajax.

Per fare questo proveremo una pagina di lgoin con ritorno al form se la login fallisce oppure visualizzazione di un’altra pagina se la login va a buon fine.

Partiamo con le classiche intestazioni:


<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<link rel=”stylesheet” href=”http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css” />
<script src=”http://code.jquery.com/jquery-1.8.2.min.js”></script>
<script src=”http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js”></script>

In seguito creiamo la pagina di login con uno span dove eventualmente inserire il messaggio di errore:


<div data-role=”page” id=”login”>
<div data-role=”header”>
<h1>My Title</h1>
</div>
<span id=”error”></span>
<form id=”login_user” data-ajax=”false”>
<label>Email:</label>
<input type=”text” id=”email” name=”email”>
<label>Password:</label>
<input type=”text” id=”pwd” name=”pwd”>
<button type=”submit”>Submit</button>
</form>
</div>
</div>

Successivamente predisponiamo una semplicissima seconda pagina per il post login:


<div data-role=”page” id=”loginok”>
<div data-role=”header”>
<h1>My Title</h1>
</div>>
<div data-role=”content”>
<span id=”test”></span>
</div>
</div>

Passiamo alla sostanza, cioè al document.ready intercettiamo il submit del form e blocchiamo il comportamento di default:


$(document).ready(function(e) {
$(‘#login_user’).on(‘submit’, function (e) {
e.preventDefault();

In seconda battuta pre paro una variabile per il mio form e procedo con il post dei dati sulla form.php:


var $this = $(this);
$.post(
‘form.php’,
$this.serialize(),

I dati inseriti saranno passati con il metodo serialize().

La form.php è sostanzialmente “finta” ovvero è basata su un if anche se nella realtà verificherà le credenziali nel database.


<?php
$email=$_POST['email'];
$pwd=$_POST['pwd'];
if($email==’pippo@tin.it’ && $pwd==’pippo’){echo ‘ok’;}
else{echo ‘ko’;}
?>

Quindi se lo user è pippo@tin.it e la pwd pippo la login andrà a buon fine risponderà ok, viceversa la pagina risponderà ko

Andiamo a gestire la risposta:


function (str){
if(str==’ok’){
$(‘#test’).html(str);
$.mobile.changePage(‘#loginok’)
}
else{
$(‘#error’).html(‘Errore login’);
$.mobile.changePage(‘#login’)
}

Se la risposta è ok, l’utente visualizzerà la pagina in loginok, altrimenti inseriremo un messaggio nello span con id=error

e ritorneremo sulla logi.

L’esempio

Nov 142012
 

Proseguiamo il lavoro impostato nel precendete post e concretizziamo il drag&drop memorizzando le informazioni con opportune chiamate ajax.
Andremo ad aggiungere anche alcune funzionalità piuttosto comuni.

Ci portiamo nell’area droppable e aggiungiamo l’evento drop:

drop:function(event,ui){
var id=ui.draggable.attr(‘id’);

recuperiamo l’id dell’elemento trascinato, quindi lo mandiamo al server web per l’inserimento nel db:

$.ajax({
type:’GET’,
url:’dati/inserisci.php?id=’+id,
success:function(str){
if(str==’OK’){

se va tutto bene aggiungiamo l’elemento alla landing area, insieme a un campo quantità e a un link elimina:


if(str==’ok’){
$(‘<div id=”elemento_’+id+’”></div>’)
.append(ui.draggable.html())
.append(‘<input type=”text” id=”qt_’+id+’” value=”1″ /><br />’)
.append(‘<a href=”#’+id+’”>Elimina</a>’)
.appendTo(‘#landing_area’)
$(‘#’+id).fadeOut(2000);
}

infine nascondiamo l’elemento dalla lista dei draggable

Restano da gestire l’input della quantità e il link elimina.
Useremo il metodo live perché vengono creati runtime, anche se sarebbe preferibile usare on

Quindi procediamo con 3 operazioni relative all’elimina:
1. rimettiamo l’elemnto nella lista
2. lo rimuoviamo dalla landing area
3. lo cancelliamo dal database:

$(‘#landing_area a’).live(‘click’, function(){
var id=$(this).attr(‘href’);
$(id).fadeIn(2000);
$(this).parent().remove();
//rimuovere dal db
$.get(‘data/test.php?id=’+id,function(){/**/})
})

si noti la forimula this parente per rimuovere l’elemnto padre del link

Per quanto riguarda la quantità molto più semplicemente si tratta di fare un update:

$(‘#landing_area input’).live(‘blur’, function(){
var id=$(this).attr(‘id’);
var qt=$(this).val();
//aggiorna qt su db
$.get(‘data/test.php?id=’+id+’&qt=’+qt,function(){/**/})
})

quindi leggo i valori e li invio al server web.

L’esempio

Nov 112012
 

Vediamo come trascinare determinati elementi all’interno di un’area di atterraggio selezionata.
Nell’html andiamo ad impostare, all’interno di un contenitore, 5 div che trascineremo e un’area di atterraggio:

<div id="contenitore"><div id=”box1″><p>Prodotto 1</p></div>
<div id=”box2″><p>Prodotto 2</p></div>
<div id=”box3″><p>Prodotto 3</p></div>
<div id=”box4″><p>Prodotto 4</p></div>
<div id=”box5″><p>Prodotto 5</p></div>
<div id=”landing_area”></div></div>
<div>

Per comodità i div da trascinare hanno id e la medesima classe, questo velocizzerà anche la creazione del css:

.box{ width:100px; height:60px; border:1px solid #000; margin-bottom:10px; padding:5px; z-index:1;}
#box1{ background-color:#FC0;}
#box2{ background-color:#9CF;}
#box3{ background-color:#96F;}
#box4{ background-color:#6C9;}
#box5{ background-color:#9F3;}
#landing_area{ width:200px; height:300px; position:absolute; top:8px; left:200px; padding:5px; border:2px solid #900; z-index:0; }

Lo stile è spartano, serve solo per distinguere gli oggetti.
Si noti però che gli elementoi da trascinare hanno uno z-index superiore all’area di atterraggio.

Per la nostra attività necessitiamo di Jquery e jQuery UI:


<script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js”></script>
<script src=”http://code.jquery.com/ui/1.9.0/jquery-ui.js”></script>

che includiamo nell’head della pagina insieme al css di default:


<link rel=”stylesheet” type=”text/css” href=”http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css” />

A questo punto rendiamo trascinabile tutti gli elementi di classe box:

$(document).ready(function(e) {
$(‘.box’).draggable();
})

Se vogliamo arricchire i comportamenti, possiamo aggiungere una classe che rende trasparente l’oggetto appena iniziamo a trascinarlo e facciamo in modo che una volta rilasciato torni al suo posto:

$(‘.box’).draggable({
revert:true,
start:function(event,ui){$(this).addClass(‘movimento’);},
stop:function(event,ui){
$(this).removeClass(‘movimento’);
}
});

La classe movimento aggiunge solo l’opacità:

.movimento{ opacity:0.5;}

al rilascio ovviamente la togliamo

Volete sapere dove avete rilasciato il vostro oggetto?
La pagina è un piano cartesiano, quindi:

var top=ui.position['top'];
var left=ui.position['left'];
alert(top+’ ‘+left);

Infine predisponiamo l’area di atterraggio:

$(‘#landing_area’).droppable({
accept:’.box’,
tolerance:’fit’
});

Dove stabiliamo gli elementi che accettiamo, tutta la classe box e quando li possiamo considerare all’interno dell’area
con il parametro tolerance, a volte potrebbe bastare toccare le pareti, altre volte bisognerà essere completamente all’interno

Esempio

Oct 312012
 

Affontiamo il problema della validazione dei form, problema annoso in passato ma oggi risolvibile più agevolemnte.

Useremo jQuery e il suo plugin jQuery Validate per risolvere la nostra questione, per inciso il plugin è in sé interessante poiché definisce i metodi di validazione più comuni, inoltre permette l’estensione con l’aggiunta di personalizzazioni.

Partiamo dal form con 3 campi di input obbligatori: il nome, l’email e lo username:


<form name=”info” id=”info”>
<fieldset>
<legend>Dati</legend>
<label for=”nome”>Nome</label><br />
<input type=”text” id=”nome” name=”nome” /><br /><br />
<label for=”email”>Email</label><br />
<input type=”text” id=”email” name=”email” /><br /><br />
<label for=”username”>Username</label><br />
<input type=”text” id=”username” name=”username” /><br /><br />
<input type=”button” id=”submit” value=”invia” />
</fieldset>
</form>

Nell’html mettiamo anche un div nascosto che useremo per dialogare con i nostri utenti:


<div id=”dialog” title=”Test”></div>

Prepariamo anche lo stile della label per la gestione degli errori:


label.error{ font:bold 14px Arial; color:#900;}

Passiamo alla parte di validazione vera e propria. Come prima cosa al caricamento della pagina agganciamo gli eventi che vogliamo gestire.

Il primo sarà relativo alla validazione dello username e andremo a verificare che non sia presente nel db con una chiamata ajax (si osservi che questa verifica non esenta dalla verifica server-side).

Quindi all’evento blur sul nostro campo, andremo a leggere il valore digitato dall’utente e manderemo una chiamata ajax al server web, in caso di risposta negativa, rimuoviamo la label dell’errore,

per evitare duplicazioni, la rimettiamo, svuotiamo il campo, altrimenti semplicemnte rimuoviamo la label dell’errore.


$(‘#username’).blur(function(){
var username=$(‘#username’).val();
$.ajax({
type:’GET’,
url:’data/test_username.php?username=’+username,
success:function(str){
if(str==’KO’){
$(“#username_error”).remove();
$(‘#username’).val(”);
$(‘#username’).after(‘<label for=”username” id=”username_error”>Username presente</label>’);
$(‘#username’).focus();
}
else{$(“#username_error”).remove();}
}
})
})

La successiva porzione di codice validerà il form e ci faremo restituire un valore booleano in base all’esito dell’operazione,

quindi al click sul submit, ma sipoteva anche dire al submit del form, aggiungiamo la vera validazione:


$(‘#submit’).click(function(){
var valido=$(‘#info’).validate().form();

})

Nel metodo validate specificheremo rules e messagges come ben spiegato nella pagina del plugin


rules:{
nome:’required’,
email:{
required:true,
email:true
},
username:{
required:true,
minlength:2
}
},
messages:{
nome:’Campo obbligatorio’,
email:{
required:’Campo obbligatorio’,
email:’Devi inserire un indirizzo valido’
},
username:{
required:’Campo obbligatorio’,
minlength:’Devi inserire almeno 2 caratteri’
}
}

Nel nostro caso ci siamo semplicemente limitati ai campi obbligatori e alla validazione dell’email.

Ultimo step l’invio del form.

Se la validazione ha avuto successo invieremo una chiamata ajax al nostro server web, passando i dati del form serializzati:


$.post(‘dati/inserisci.php’,$(‘#info’).serialize()

per poi gestire con una callback l’esito della risposta che se positivo implicherà:

1. nascondere il form

2. mostrare un messaggio di avviso all’utente

3. sostituire un contenuto visuale al posto del form


function(){
$(‘#info’).hide();
$(‘#dialog’).dialog().html(‘<p>Tutto ok!</p>’);
$(‘#contenitore’).append(‘<p>Record inserito</p>’);
}

Per testare tutte le funzionalità dell’esempio lo username presente è “pippo”

Oct 272012
 

Costruiamo un sistema per aggiornare il database tramite checkbox, senza ricaricare la pagina utilizzando chiamate ajax.

Per prima cosa il form:


<form>
<input type=”checkbox” id=”u1″ name=”u1″  /><label id=”l1″>Utente 1</label><br />
</form>

con tutte le checkbox di cui abbiamo bisogno. E’ importante fare in mdo che l’id e il name dei nostri checkbox siano legati all’id del record da aggiornare, in questo caso lo contengono insieme a un prefisso “u” poiché non si può assegnare agli id dei valori solo numerici. All’interno del form inseriamo anche un div che nasconderemo con il css per mostrare l’immaghine del loader ajax e avvisare l’utente che l’operazione è in corso e un dialog box che useremo per dare la risposta circa l’esito dell’operazione:


<div id=”loader”><img src=”images/ajax_loader.gif” /></div>
<div id=”dialog” title=”Risposta del server:”><p></p></div>

Nel css prevediamo due class per evidenziare in kodo diverso gli utenti abilitati e quelli non abilitati e nascondiamo ciò che non serve subito.


<style type=”text/css”>
.abilitato{ color:#003366;}
.disabilitato{ color:#666;}
#msg, #dialog, #loader{ display:none;}
</style>

Passiamo ora alla parte jQuery:

predisponiamo la visualizzazione del loader:


$(document)
.ajaxStart(function(){$(‘#loader’).css({‘display’:'block’});})
.ajaxStop(function(){$(‘#loader’).css({‘display’:'none’});});

al caricamento della pagina mappiamo l’evento click solo sui checkbox:


$(‘:checkbox’).bind(‘click’,function(){

e leggiamo l’id e il valore dell’attributo checked, oltre a ri cavare l’id “vero” del record:


var ctr=this.id;
var chk=$(‘#’+ctr).attr(‘checked’);
var id=ctr.substr(1);

inseriamo la chiamata ajax:


$.ajax({
type:’GET’,
url:’checkbox.php?azione=aggiorna_utenti&id=’+id+’&chk=’+chk,
success:function(chk){

e vediamo ora brevemente la pagina php che sarà un normale update sul db:


error_reporting(0);
include(‘include/mysql.inc.php’);


if($_GET['azione']==’aggiorna_utenti’){
$id=(int)$_GET['id'];
$chk=$_GET['chk'];
if($chk==’checked’){$chk=1;}
else{$chk=0;}
$sql=’update utenti set abil=”‘.$chk.’” where id=’.$id;
$result=mysql_query($sql,$conn);
if(!$result){echo -1;}
else{echo $chk;}
}

con 3 possibili output: -1 in caso di errore, 0 se l’utente è disabilitato e 1 se è abilitato.

Ora andiamo a gestire le risposte:


if(chk==1){
$(‘#l’+id).removeClass(‘disabilitato’).addClass(‘abilitato’);
$(‘#dialog’).dialog();
$(‘#dialog p’).html(‘Operazione completata’);
}

e quindi modifichiamo la classe sulla label per segnalre il cambio di stato e mostriamo il dilog di jQuery UI per avvertire l’utente che l’operazione è conclusa. Ripetiamo e personalizziamo l’operazione anche per le altre due risposte.

L’esempio completo

Oct 252012
 

Andiamo a leggere un file xml e a visualizzare i dati all’interno di una tabella.
Come prima cosa prepariamo l’html:
il div da utlizzare come avviso durante il caricamento con ajax che verrà nascosto dal css:

<div id="loader"><img alt="" src="http://www.lorenzodeambrosis.net/blog/2012/10/jquery-parsing-xml/images/ajax_loader.gif" /></div>

e la tabella dove andremo a visualizzare i dati:

<table id="lista">
	<thead>
    	<tr>
        	<th>Titolo</th>
        	<th>Link</th>
        	<th>Autore</th>
        </tr>
    </thead>
    <tr class="template">
    	<td><span class="item_titolo"></span></td>
    	<td><span class="item_link"></span></td>
    	<td><span class="item_autore"></span></td>
    </tr>
</table>

La prima riga della tabella contiene l’intestazione della stessa,
la seconda una riga “template”, nascosta dal css che verrà clonata nel corso della lettura del file xml

Rapidamente la struttura della nostra fonte di dati:

Al document.ready partirà la chiamata ajax come di consueto:

$.ajax({
type:’GET’,
url:’data/news2.xml’,
dataType:’xml’,
success:function(str_xml){
…
}
})

e una volta ricevuti i dati procediamo con il ciclo di lettura:


$(str_xml).find(‘item’).each(function(){
var titolo=$(this).find(‘titolo’).text();
var miolink=$(this).find(‘link’).text();
var autore=$(this).find(‘autore’).text();

e a questo prunto prepariamo l’output clonando il template e rimuovendo la class per renderlo visibile

var newRow=$(‘#lista .template’).clone().removeClass(‘template’);

prepariamo un oggetto litteral con i dati da iniettare nella nuova riga:

var listaItem={titolo:titolo, varlink:miolink, varautore:autore};

infine popoliamo e appendiamo la nostra riga:

popola_template(newRow, listaItem).appendTo(‘#lista’).fadeIn();

la funzione popola_template cerca i tag span dove andare a scrivere i contenuti dell’oggetto passato
e restituisce l’oggetto jQuery da appendere:

function popola_template(row, lista){
row.find(‘.item_titolo’).text(lista.titolo);
row.find(‘.item_link’).text(lista.varlink);
row.find(‘.item_autore’).text(lista.varautore);
return(row);
}

L’esempio completo

Oct 232012
 

Quando ci troviamo ad utilizzare massicciamente ajax potremmo avere delle difficoltà nel monitorare correttamente gli accessi alle nostre pagine.

Supponiamo, per ipotesi, di costruire un sito a partire da un unico file e popolarlo iniettando dei contenuti con delle chiamate ajax; supponiamo inoltre di voler monitorare gli accessi a questi contenuti con un classico Google Analytics. Ora con l’approccio tradizionale potremmo trovarci nell’imbarazzante situazione di poter contare solamente gli accessi al file principale ma di non poter distinguere gli accessi ai contenuti particolari caricati via ajax. Infatti, in teoria e per un certo periodo anche nella pratica, gli strumenti di analisi basati su javascript attivavano la chiamata e il conteggio dell’accesso, di fatto, solo al caricamento della pagina quando il browser interpretava lo script di monitoraggio. Questo ovviamente causava una serie di limti fastidiosi legato non tanto e non solo al mancato monitoraggio delle chiamate ajax ma anche per esempio all’accesso a un file pdf.

Fortunatamente ora non è più così e possiamo tranquillamente monitorare tutto quello che ci occorre, serve solo un minimo di programmazione e qualche cautela.

Infatti una cosa alla quale fare attenzione è, innazitutto, inserire il codice di monitoraggio all’interno del tag <body>, per esempio così:


&lt;body&gt;
&lt;script type=”text/javascript”&gt;

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-xxxxxxx-1']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(ga, s);
})();

&lt;/script&gt;

Il secondo passaggio sarà quello di rendere esplicito la chiamata di monitoraggio, associandola per esempio a un evento javascript che richiama una funzione, all’interno della quale collocare un codice simile a questo:


_gaq.push(['_trackPageview', '/miapagina']);

dove al posto di /miapagina ci sarà il contenuto che leggeremo nel report di analytics

Ulteriori approfondimenti in merito sono disponibili nella guida di Google Analytics