In quest'ultimo articolo dedicato a JQuery parleremo della sua estendibilità tramite la creazione e l'utilizzo di plugin realizzati sia dagli stessi sviluppatori di JQuery sia da terze parti.
Analizzeremo alcuni plugin divenuti ormai famosi nella comunità del framework.
I plugin principali
Il principale luogo dove prendere spunto per ricercare dei plugin è senza dubbio il repository ufficiale del framework Javascript, presente a questo indirizzo web: http://plugins.jquery.com/. Qui i plugin sono suddivisi in diverse aree adottando un criterio basato sull'utilità del plugin stesso: troveremo plugin adatti per la validazione dei form, per la gestione del DOM, per la creazione di GUI e di widget, per migliorare la navigazione e moltro altro.
I plugin che verranno analizzati nell'articolo sono 3 e nel dettaglio:
- Tabs Plugin - plugin per realizzare interfacce grafiche utilizzando le tab tramite contenuti statici o dinamici (utilizzando AJAX);
- Treeview - plugin per trasformare delle liste disordinate (ul) in alberi espandibili;
- JQuery Validation Plugin - plugin per gestire la validazione e la segnalazione di errori per qualsiasi tipologia di form.
Ho scelto questi plugin soprattutto per la loro maturità e perché rappresentano delle necessità comuni per tutti gli sviluppatori web. L'ordine con il quale verranno presentati non è casuale ma facilita una sorta di comprensione partendo dal plugin più semplice a quello più complesso e personalizzabile. Per ciascun plugin realizzeremo un mini esempio introducendo tutte le caratteristiche dello stesso.
Tabs Plugin
Il primo plugin analizzato permetterà di trasformare un semplice frammento HTML in una struttura molto di moda in questo periodo: quella basata su tab.
Il codice HTML deve includere una struttura di questo tipo:
<div id="tab-container-1">
<ul>
<li><a href="#tab-1-1"><span>One</span></a></li>
<li><a href="#tab-1-2"><span>Two</span></a></li>
<li><a href="#tab-1-3"><span>Three</span></a></li>
</ul>
<div id="tab-1-1">Io sono il primo tab</div>
<div id="tab-1-2">Io sono il secondo tab</div>
<div id="tab-1-3">Io sono il terzo tab</div>
</div>
Non si tratta che di un div
(con id="tab-container-1"
) container per un elenco non ordinato (ul
) e un numero di div
pari al numero di tab. Da notare la semplice associazione tra l'attributo href
degli elementi a
e l'id dei div
sottostanti.
Una volta realizzata questa struttura, basterà invocare il metodo tabs()
sull'oggetto JQuery che rappresenta la lista ul
:
$(document).ready(function(){
$("#tab-container-1 > ul").tabs();
});
Ovviamente l'invocazione del metodo deve essere effettuata dopo che il documento è stato caricato.
Le funzionalità del plugin non finiscono qua. Sono infatti moltissime le personalizzazioni che si possono fare.
Innanzitutto è possibile forzare l'apertura di una tab diversa dalla prima passando il suo indice al metodo tabs
:
$("#tab-container-1 > ul").tabs(2); //apre in automatico la seconda tab
oppure abilitare o disabilitare, tramite metodi appositi, determinate tab, rendendole non solo non cliccabili ma anche leggermente trasparenti:
$('#container').tabsDisable(4); //disabilita la quarta tab
$('#container').tabsEnable(3); //abilita la terza tab
Ecco un primo esempio di quanto visto fino a questo punto.
Una delle caratteristiche più innovative di questo plugin, però, è la possibilità di caricare i contenuti dal server tramite una richiesta asincrona con l'oggetto XmlHttpRequest.
Per caricare un documento esterno basterà modificare l'attributo href
degli elementi a
facendo riferimento ad una pagina o ad un url remoto; sarà il plugin a gestire tutto il resto:
<div id="tab-container-2">
<ul>
<li><a href="ajax/tab1.html"><span>One</span></a></li>
<li><a href="ajax/tab2.html"><span>Two</span></a></li>
<li><a href="ajax/tab3.html"><span>Three</span></a></li>
</ul>
</div>
In questo esempio vengono caricate le pagine contenute nella cartella ajax in maniera totalmente automatica.
Il plugin prevede anche ulteriori funzionalità come per esempio l'utilizzo di animazioni (prime di tutte il fade e lo slide) per il cambiamento di tab:
$('#container').tabs({ fxSlide: true }); //apre le tab con un effetto di slide
e la possibilità di impostare particolari callback per i principali eventi scatenabili:
$('#container').tabs({
click: function() {
alert('Hai cliccato su un tab');
}
}
Riguardo invece all'aspetto grafico, il plugin include anche un file CSS per creare in tempi rapidissimi un layout a tab. Ovviamente è possibile modificare questi stili per realizzare una interfaccia personalizzata.
Per ulteriori customizzazioni rimando alla documentazione ufficiale raggiungibile a questo indirizzo: http://docs.jquery.com/UI/Tabs
Treeview
Questo secondo plugin è concettualmente simile al precedente. Permette infatti di costruire un albero espandibile e dinamico a partire da un frammento HTML (nello specifico una serie di elementi ul
annidati). L'effetto finale è davvero gradevole e permette di realizzare interfacce molto usabili.
Il frammento HTML di base deve avere una struttura simile a questa:
<ul id="treeview">
<li><span>Primo elemento</span></li>
<li><span>Secondo elemento</span></a>
<ul>
<li><span>Primo sotto-elemento</span></li>
<li><span>Secondo sotto-elemento</span></a></li>
<li><span>Terzo sotto-elemento</span></li>
</ul>
</li>
<li><span>Terzo elemento</span></li>
<li><span>Quarto elemento</span>
<ul>
<li><span>Primo sotto-elemento</span></li>
<li><span>Secondo sotto-elemento</span></a></li>
<li><span>Terzo sotto-elemento</span></li>
</ul>
</li>
</ul>
È un elenco di liste (ul
) annidate tra di loro partendo da una lista root (ul
con id="treeview"
). Come per il precedente plugin, per trasformare le liste in un albero dinamico occorre invocare un particolare metodo dopo che il DOM sia stato correttamente caricato dal browser. Facciamo quindi affidamento al metodo ready
esposto da Jquery:
$(document).ready(function(){
$("#treeview").treeview();
});
Il plugin permette anche di associare a ciascun item delle liste un'icona che rappresenta il suo stato di item o di container di altri item secondo una convenzione simile al file system dei sistemi operativi (folder e file). Basterà associare alla lista root la classe filetree
e a ciascun span
contenuto dentro i li
la classe folder
o file
in base al suo comportamento. Ecco un esempio del plugin in azione.
Oltre a queste impostazioni basilari, il plugin presenta ulteriori estensioni che permettono di migliorare nelle funzionalità il nostro albero. Queste estensioni possono essere attivate passando al metodo treeview
un oggetto JSON contente particolari configurazioni.
Una delle configurazioni che ritengo più interessanti è unique
che permette di avere un solo nodo espanso dallo stesso padre.
// rendiamo l'apertura di un nodo vincolata alla chiusura degli altri
$("#treeview").treeview( {unique: true} );
La seconda configurazione possibile che segnalo riguarda l'evento toggle
che scatta ogni volta che un ul
viene aperto o chiuso:
$("#treeview").treeview( {toggle: function() {
alert("Hai modificato la struttura dell'albero"); //impostiamo una funzione di callback all'evento toggle
}});
La funzionalità più interessante riguarda la possibilità di persistere lo stato del tree (quali nodi sono espansi e quali no) tramite l'utilizzo di cookie o tramite l'oggetto location. Realizzare questa persistenza è banale:
// utilizzo l'oggetto location per la persistenza
$("#treeview").treeview( {persist: "location"} );
//utilizzo un cookie per la persistenza
$("#treeview").treeview( {persist: "cookie"} );
Come per il precedente, rimando per ulteriori informazioni alla documentazione ufficiale: http://docs.jquery.com/Plugins/Treeview/treeview
JQuery Validation Plugin
Quest'ultimo plugin si differenzia dai precedenti perché non consente di creare widget grafici (come appunto tab e tree) ma permette di implementare facilmente una delle componenti più scomode e spesso mal organizzate di una applicazione web: la validazione dei dati inseriti dall'utente.
Per meglio comprendere il meccanismo di funzionamento è bene definire due concetti chiave: metodo di validazione e regola di validazione.
Un metodo di validazione non è nient'altro che una funzione che implementa la logica per determinare la validità di un testo. Tutti i metodi di validazione devono ritornare un booleano. Il plugin presenta alcuni metodi di validazione standard (lunghezza testo, email, url, data, numero e altri). La creazione di nuovi metodi di validazione avviene tramite il metodo addMethod
che riceve come parametri il nome del metodo, la funzione da eseguire e un messaggio di errore da visualizzare.
Una regola di validazione è una sorta di relazione tra un campo di input HTML (di qualsiasi tipo) con uno o più metodi di validazione. Le regole di validazione vengono comunicate utilizzando l'attributo class
presente nel DOM utilizzando lo spazio tra ciascun metodo invocato.
A differenza dei precedenti plugin, quest'ultimo presenta delle dipendenze. Significa che per poter usufruire in pieno delle sue funzionalità è necessario disporre anche di ulteriori plugin realizzati da terze parti. I plugin necessari sono:
- delegate (obbligatorio);
- metadata (obbligatorio solo se si vogliono impostare regole di validazione tramite l'attributo
class
) ; - form (obbligatorio per inviare i dati tramite richieste asincrone ed Ajax - componente non presa in considerazione in questa introduzione al plugin).
Guardiamo subito un esempio di form che imposta le regole tramite l'attributo class
degli input:
<form action="#" method="post" id="form2validate">
<p>
<label for="username">Username:</label>
<input type="text" name="username" class="required {minlength:2}"/>
</p>
<p>
<label for="password">Password:</label>
<input type="text" name="password"/>
</p>
<p>
<label for="password_confirm">Conferma la Password:</label>
<input type="text" name="password_confirm"/>
</p>
<p>
<label for="birthdate">Data di nascita</label>
<input type="text" name="birthdate"/>
</p>
<p>
<label for="email">Indirizzo email</label>
<input type="text" name="email" class="email required"/>
</p>
<p>
<label for="privacy">Accetto</label>
<input type="checkbox" name="privacy" class="required"/>
</p>
<p>
<input type="submit"/>
</p>
</form>
Come possiamo vedere ci sono due tipologie di metodi di validazione: quelli che richiedono dei parametri (per esempio maxlength
) e quelli che non ne richiedono (per esempio required
).
Per il secondo caso basterà citare come class
il nome del metodo mentre per il primo tipo bisognerà utilizzare la sintassi JSON metodo:parametro
. Ecco qua il primo esempio dal vivo.
I messaggi di errore verranno di default appesi dopo l'input all'interno di un tag label
con classe error
. Questo è il comportamenti di default, ma si può semplicemente modificare per esempio creando un container HTML dove andremo a mettere tutti i nostri errori - ma lo vedremo successivamente.
Ovviamente i metodi di validazione non saranno mai sufficienti per implementare un controllo che sia davvero efficace e personalizzato. La soluzione migliore risulta quindi quella di creare un nostro metodo di validazione da richiamare poi nella class di un input. Creiamo per esempio un metodo che controlla che il campo inserito sia correttamente un codice fiscale utilizzando una regex. Basterà quindi chiamare il metodo statico addMethod
:
jQuery.validator.addMethod("codfiscale", function(value) {
// espressione migliorabile... ma sufficiente per il nostro esempio
var regex = /[A-Z]{6}[d]{2}[A-Z][d]{2}[A-Z][d]{3}[A-Z]/;
return value. match(regex);
}, "Please insert a valid italian identification number");
E poi richiamare il metodo nell'HTML:
<p>
<label for="id">Codice fiscale:</label>
<input type="text" name="id" class="codfiscale"/>
</p>
Se volessimo invece inserire un metodo di validazione che si aspetta valori in entrata basterà aggiungere alcuni parametri alla nostra callback da passare a addMethod
:
jQuery.validator.addMethod("radice", function(value, element, params) {
return this.optional(element) || value * value == params;
}, "Please enter the correct radix");
Da notare la presenza del doppio controllo utilizzando this.optional(element)
. Questo permette di impostare il campo come opzionale: può essere quindi vuoto. Ovviamente in questo modo è possibile creare metodi di validazione annidati tra di loro. Ecco il secondo esempio funzionante.
Qualsiasi altra personalizzazione del plugin (come per esempio la modifica dei messaggi di errore standard, delle classi associate alla label di errore o eventuali callback per gli eventi esposti dal plugin) può avvenire tramite il passaggio di un parametro di opzioni al metodo validate. Non mi soffermo su questi aspetti che riguardano un utilizzo più approfondito del plugin; per maggiori informazioni rimando come al solito alla documentazione ufficiale presente a questo indirizzo: http://docs.jquery.com/Plugins/Validation.
Termina qui questa carrellata su alcuni dei plugin più interessanti per jQuery. Nel prossimo articolo vedremo come creare il nostro primo plugin per jQuery.