fondamentali di jquery -...

57
Fondamentali di jQuery Di Rebecca Murphey http://github.com/rmurphey/jqfundamentals Con il contributo di James Padolsey, Paolo Irish e gli altri. Per una storia completa dei contributi visitare il repository GitHub. Copyright © 2011 Concesso in licenza da Rebecca Murphey sotto la Creative Commons Attribution-Share Alike 3.0 United States license Siete liberi di copiare, distribuire, trasmettere, e remix questo lavoro, a condizione di attribuire l'opera a Rebecca Murphey come l'autore originale e il repository di riferimento GitHub per il lavoro. Se alteri, trasformi o sviluppi quest'opera, puoi distribuire l'opera risultante solo con la stessa, simile o di una licenza compatibile. Una delle condizioni di cui sopra può essere revocata se si ottiene il permesso del detentore del copyright. Ogni volta che usi o distribuisci quest'opera, devi farlo secondo i termini della licenza di quest'opera. Il modo migliore per farlo è con un link per la licenza. Contenuti Capitolo 1: Benvenuti Capitolo 2: Concetti di base di JavaScript Capitolo 3: Nozioni di base di jQuery Capitolo 4: Il nucleo di jQuery Capitolo 5: Eventi Capitolo 6: Effetti Capitolo 7: Ajax Capitolo 8: Estensioni Capitolo 9: Best practice per migliorare le prestazioni Capitolo 10: Organizzazione del codice Capitolo 11: Eventi personalizzati Lista di esempi Esempio 1.1: Esempio di codice JavaScript in linea Esempio 1.2: Esempio d'inclusione di un file esterno JavaScript Esempio 1.3: Un codice di esempio Esempio 2.1: Dichiarazione semplice di una variabile Esempio 2.2: Gli spazi non hanno alcun valore al di fuori delle virgolette Esempio 2.3: Le parentesi indicano la priorità Esempio 2.4: La tabulazione migliora la lettura del codice, ma non ha un significato speciale Esempio 2.5: Concatenazione Esempio 2.6: Moltiplicazione e divisione Esempio 2.7: Incremento e decremento Esempio 2.8: Somma vs. concatenazione Esempio 2.9: Forzare una stringa ad agire come un numero Esempio 2.10: Forzare una stringa per agire come un numero (somma unaria) Esempio 2.11: Operatori Logici AND e OR Esempio 2.12: Operatori di confronto Esempio 2.13: Controllo del flusso Esempio 2.14: Valori che ritornano il vero true Esempio 2.15: Valori che ritornano il falso false Esempio 2.16: L'operatore ternario Esempio 2.17: Una dichiarazione Switch Esempio 2.18: Cicli Esempio 2.19: Un tipico ciclo utilizzando for Esempio 2.20: Un típico bucle utilizzando while Esempio 2.21: Ciclo utilizzando while con la combinazione della condizione e l'incremento Esempio 2.22: Un ciclo do-while Esempio 2.23: Fermare un ciclo con break Esempio 2.24: Saltare alla seguente iterazione di un ciclo Esempio 2.25: Un vettore semplice Esempio 2.26: Accedere agli elementi dell'array attraverso il suo indice Esempio 2.27: Ottenere il numero di elementi dell'array Esempio 2.28: Modificare il valore di un elemento di un array Esempio 2.29: Aggiungere elementi ad un array Esempio 2.30: Lavorando con gli array Esempio 2.31: Creazione di un "oggetto letterale" Esempio 2.32: Dichiarazione di una funzione Esempio 2.33: Dichiarare una funzione denominata Esempio 2.34: Una semplice funzione Esempio 2.35: Una funzione che restituisce un valore Esempio 2.36: Una funzione che restituisce un'altra funzione Esempio 2.37: Una funzione anonima autoeseguibile Esempio 2.38: Passare una funzione anonima come argomento Esempio 2.39: Passare una chiamata di funzione come argomento Esempio 2.40: Determinare il tipo tra differenti variabili Esempio 2.41: Una funzione invocata utilizzando Function.call Esempio 2.42: Una función creada utilizando Function.bind Esempio 2.43: Una funzione vincolata ad un oggetto Esempio 2.44: Le funzioni hanno accesso alle variabili definite all'interno dello stesso ambito Esempio 2.45: Il codice esterno non può accedere alla variabile definita all'interno della funzione Esempio 2.46: Variabili con nomi identici ma diversi valori possono esistere in diversi ambiti Esempio 2.47: Le funzioni possono "vedere" le modifiche nelle variabili prima che la funzione sia definita Esempio 2.48: Ambito folle Esempio 2.49: Come impostare il valore di i? Esempio 2.50: Impostare il valore di i utilizzando una chiusura Fondamentali di jQuery http://rhadrix.net/guest/book/index.html 1 di 57 24/08/2012 19:45

Upload: vutruc

Post on 10-Sep-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Fondamentali di jQuery

Di Rebecca Murphey

http://github.com/rmurphey/jqfundamentals

Con il contributo di James Padolsey, Paolo Irish e gli altri. Per una storia completa dei contributi visitare il repository GitHub.

Copyright © 2011

Concesso in licenza da Rebecca Murphey sotto la Creative Commons Attribution-Share Alike 3.0 United States license Siete liberi di copiare, distribuire, trasmettere, eremix questo lavoro, a condizione di attribuire l'opera a Rebecca Murphey come l'autore originale e il repository di riferimento GitHub per il lavoro. Se alteri, trasformio sviluppi quest'opera, puoi distribuire l'opera risultante solo con la stessa, simile o di una licenza compatibile. Una delle condizioni di cui sopra può essere revocata se siottiene il permesso del detentore del copyright. Ogni volta che usi o distribuisci quest'opera, devi farlo secondo i termini della licenza di quest'opera. Il modo miglioreper farlo è con un link per la licenza.

Contenuti

Capitolo 1: BenvenutiCapitolo 2: Concetti di base di JavaScriptCapitolo 3: Nozioni di base di jQueryCapitolo 4: Il nucleo di jQueryCapitolo 5: EventiCapitolo 6: EffettiCapitolo 7: AjaxCapitolo 8: EstensioniCapitolo 9: Best practice per migliorare le prestazioniCapitolo 10: Organizzazione del codiceCapitolo 11: Eventi personalizzati

Lista di esempi

Esempio 1.1: Esempio di codice JavaScript in lineaEsempio 1.2: Esempio d'inclusione di un file esterno JavaScriptEsempio 1.3: Un codice di esempioEsempio 2.1: Dichiarazione semplice di una variabileEsempio 2.2: Gli spazi non hanno alcun valore al di fuori delle virgoletteEsempio 2.3: Le parentesi indicano la prioritàEsempio 2.4: La tabulazione migliora la lettura del codice, ma non ha un significato specialeEsempio 2.5: ConcatenazioneEsempio 2.6: Moltiplicazione e divisioneEsempio 2.7: Incremento e decrementoEsempio 2.8: Somma vs. concatenazioneEsempio 2.9: Forzare una stringa ad agire come un numeroEsempio 2.10: Forzare una stringa per agire come un numero (somma unaria)Esempio 2.11: Operatori Logici AND e OREsempio 2.12: Operatori di confrontoEsempio 2.13: Controllo del flussoEsempio 2.14: Valori che ritornano il vero trueEsempio 2.15: Valori che ritornano il falso falseEsempio 2.16: L'operatore ternarioEsempio 2.17: Una dichiarazione SwitchEsempio 2.18: CicliEsempio 2.19: Un tipico ciclo utilizzando forEsempio 2.20: Un típico bucle utilizzando whileEsempio 2.21: Ciclo utilizzando while con la combinazione della condizione e l'incrementoEsempio 2.22: Un ciclo do-whileEsempio 2.23: Fermare un ciclo con breakEsempio 2.24: Saltare alla seguente iterazione di un cicloEsempio 2.25: Un vettore sempliceEsempio 2.26: Accedere agli elementi dell'array attraverso il suo indiceEsempio 2.27: Ottenere il numero di elementi dell'arrayEsempio 2.28: Modificare il valore di un elemento di un arrayEsempio 2.29: Aggiungere elementi ad un arrayEsempio 2.30: Lavorando con gli arrayEsempio 2.31: Creazione di un "oggetto letterale"Esempio 2.32: Dichiarazione di una funzioneEsempio 2.33: Dichiarare una funzione denominataEsempio 2.34: Una semplice funzioneEsempio 2.35: Una funzione che restituisce un valoreEsempio 2.36: Una funzione che restituisce un'altra funzioneEsempio 2.37: Una funzione anonima autoeseguibileEsempio 2.38: Passare una funzione anonima come argomentoEsempio 2.39: Passare una chiamata di funzione come argomentoEsempio 2.40: Determinare il tipo tra differenti variabiliEsempio 2.41: Una funzione invocata utilizzando Function.callEsempio 2.42: Una función creada utilizando Function.bindEsempio 2.43: Una funzione vincolata ad un oggettoEsempio 2.44: Le funzioni hanno accesso alle variabili definite all'interno dello stesso ambitoEsempio 2.45: Il codice esterno non può accedere alla variabile definita all'interno della funzioneEsempio 2.46: Variabili con nomi identici ma diversi valori possono esistere in diversi ambitiEsempio 2.47: Le funzioni possono "vedere" le modifiche nelle variabili prima che la funzione sia definitaEsempio 2.48: Ambito folleEsempio 2.49: Come impostare il valore di i?Esempio 2.50: Impostare il valore di i utilizzando una chiusura

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

1 di 57 24/08/2012 19:45

Page 2: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 2.51: Utilizzando una chiusura per accedere simultaneamente ad istanze di oggetti interni ed esterniEsempio 3.1: Il blocco $(document).ready()Esempio 3.2: Forma abbreviata per $(document).ready()Esempio 3.3: Passare il nome di una funzione al posto di una funzione anonimaEsempio 3.4: Selezione di elementi in base al loro IDEsempio 3.5: Selezione di elementi in base al nome della classeEsempio 3.6: Selezione di elementi per il suo attributoEsempio 3.7: Selezione di elementi in forma di selettore CSSEsempio 3.8: Pseudo-selettoriEsempio 3.9: Valutare se una selezione ha degli elementiEsempio 3.10: Salvare le selezioni su una variabileEsempio 3.11: Affinamento delle selezioniEsempio 3.12: Utilizzando pseudo-selettori sugli elementi dei formsEsempio 3.13: ConcatenandoEsempio 3.14: Formattazione del codice incatenatoEsempio 3.15: Ripristinare la selezione originale utilizzando il metodo $.fn.endEsempio 3.16: Il metodo $.fn.html utilizzato come impostatoreEsempio 3.17: Il metodo html utilizzato come ottenitoreEsempio 3.18: Ottenendo le proprietà CSSEsempio 3.19: Impostando le proprietà CSSEsempio 3.20: Lavorare con le classiEsempio 3.21: Dimensioni - Metodi di baseEsempio 3.22: Impostare attributiEsempio 3.23: Ottenere attributiEsempio 3.24: Muoversi attraverso il DOM usando metodi di attraversamentoEsempio 3.25: Interagire in una selezioneEsempio 3.26: Modificare il codice HTML di un elementoEsempio 3.27: Spostare oggetti con differenti approcciEsempio 3.28: Ottenere una copia del elementoEsempio 3.29: Creare nuovi elementiEsempio 3.30: Creare un nuovo elemento con attributi utilizzando un oggettoEsempio 3.31: Creare un nuovo elemento nella paginaEsempio 3.32: Creare e aggiungere allo stesso tempo un elemento alla paginaEsempio 3.33: Manipolazione di un singolo attributoEsempio 3.34: Manipolazione di più attributiEsempio 3.35: Utilizzare una funzione per determinare il valore del nuovo attributoEsempio 4.1: Verificare il tipo di un determinato valoreEsempio 4.2: Salvare e recuperare informazioni relative a un elementoEsempio 4.3: Relazione tra gli elementi utilizzando il metodo $.fn.dataEsempio 4.4: Mettere jQuery in modo non-conflittoEsempio 4.5: Utilizzare $ all'interno di una funzione anonima auto-eseguibileEsempio 5.1: Collegamento di un evento utilizzando un metodo ridottoEsempio 5.2: Collegamento di un evento utilizzando il metodo $.fn.bindEsempio 5.3: Collegamento di un evento utilizzando il metodo $.fn.bind con informazione associataEsempio 5.4: Cambiare controller usando il metodo $.fn.one methodEsempio 5.5: Scollegare tutti i controllori di evento click in una selezioneEsempio 5.6: Scollegare un controllore di evento particolare clickEsempio 5.7: Spazio di Nomi per gli EventiEsempio 5.8: Collegare più eventi a un elementoEsempio 5.9: Annullare che facendo click su un link, questo si eseguaEsempio 5.10: Sparare un gestore di eventi nel modo giustoEsempio 5.11: Delegare un evento con $.fn.delegateEsempio 5.12: Delegare un evento con $.fn.liveEsempio 5.13: Scollegare Eventi DelegatiEsempio 5.14: La funzione ausiliaria hoverEsempio 5.15: La funzione ausiliaria toggleEsempio 6.1: Utilizzo di base di un effetto incorporatoEsempio 6.2: Impostare la durata degli effettiEsempio 6.3: Aumentare la velocità con jQuery.fx.speedsEsempio 6.4: Eseguire del codice quando un'animazione è completataEsempio 6.5: Eseguire una funzione di retrochiamata, anche se non c'è nessun elemento da animareEsempio 6.6: Effetti personalizzati con $.fn.animateEsempio 6.7: Transizione easing per ogni proprietàEsempio 7.1: Utilizzare il metodo $.ajaxEsempio 7.2: Utilizzare metodi appropriati nelle richieste AjaxEsempio 7.3: Utilizzare il metodo $.fn.load per riempire un elementoEsempio 7.4: Utilizzare il metodo $.fn.load per riempire un elemento basato su una selezione.Esempio 7.5: Trasformare le informazioni da una form in una stringa di datiEsempio 7.6: Creare un array di oggetti che contengono informazioni da un formEsempio 7.7: Usare YQL e JSONPEsempio 7.8: Mostra/Nascondi un indicatore utilizzando Eventi di AjaxEsempio 8.1: Creare una estensione per aggiungere e rimuovere una clesse in un elemento quando accade l'evento hoverEsempio 8.2: Il modello di sviluppo di estensioni per jQuery spiegato da Mike AlsupEsempio 8.3: Una semplice estensione con mantenimento dello stato utilizzando widget factory di jQuery UIEsempio 8.4: Passare opzioni al widgetEsempio 8.5: Impostare le opzioni di default per un widgetEsempio 8.6: Creare metodi nel WidgetEsempio 8.7: Chiamare i metodi in un'istanza dell'estensioneEsempio 8.8: Risponde quando l'opzione è impostataEsempio 8.9: Fornire funzioni di (callback) retrochiamataEsempio 8.10: Vincolare a eventi del widgetEsempio 8.11: Aggiungere un metodo destroy al widgetEsempio 10.1: Un oggetto letteraleEsempio 10.2: Utilizzare un oggetto letterale per una funzionalità jQueryEsempio 10.3: Il modello modulareEsempio 10.4: Utilizzare il modello modulare per una funzionalità jQueryEsempio 10.5: Usare RequireJS: un semplice esempioEsempio 10.6: Un semplice file JavaScript con dipendenzeEsempio 10.7: Definizione di un modulo RequireJS che non ha dipendenzeEsempio 10.8: Definizione di un modulo RequireJS con dipendenze

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

2 di 57 24/08/2012 19:45

Page 3: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 10.9: Definizione di un modulo RequireJS che restituisce una funzione

Torna in cima

Benvenuti

jQuery stà diventando rapidamente uno strumento che ogni sviluppatore web di interfacce dovrebbe conoscere. Lo scopo di questo libro è di fornire una panoramicadella biblioteca, in modo che quando hai finito di leggere, sarai in grado di eseguire operazioni di base utilizzando jQuery e avere una solida base per un apprendimentoulteriore. Il libro è stato progettato per essere utilizzato come materiale in un'aula di classe, ma può anche essere utile per lo studio individuale.

Il metodo di lavoro è il seguente: in primo luogo, si dedicherà del tempo per capire un concetto per poi fare un esercizio correlato. Alcuni degli esercizi possono ancheessere banali, mentre altre non lo sono. L'obiettivo è quello di imparare a risolvere in maniera semplice, ciò che normalmente si risolverebbe con jQuery. Soluzioni pertutti gli esercizi sono inclusi nello stesso materiale d'apprendimento.

Ottenere il materiale didattico

Il materiale didattico e il codice sorgente degli esempi citati nel libro sono ospitati sulla repository GitHub . Da qui è possibile scaricare un file in formato .zip o .tar con ilcodice per l'uso su un server web.

Software

Per lavorare con i contenuti del libro, saranno necessari i seguenti strumenti:

Firefox Browser Web

L'estensione Firebug per Firefox

Un editor di testo (come Notepad + + per Windows, gedit / Kate TextMate per Linux o Mac OS X)

Per le sezioni su Ajax: un server locale (come WAMP o MAMP) o un client FTP/SSH per accedere a un server remoto.

Aggiungere JavaScript in una Página

Ci sono due modi per inserire del codice JavaScript all'interno di una pagina: scrivendo il codice nella stessa linea (in lingua inglese inline) o tramite un file esternoutilizzando il tag script. L'ordine in cui s'include il codice è importante: un codice che dipende da un altro dovrebbe essere incluso dopo di quello che fa riferimento(Esempio: Se la funzione B dipende dalla A, l'ordine deve essere A, B e non B, A).

Per migliorare le prestazioni della pagina, il codice JavaScript deve essere incluso alla fine del HTML. Inoltre, quando si lavora in un ambiente di produzione con più fileJavaScript, devono essere combinati in un unico file.

Esempio 1.1: Esempio di codice JavaScript in linea

Esempio 1.2: Esempio d'inclusione di un file esterno JavaScript

Debugging del codice JavaScript

L'uso di uno strumento di debug è essenziale per lavorare con JavaScript. Firefox fornisce un debugger tramite l'estensione Firebug, mentre Safari e Chrome hanno unsistema integrato.

Ogni debugger offre:

Un editore multi-line per sperimentare con JavaScript;

Un ispettore per rivedere il codice generato nella pagina;

Un visualizzazione di rete o risorse, di esaminare le richieste che vengono fatte.

Quando si scrive codice JavaScript, è possibile utilizzare uno dei seguenti metodi per inviare messaggi alla console del debugger:

console.log() per inviare e registrare messaggi generali;console.dir() per registrare un oggetto e visualizzarne le proprietà;console.warn() per registrare messaggi di alert;console.error() per registrare i messaggi di errore;

Esistono altri metodi per utilizzarli dalla console, ma questi possono variare a seconda del browser. La console offre inoltre la possibilità di impostare puntid'interruzione e osservare le espressioni nel codice per facilitare il debug.

Esercizi

La maggior parte dei capitoli concludono con uno o più esercizi. In alcuni si potrà lavorare direttamente con Firebug, in altri sarà necessario scrivere il codice JavaScriptdopo d'includere la libreria jQuery nel documento.

Anche così, per completare alcuni esercizi, sarà necessario consultare la documentazione ufficiale di jQuery. Imparare a trovare le risposte è una parte importante del

1 <script>2 console.log('ciao');3 </script>

1 <script src='/js/jquery.js'></script>

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

3 di 57 24/08/2012 19:45

Page 4: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

processo di apprendimento.

Ecco alcuni suggerimenti per affrontare i problemi:

Per prima cosa, assicurarsi di aver compreso il problema si sta tentando di risolvere.

Poi, sapere a quali oggetti si dovranno accedere per risolvere il problema e decidere come accedervi. È possibile utilizzare Firebug per verificare se si staottenendo il risultato atteso.

Infine, scoprire cosa deve essere fatto con questi elementi per risolvere il problema. Può essere utile prima di iniziare, scrivere commenti che spiega cosadovrà fare.

Non abbiate paura di sbagliare. E neanche provare, al primo tentativo, di scrivere un codice perfetto. Commettere errori e sperimentare soluzioni fa parte del processodi apprendimento e aiuterà a essere uno sviluppatore migliore. È possibile trovare nella cartella /solutions esempi di soluzioni agli esercizi del libro.

Convenzioni utilizzate nel libro

I metodi che possono essere chiamati dall'oggetto jQuery, faranno riferimento come $.fn.nomreDelMetodo. I metodi che esistono nello spazio dei nomi (namespace in

inglese) di jQuery, ma che non possono essere chiamati dall'oggetto jQuery, faranno riferimento come $.nomeDelMetodo. Se questo non significa molto per ora, non si

preoccupi - sarà più chiaronel procedere del libro.

Esempio 1.3: Un codice di esempio

I richiami appariranno in questo modo..

Note

Le note su qualche tema appariranno di questa forma.

Note sulla traduzione

Perché il materiale ha lo scopo di apprendimento e di insegnamento, è tradotto in italiano formale (voi).

Molti termini tecnici sono nominati nella sua traduzione in italiano. Tuttavia, per tenere riferimento, si spiega anche come si chiamano in inglese.

Gli esempi e le soluzioni agli esercizi non sono completamente tradotti. Questo perché, quando si lavora su un progetto reale, il codice trovato su altri sitipotrebbe essere scritto in inglese. Eppure, i commenti incorporati nei codici sono stati tradotti così come altri testi particolari per facilitare la comprensione.

Materiale di riferimento

Ci sono una gran quantità di articoli che trattano alcuni aspetti di jQuery. Alcuni sono eccellenti, mentre altri, francamente, sono erronei. Quando si legga un articolo sujQuery, accertarsi che tratti la stessa versione della libreria in uso, e resistere alla tentazione di copiare e incollare il codice - prendere tempo per capirlo.

A continuazione ci sono una serie di eccellenti risorse da utilizzare durante l'apprendimento. La più importante di tutte è il codice sorgente di jQuery, che contiene (informato non compresso) una documentazione completa attraverso i commenti. La biblioteca non è una scatola nera - la sua comprensione aumenterà in modoesponenziale ogni volta che la si rivede - ed è altamente consigliabile memorizzare il link nel vostro browser preferito per averla come guida di riferimento.

Codice sorgente jQuery

Documentazione di jQuery

Forum di jQuery

Preferiti su Delicious

Canale IRC #jquery in Freenode

Torna in cima

Concetti di base di JavaScript

Introduzione

jQuery è scritto in JavaScript, un linguaggio di programmazione molto ricco ed espressivo.

Il capitolo si rivolge a chi non conosce il linguaggio, e copre i concetti di base e problemi comuni che possono sorgere quando si lavora con esso. Inoltre, la sezione puòessere utile a chi utilizza altri linguaggi di programmazione per capire le peculiarità di JavaScript.

Se siete interessati a saperne di più sul linguaggio, si può leggere il libro JavaScript: The Good Parts che Douglas Crockford ha scritto.

1 // Il codice di esempio apparirà in questo modo

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

4 di 57 24/08/2012 19:45

Page 5: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Sintassi di base

Comprendere dichiarazioni, nomi di variabile, spaziatura, e altre sintassi di base JavaScript

Esempio 2.1: Dichiarazione semplice di una variab ile

Esempio 2.2: Gli spazi non hanno alcun valore al di fuori delle virgolette

Esempio 2.3: Le parentesi indicano la priorità

Esempio 2.4: La tabulazione migliora la lettura del codice, ma non ha un significato speciale

Operatori

Operatori di base

Gli operatori di base permettono la manipolazione di valori.

Esempio 2.5: Concatenazione

Esempio 2.6: Moltiplicazione e divisione

Esempio 2.7: Incremento e decremento

Lavorare con i numeri e le stringhe

In JavaScript, quando si lavora con i numeri e con le stringhe può causare risultati imprevisti.

Esempio 2.8: Somma vs. concatenazione

Esempio 2.9: Forzare una stringa ad agire come un numero

Il costruttore Number, quando viene chiamato come una funzione (come nell'esempio) obbliga al suo argomento a comportarsi come un numero. È inoltre possibileutilizzare l'operatore somma unaria, che ritorna lo stesso risultato:

Esempio 2.10: Forzare una stringa per agire come un numero (somma unaria)

Operatori Logici

Gli operatori logici permettono valutare una serie di operandi utilizzando operazioni AND e OR.

Esempio 2.11: Operatori Logici AND e OR

1 var foo = 'ciao mondo';

1 var foo = 'ciao mondo';

1 2 * 3 + 5; // ritorna 11; il prodotto si esegue prima2 2 * (3 + 5); // ritorna 16; per le parentesi, la somma si esegue prima

1 var foo = function() {2 console.log('ciao');3 };

1 var foo = 'ciao';2 var bar = 'mondo';3 4 console.log(foo + ' ' + bar); // 'ciao mondo'

1 2 * 3;2 2 / 3;

1 var i = 1;2 3 var j = ++i; // incremento anticipato: j è uguale a 2; i è uguale a 24 var k = i++; // incremento posticipato: k è uguale a 2; i è uguale a 3

1 var foo = 1;2 var bar = '2';3 4 console.log(foo + bar); // errore: la console di debug mostra 12

1 var foo = 1;2 var bar = '2';3 4 // il costruttore 'Number' obbliga alla5 // stringa di comportarsi come un numero6 console.log(foo + Number(bar)); // la console di debug mostra 3

1 console.log(foo + +bar);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

5 di 57 24/08/2012 19:45

Page 6: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

L'operatore || (OR logico) restituisce il valore del primo operando, se questo è vero, altrimenti restituisce il valore del secondo operando. Se entrambi gli operandi sono

falsi restituisce false (falso). L'operatore && (AND logico) restituisce il valore del primo operando se questo è falso, altrimenti restituisce il valore del secondo operando.

Quando entrambi i valori sono veri ritorna vero (true), altrimenti restituisce falso.

È possibile consultare la sezione "Elementi Vero e Falso" per ulteriori dettagli su quali valori vengono valutati come true e quali vengono valutati come false.

Nota

Talvolta si può notare che alcuni sviluppatori utilizzino questa logica per il controllo del flusso invece di utilizzare la dichiarazione if. Per Esempio:

Questo stile dichiarazione è molto elegante e concisa, ma può essere difficile da leggere (specialmente per i principianti). È per questo si esplicita, perriconoscerlo durante la lettura del codice. Tuttavia, il suo uso non è raccomandato a meno che non si ha dimestichezza con il concetto e il comportamento.

Operatori di Confronto

Gli operatori di confronto consentono di verificare se certi valori sono equivalenti o identiche.

Esempio 2.12: Operatori di confronto

Codice Condizionale

A volte si desidera eseguire un blocco di codice in determinate condizioni. Le strutture di controllo del flusso - attraverso l'uso di istruzioni if ??ed else permettono di

farlo.

Esempio 2.13: Controllo del flusso

Note

In una linea singola, quando si scrive un'istruzione if, le parentesi non sono strettamente necessari, ma è raccomandato in quanto rende il codice molto più

leggibile.

01 var foo = 1;02 var bar = 0;03 var baz = 2;04 05 foo || bar; // ritorna 1, il quale è vero (true)06 bar || foo; // ritorna 1, il quale è vero (true)07 08 foo && bar; // ritorna 0, il quale è falso (false)09 foo && baz; // ritorna 2, il quale è vero (true)10 baz && foo; // ritorna 1, il quale è vero (true)

1 // fare qualcosa con foo se foo è vero2 foo && doSomething(foo);3 4 // stabilire bar uguale a baz se baz è vero;5 // caso contrario, stabilire bar uguale al6 // valore di createBar()7 var bar = baz || createBar();

01 var foo = 1;02 var bar = 0;03 var baz = '1';04 var bim = 2;05 06 foo == bar; // ritorna false07 foo != bar; // ritorna true08 foo == baz; // ritorna true; fare attenzione!09 10 foo === baz; // ritorna false11 foo !== baz; // ritorna true12 foo === parseInt(baz); // ritorna true13 14 foo > bim; // ritorna false15 bim > baz; // ritorna true16 foo <= baz; // ritorna true

01 var foo = true;02 var bar = false;03 04 if (bar) {05 // questo codice non verrà mai eseguito06 console.log('ciao!');07 }08 09 if (bar) {10 // questo codice non si eseguirà11 } else {12 if (foo) {13 // questo codice si eseguirà14 } else {15 // si eseguirà se foo e bar sono falsi (false)16 }17 }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

6 di 57 24/08/2012 19:45

Page 7: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

È necessario essere consapevoli di non definire funzioni con lo stesso nome più volte all'interno di istruzioni if/else, giacché si potrebbe ottenere risultati

inaspettati.

Elementi Veri e Falsi

Per controllare il flusso correttamente, è importante capire quali tipi di valori sono "veri" e che "false". A volte, alcuni valori possino sembrare una cosa, ma finisconoper essere un'altra.

Esempio 2.14: Valori che ritornano il vero true

Esempio 2.15: Valori che ritornano il falso false

Variabili condizionali utilizzando l'operatore ternario

A volte si desidera impostare il valore di una variabile in funzione a una certa condizione. Per farlo si può utilizzare una dichiarazione if/else, ma in molti casi è più

conveniente usare l'operatore ternario. [Definizione:. L'operatore ternario valuta una condizione, se la condizione è vera, restituisce un certo valore, altrimentirestituisce un valore diverso]

Esempio 2.16: L'operatore ternario

L'operatore ternario può essere utilizzato senza restituire un valore alla variabile, ma questo uso è generalmente sconsigliato.

Dichiarazione Switch

Invece di usare una serie di istruzioni if/else/else if/else, a volte può essere utile usare l'istruzione switch. [Definizione: un'istruzione Switch valuta il valore di unavariabile o espressione ed esegue diferenti blocchi di codice a seconda di quel valore.]

Esempio 2.17: Una dichiarazione Switch

Istruzioni switch sono poco utilizzati in JavaScript, perché lo stesso comportamento può essere ottenuto attraverso la creazione di un oggetto, che ha più potenzialitàperché si può riutilizzare, usarlo per i test, e così via. Per Esempio:

Più avanti si tratterà il concetto di oggetti.

1 '0';2 'qualunque stringa';3 []; // un array vuoto4 {}; // un oggetto vuoto5 1; // qualsiasi numero diverso da zero

1 0;2 ''; // una stringa vuota3 NaN; // la variabile JavaScript "not-a-number" (non è un numero)4 null; // un valore nullo5 undefined; // // fare attenzione -- (undefined) può essere ridefinito

1 // imposta foo uguale a 1 se bar è vero;2 // caso contrario, imposta foo uguale a 03 var foo = bar ? 1 : 0;

01 switch (foo) {02 03 case 'bar':04 alert('il valore è bar');05 break;06 07 case 'baz':08 alert('il valore è baz');09 break;10 11 default:12 alert('impostazione predefinita, questo codice verrà eseguito');13 break;14 15 }

01 var stuffToDo = {02 'bar' : function() {03 alert('il valore è bar');04 },05 06 'baz' : function() {07 alert('il valore è baz');08 },09 10 'default' : function() {11 alert('impostazione predefinita, questo codice verrà eseguito');12 }13 };14 15 if (stuffToDo[foo]) {16 stuffToDo[foo]();17 } else {18 stuffToDo['default']();19 }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

7 di 57 24/08/2012 19:45

Page 8: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Cicli

I cicli (loops in inglese) permettono eseguire un blocco di codice un certo numero di volte.

Esempio 2.18: Cicli

Si noti che nell'esempio si utilizza la parola var prima della variabile i, questo significa che detta variabile è all'interno della sua portata, o ambito, (in inglese scope)

del ciclo. Più avanti in questo capitolo si esaminerà in modo approfondito il concetto di portata.

Cicli utilizzando FOR

Un ciclo utilizzando for si compone da quattro Stati e ha la seguente struttura:

Lo stato espressioneIniziale viene eseguito una solavolta, prima che il ciclo cominci. Questo dà la possibilità di preparare o di dichiarare le variabili.

Lo stato condizione viene eseguita prima di ogni iterazione, e restituisce un valore che decide se il ciclo deve continuare oppure no. Se lo stato condizionale valuta unvalore come falso il ciclo si interrompe.

Lo stato incrementoDellaEspressione viene eseguito alla fine di ogni ripetizione e offre l'opportunità di modificare lo stato di variabili importanti. Di solito, questo statocomporta l'incremento o il decremento di un contatore.

Il corpoCiclo è il codice da eseguire in ogni iterazione del ciclo. In genere ci sono più istruzioni che devono essere eseguiti e così li avvolgono in un blocco ({...}).

Un tipico ciclo utilizzando for:

Esempio 2.19: Un tipico ciclo utilizzando for

Cicli utilizzando WHILE

Un ciclo utilizzando while è simile ad un'istruzione condizionale if, tranne che il corpo continuerà a funzionare fino a quando la condizione da valutare sia falsa.

Un típico bucle utilizzando while:

Esempio 2.20: Un típico bucle utilizzando while

Si può notare che nell'esempio viene incrementato il contatore all'interno del corpo del ciclo, ma è anche possibile combinare la condizione e l'incremento, comeillustrato di seguito:

Esempio 2.21: Ciclo utilizzando while con la combinazione della condiz ione e l'incremento

la variabile i inizia a -1 e poi utilizza l'incremento anticipato (++i).

Cicli utilizzando do-while

Questo ciclo è come usare while, tranne che il corpo viene eseguito almeno una volta prima che la condizione venga valutata.

Esempio 2.22: Un ciclo do-while

1 // mostra nella console 'tentativo 0', 'tentativo 1', ..., 'tentativo 4'2 for (var i=0; i<5; i++) {3 console.log('tentativo ' + i);4 }

1 for ([espressioneIniziale]; [condizione]; [incrementoDellaEspressione])2 [corpoCiclo]

1 for (var i = 0, limit = 100; i < limit; i++) {2 // Questo blocco di codice viene eseguito 100 volte3 console.log('Attualmente a ' + i);4 // Nota: L'ultimo record da visualizzare5 // nella console sarà "Attualmente a 99"6 }

1 while ([condizione]) [corpoCiclo]

1 var i = 0;2 while (i < 100) {3 4 // Questo blocco di codice verrà eseguito 100 volte5 console.log('Attualmente a ' + i);6 7 i++; // incrementa la variabile i8 9 }

1 var i = -1;2 while (++i < 100) {3 // Questo blocco di codice verrà eseguito 100 volte4 console.log('Attualmente a ' + i);5 }

1 do [corpoCiclo] while ([condizione])

1 do {2

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

8 di 57 24/08/2012 19:45

Page 9: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Tali cicli sono abbastanza insoliti, perché raramente si ha bisogno di un ciclo che esegua un giro almeno una volta. In entrambi i casi si dovrebbe essere a conoscenza.

Break e Continue

Di solito, la fine dell'esecuzione di un ciclo coinciderà quando la condizione non continui a valutare un valore vero, tuttavia è anche possibile fermare un cicloutilizzando l'istruzione break all'interno del corpo.

Esempio 2.23: Fermare un ciclo con b reak

Può anche accadere che si desidera continuare il ciclo senza dover eseguire più dichiarazioni del corpo del ciclo. Questo può essere fatto utilizzando l'istruzionecontinue.

Esempio 2.24: Saltare alla seguente iterazione di un ciclo

Parole Riservate

JavaScript ha un numero di "parole riservate", o parole che sono speciali all'interno dello stesso linguaggio. Si dovrebbe utilizzare queste parole quando si ha bisognoper il suo uso specifico.

abstract

boolean

break

byte

case

catch

char

class

const

continue

debugger

default

delete

do

double

else

enum

export

extends

final

finally

float

for

function

goto

if

implements

import

in

instanceof

int

interface

long

native

new

package

private

protected

public

return

short

3 // Anche quando la condizione è falsa4 // il corpo del ciclo viene eseguito almeno una volta.5 6 alert('Ciao!');7 8 } while (false);

1 for (var i = 0; i < 10; i++) {2 if (qualcosa) {3 break;4 }5 }

01 for (var i = 0; i < 10; i++) {02 03 if (qualcosa) {04 continue;05 }06 07 // La seguente dichiarazione sarà eseguita08 // se la condizione 'something' non si compie09 console.log('I have been reached');10 11 }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

9 di 57 24/08/2012 19:45

Page 10: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

static

super

switch

synchronized

this

throw

throws

transient

try

typeof

var

void

volatile

while

with

Vettori o Matrici

I vettori (in inglese arrays) sono liste di valori a indice zero (in inglese zero-index), cioè il primo elemento della matrice è l'indice 0. sono un modo conveniente permemorizzare un insieme di dati correlati (come stringhe), ma in realtà, un array può includere più tipi di dati, compresi altri array.

Esempio 2.25: Un vettore semplice

Esempio 2.26: Accedere agli elementi dell'array attraverso il suo indice

Esempio 2.27: Ottenere il numero di elementi dell'array

Esempio 2.28: Modificare il valore di un elemento di un array

Come mostrato nell'esempio "Modificare il valore di un elemento di un array" è possibile modificare il valore di un elemento di un array, in genere non è consigliabile.

Esempio 2.29: Aggiungere elementi ad un array

Esempio 2.30: Lavorando con gli array

Oggetti

Gli oggetti sono elementi che possono contenere zero o più insiemi di coppie di nomi chiave e valori associati a tale oggetto. I nomi possono essere qualsiasi parola onumero valido. Il valore può essere qualsiasi tipo di valore: un numero, una stringa, un array, una funzione, anche un altro oggetto.

[Definizione: Quando uno dei valori di un oggetto è una funzione, è chiamato come metodo dell'oggetto.] In caso contrario, essi sono chiamati proprietà..

È interessante notare che in JavaScript, quasi tutto è un oggetto - array, funzioni, numeri, anche le stringhe - e tutti possiedono proprietà e metodi.

Esempio 2.31: Creazione di un "oggetto letterale"

Nota

Si noti che quando si creano oggetti letterali, il nome della proprietà può essere qualsiasi identificatore JavaScript, una stringa (racchiusa tra virgolette) o unnumero:

1 var myArray = [ 'ciao', 'mondo' ];

1 var myArray = [ 'ciao', 'mondo', 'foo', 'bar' ];2 console.log(myArray[3]); // mostra 'bar' nella console

1 var myArray = [ 'ciao', 'mondo' ];2 console.log(myArray.length); // mostra '2' nella console

1 var myArray = [ 'ciao', 'mondo' ];2 myArray[1] = 'modificato';

1 var myArray = [ 'ciao', 'mondo' ];2 myArray.push('nuovo');

1 var myArray = [ 'c', 'i', 'a', 'o' ];2 var myString = myArray.join(''); // 'ciao'3 var mySplit = myString.split(''); // [ 'c', 'i', 'a', 'o' ]

01 var myObject = {02 sayHello : function() {03 console.log('ciao');04 },05 06 myName : 'Rebecca'07 };08 09 myObject.sayHello(); // si chiama il metodo sayHello, che10 // visualizza sulla console 'Ciao'11 console.log(myObject.myName); // si chiama la proprietà myName, che12 // mostra 'Rebecca' nella console

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

10 di 57 24/08/2012 19:45

Page 11: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Gli oggetti letterali possono essere molto utile per l'organizzazione del codice, per maggiori informazioni potete leggere l'articolo (in inglese) Using Objects toOrganize Your Code di Rebecca Murphey.

Funzioni

Le funzioni contengono blocchi di codice che viene eseguito ripetutamente. Alle stesse possono essere passati argomenti, e facoltativamente la funzione può restituireun valore.

Le funzioni possono essere creati in diversi modi:

Esempio 2.32: Dichiarazione di una funzione

Esempio 2.33: Dichiarare una funzione denominata

È preferibile il metodo della funzione denominata a causa di alcuni motivi tecnici profondo. Probabilmente troverete i due metodi quando si revisiona il codiceJavaScript.

Utilizzo delle Funzioni

Esempio 2.34: Una semplice funzione

Esempio 2.35: Una funzione che restituisce un valore

Esempio 2.36: Una funzione che restituisce un'altra funzione

Funzioni Anonime Autoeseguilili

Un modello comune in JavaScript sono le funzioni anonime autoeseguibili. Questo modello consiste in creare un'espressione di funzione ed immediatamente eseguirla.Lo stesso è utile nei casi in cui non si vuole intervenire nei namespace globale, perché nessuna variabile dichiarata all'interno della funzione è visibile dall'esterno.

Esempio 2.37: Una funzione anonima autoeseguib ile

Funzioni come Argomenti

In JavaScript, le funzioni sono "cittadini di prima classe" — possono essere assegnati alle variabili o passate ad altre funzioni come argomenti. In jQuery, passarefunzioni come argomenti è una pratica molto comune.

Esempio 2.38: Passare una funzione anonima come argomento

1 var myObject = {2 validIdentifier: 123,3 'qualche stringa': 456,4 99999: 7895 };

1 function foo() { /* fa qualcosa */ }

1 var foo = function() { /* fa qualcosa */ }

1 var greet = function(person, greeting) {2 var text = greeting + ', ' + person;3 console.log(text);4 };5 6 7 greet('Rebecca', 'Ciao');

1 var greet = function(person, greeting) {2 var text = greeting + ', ' + person;3 return text;4 };5 6 console.log(greet('Rebecca','ciao'));

1 var greet = function(person, greeting) {2 var text = greeting + ', ' + person;3 return function() { console.log(text); };4 };5 6 7 var greeting = greet('Rebecca', 'Ciao');8 greeting();

1 (function(){2 var foo = 'Ciao mondo';3 })();4 5 6 console.log(foo); // indefinito (undefined)

1 var myFn = function(fn) {2 var result = fn();3 console.log(result);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

11 di 57 24/08/2012 19:45

Page 12: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 2.39: Passare una chiamata di funzione come argomento

Determinazione del tipo di variabile

JavaScript offre un modo per verificare il "tipo" (in inglese type) di una variabile. Tuttavia, il risultato può essere fonte di confusione - per Esempio, il tipo di array è un"object".

Per ciò, è pratica comune usare l'operatore typeof quando si tratta di determinare il tipo di un valore specifico.

Esempio 2.40: Determinare il tipo tra differenti variabili

jQuery fornisce metodi per determinare il tipo di un certo valore. Questi metodi si vedranno più avanti.

La parola chiave this

In JavaScript, come in molti linguaggi di programmazione object-oriented, this è una parola chiave speciale che fa riferimento all'oggetto in cui il metodo viene

invocato. Il valore di this viene determinato utilizzando una serie di semplici passi:

Se la funzione viene invocata utilizzando Function.call o Function.apply, this avrà il valore del primo argomento passato al metodo. Se l'argomento è nullo(null) o indefinito (undefined), this farà riferimento all'oggetto globale (l'oggetto window);

1.

Se la funzione a invocare viene creata utilizzando Function.bind, this sarà il primo argomento che viene passato alla funzione, al momento della sua creazione;2.Se la funzione è invocata come metodo di un oggetto, this farà riferimento a detto oggetto;3.Altrimenti, se la funzione viene invocata come una funzione indipendente, non legata ad alcun oggetto, this farà riferimento all'oggetto globale.4.

Esempio 2.41: Una funzione invocata utilizzando Function.call

4 };5 6 // mostra nella console 'Ciao mondo'7 myFn(function() { return 'Ciao mondo'; });

01 var myFn = function(fn) {02 var result = fn();03 console.log(result);04 };05 06 var myOtherFn = function() {07 return 'Ciao mondo';08 };09 10 // mostra nella console 'Ciao mondo'11 myFn(myOtherFn);

01 var myFunction = function() {02 console.log('ciao');03 };04 05 var myObject = {06 foo : 'bar'07 };08 09 var myArray = [ 'a', 'b', 'c' ];10 11 var myString = 'ciao;12 13 var myNumber = 3;14 15 typeof myFunction; // ritorna 'function'16 typeof myObject; // ritorna 'object'17 typeof myArray; // ritorna 'object' -- fare attenzione18 typeof myString; // ritorna 'string';19 typeof myNumber; // ritorna 'number'20 21 typeof null; // ritorna 'object' -- fare attenzione22 23 24 if (myArray.push && myArray.slice && myArray.join) {25 // probabilmente è un array26 // (questo stile è chiamato, in inglese, "duck typing")27 }28 29 if (Object.prototype.toString.call(myArray) === '[object Array]') {30 // definitivamente è un array;31 // questa è considerata la forma più robusta32 // per determinare se un valore è un array.33 }

01 var myObject = {02 sayHello : function() {03 console.log('Ciao! il mio nome è ' + this.myName);04 },05 06 myName : 'Rebecca'07 };08 09 var secondObject = {10 myName : 'Colin'11 };12 13 myObject.sayHello(); 14 // registra 'Ciao, il mio nome è Rebecca'15 myObject.sayHello.call(secondObject);16 // registra 'Ciao, il mio nome è Colin'

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

12 di 57 24/08/2012 19:45

Page 13: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 2.42: Una función creada utilizando Function.bind

Esempio 2.43: Una funzione vincolata ad un oggetto

Nota

A volte, quando si invoca una funzione che si trova all'interno di uno spazio dei nomi (namespace in inglese) ampio, si può essere tentati di salvare il riferimentoalla funzione corrente in una variabile più breve ed accessibile. Tuttavia, è importante non farlo nelle istanze dei metodi, giacché possono portare all'esecuzionedel codice errato. Per Esempio:

Per evitare che questi errori si verifichino, è necessario fare riferimento all'oggetto dove il metodo e invocato:

Ambito

"L'ambito" (scope in inglese) si riferisce a variabili che sono disponibili in un blocco di codice in un dato tempo. La mancanza di comprensione di questo concetto puòessere un'esperienza frustrante durante la depurazione.

Quando una variabile viene dichiarata all'interno di una funzione utilizzando la parola chiave var, è disponibile solo per il codice all'interno della funzione - tutto il

codice al di fuori della funzione non può accedere alla variabile. D'altra parte, le funzioni definite all'interno della funzione potranno accedere alla variabile dichiarata.

Le variabili dichiarate all'interno della funzione senza la parola chiave var non rimangono nell'ambito di applicazione della stessa funzione - JavaScript cercherà il luogo

dove la variabile è stata precedentemente dichiarata, e nel caso che non sia stata dichiarata, sarà definita nell'ambito globale, il quale può portare a risultati inattesi;

Esempio 2.44: Le funzioni hanno accesso alle variabili definite all'interno dello stesso ambito

01 var myName = 'the global object',02 03 sayHello = function () {04 console.log('Ciao, il mio nome è ' + this.myName);05 },06 07 myObject = {08 myName : 'Rebecca'09 };10 11 var myObjectHello = sayHello.bind(myObject);12 13 sayHello(); // registra 'Ciao, il mio nome è oggetto globale'14 myObjectHello(); // registra 'Ciao, il mio nome è Rebecca'

01 var myName = 'oggetto globale',02 03 sayHello = function() {04 console.log('Ciao, il mio nome è ' + this.myName);05 },06 07 myObject = {08 myName : 'Rebecca'09 },10 11 secondObject = {12 myName : 'Colin'13 };14 15 myObject.sayHello = sayHello;16 secondObject.sayHello = sayHello;17 18 sayHello(); // registra 'Ciao, il mio nome è oggetto globale'19 myObject.sayHello(); // registra 'Ciao, il mio nome è Rebecca'20 secondObject.sayHello(); // registra 'Ciao, il mio nome è Colin'

01 var myNamespace = {02 myObject : {03 sayHello : function() {04 console.log('Ciao, il mio nome è ' + this.myName);05 },06 07 myName : 'Rebecca'08 }09 };10 11 var hello = myNamespace.myObject.sayHello;12 13 hello(); // registra 'Ciao, il mio nome è undefined'

01 var myNamespace = {02 myObject : {03 sayHello : function() {04 console.log('Ciao!, il mio nome è ' + this.myName);05 },06 07 myName : 'Rebecca'08 }09 };10 11 var obj = myNamespace.myObject;12 13 obj.sayHello(); // registra 'Ciao!, il mio nome è Rebecca'

1 var foo = 'Ciao';

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

13 di 57 24/08/2012 19:45

Page 14: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 2.45: Il codice esterno non può accedere alla variab ile definita all'interno della funzione

Esempio 2.46: Variabili con nomi identici ma diversi valori possono esistere in diversi ambiti

Esempio 2.47: Le funzioni possono "vedere" le modifiche nelle variabili prima che la funzione sia definita

Esempio 2.48: Ambito folle

Chiusure

Le chiusure (closures in inglese) sono un'estensione del concetto di ambito (scope) - funzioni che hanno accesso alle variabili che sono disponibili all'interno dell'ambitoin cui è stata creata la funzione. Se questo concetto è confuso, non preoccuparsi: si capisce meglio attraverso degli esempi.

Nell'sempio 2.47 il modo in cui le funzioni hanno accesso per cambiare il valore delle variabili. Lo stesso comportamento si verifica nelle funzioni create all'interno deicicli - la funzione "osserva" il cambiamento nella variabile, anche dopo che la funzione sia stata definita, risultando che ad ogni click appaia una finestra di avvisomostrando il valore 5.

Esempio 2.49: Come impostare il valore di i?

Esempio 2.50: Impostare il valore di i utilizzando una chiusura

2 3 var sayHello = function() {4 console.log(foo);5 };6 7 sayHello(); // mostra nella console 'Ciao'8 console.log(foo); // mostra anche nella console 'Ciao'

1 var sayHello = function() {2 var foo = 'Ciao';3 console.log(foo);4 };5 6 sayHello(); // mostra nella console 'Ciao'7 console.log(foo); // non mostra niente nella console

1 var foo = 'mondo';2 3 var sayHello = function() {4 var foo = 'ciao';5 console.log(foo);6 };7 8 sayHello(); // mostra nella console 'ciao'9 console.log(foo); // mostra nella console 'mondo'

01 var myFunction = function() {02 var foo = 'Ciao';03 04 var myFn = function() {05 console.log(foo);06 };07 08 foo = 'mondo';09 10 return myFn;11 };12 13 var f = myFunction();14 f(); // registra 'mondo' -- errore

01 // a self-executing anonymous function02 (function() {03 var baz = 1;04 var bim = function() { alert(baz); };05 bar = function() { alert(baz); };06 })();07 08 console.log(baz); // La console non mostra nulla,09 // visto che baz è definita nell'ambito10 // della funzione anonima11 12 bar(); // bar è definita al di fuori della funzione13 // anonima dopo essere stata dichiarata senza la14 // parola chiave var; inoltre, come è stata15 // definita all'interno della stessa portata di16 // baz, è possibile interrogare il valore del baz,17 // anche se questa sia definita all'interno18 // della portata della funzione anonima19 20 bim(); // bim non è definito per essere accessibile21 // al di fuori della funzione anonima,22 // quindi viene visualizzato un errore

1 /* questo non si comporta come desiderato */2 /* ogni click visualizzerà una finestra di avviso con il valore 5 */3 for (var i=0; i<5; i++) {4 $('<p>click me</p>').appendTo('body').click(function() {5 alert(i);6 });7 }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

14 di 57 24/08/2012 19:45

Page 15: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Le chiusure possono anche essere utilizzate per risolvere i problemi con la parola chiave this, la quale è unica per ogni ambito.

Esempio 2.51: Utilizzando una chiusura per accedere simultaneamente ad istanze di oggetti interni ed esterni

Questo meccanismo può essere utile quando si lavora con funzioni di richiamo o retro-chiamate (callbacks in inglese). Tuttavia, in questi casi è preferibile usareFunction.bind per evitare qualunque sovraccarico associatoall'ambito (scope).

Torna in cima

Nozioni di base di jQuery

$(document).ready()

Non si può interagire di forma sicura con il contenuto di una pagina fino a quando il documento non è pronto per la manipolazione. jQuery permette rilevare questostato attaverso la dichiarazione $(document).ready() in modo che il blocco viene eseguito solo una volta che la pagina sia disponibile.

Esempio 3.1: Il b locco $(document).ready()

C'è una scorciatoia per $(document).ready() che potete trovare a volte, ma si consiglia di non utilizzare se si scrive codice per le persone che non conoscono jQuery.

Esempio 3.2: Forma abbreviata per $(document).ready()

E' anche possibile passare a $(document).ready() il nome di una funzione al posto di una anonima.:

Esempio 3.3: Passare il nome di una funzione al posto di una funzione anonima

Selezione di elementi

1 /* soluzione: "clausurare" il valor di i all'interno di createFunction */2 var createFunction = function(i) {3 return function() { alert(i); };4 };5 6 for (var i=0; i<5; i++) {7 $('<p>click me</p>').appendTo('body').click(createFunction(i));8 }

01 var outerObj = {02 myName : 'esterno',03 outerFunction : function () {04 05 // fornisce un riferimento allo stesso oggetto outerObj06 // da utilizzare all'interno di innerFunction07 var self = this;08 09 var innerObj = {10 myName : 'interno',11 innerFunction : function () {12 console.log(self.myName, this.myName);13 // registra 'esterno interno'14 }15 };16 17 innerObj.innerFunction();18 19 console.log(this.myName);20 // registra 'esterno'21 }22 };23 24 outerObj.outerFunction();

1 $(document).ready(function() {2 console.log('il ocumento è pronto!');3 });

1 $(function() {2 console.log('il ocumento è pronto!');3 });

1 function readyFn() {2 // codice da eseguire quando il documento è pronto3 }4 5 6 $(document).ready(readyFn);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

15 di 57 24/08/2012 19:45

Page 16: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Il concetto di base di jQuery è quello di "selezionare alcuni elementi ed eseguire azioni su di essi." La libreria supporta la maggior parte dei selettori CSS3 e molti nonstandardizzati. In http://api.jquery.com/category/selectors/ può trovare un riferimento completo sui selettori della libreria.

Di seguito sono elencate alcune tecniche comuni per la selezione degli elementi:

Esempio 3.4: Selezione di elementi in base al loro ID

Esempio 3.5: Selezione di elementi in base al nome della classe

Esempio 3.6: Selezione di elementi per il suo attributo

Esempio 3.7: Selezione di elementi in forma di selettore CSS

Esempio 3.8: Pseudo-selettori

Nota

Quando si utilizzano i pseudo-selettori: :visible e :hidden, jQuery verifica la corrente visibilità del elemento; ma non se questi sono già stati assegnati con gli

stili CSS visibility o display - in altre parole, verifica se l'altezza e la larghezza fisica dell'elemento è maggiore di zero. Tuttavia, questo controllo non

funziona con gli elementi <tr>; in questo caso, jQuery verifica se si sta' applicando lo stile display e prenderà in considerazione l'elemento come nascosto se è

stato assegnato il valore none. Inoltre, gli elementi che non sono ancora state aggiunte al DOM saranno trattati come nascosti, anche se hanno stili applicati come

visibili (nella sezione sulla manipolazione di questo manuale si spiega come creare e aggiungere elementi al DOM)

Per avere un riferimento, il seguente è il frammento di codice che utilizza jQuery per determinare quando un elemento è visibile o meno. I commenti sono statiinseriti per rendere più chiara la sua comprensione:

Scelta di Selettori

La scelta di buoni selettori è un punto importante quando si desidera migliorare le prestazioni del codice. Un po' di specificità - per esempio includere il tipo di elemento(ad esempio, div)(come div), quando viene effettuata una selezione dal nome della classe - può aiutare molto. Pertanto, si consiglia di dare alcuni "suggerimenti" a

jQuery su dove si può trovare nel documento ciò che si desidera selezionare. D'altra parte, la troppa specificità può essere dannosa. Un selettore come #miaTabella

thead tr th.especiale è un eccesso, sarebbe meglio usare #miaTabella th.especiale.

jQuery fornisce molti selettori basati sugli attributi che consentono di fare delle selezioni in base ai contenuti degli attributi utilizzando semplificazioni con delleespressioni regolari.

Questi tipi di selettori possono essere utili ma sono anche molto lenti. Quando possibile, si dovrebbe fare la selezione utilizzando gli ID, i nomi delle classi e nomi dei tag.

1 $('#myId'); // si noti che l'ID deve essere univoco per ogni pagina

1 $('div.myClass'); // se si specifica il tipo di elemento,2 // si migliora le prestazioni della selezione

1 $('input[name=first_name]'); // attenzione, che può essere molto lento

1 $('#contents ul.people li');

1 $('a.external:first'); // il primo elemento <a> con la classe 'external'2 $('tr:odd'); // gli elementi <tr> dispari di una tabella3 $('#myForm :input'); // gli elementi del tipo input4 $('div:visible'); // gli elementi <div> visibili5 $('div:gt(2)'); // gli elementi <div> tranne i primi tre6 $('div:animated'); // gli elementi <div> attualmente animati

01 jQuery.expr.filters.hidden = function( elem ) {02 var width = elem.offsetWidth, height = elem.offsetHeight,03 skip = elem.nodeName.toLowerCase() === "tr";04 05 // Scelta di Selettori ha 0 di altezza,06 // 0 di larghezza e non è <tr>?07 return width === 0 && height === 0 && !skip ?08 09 // allora deve essere nascosto (hidden)10 true :11 12 // ma se ha larghezza e l'altezza e non è un <tr>13 width > 0 && height > 0 && !skip ?14 15 // allora deve essere visibile16 false :17 18 // se siamo qui è perché l'elemento ha larghezza19 // e altezza, ma è anche un <tr>, quindi verifica20 // il valore dello stile display applicato attraverso21 // i CSS per decidere se è nascosto o meno22 jQuery.curCSS(elem, "display") === "none";23 };24 25 jQuery.expr.filters.visible = function( elem ) {26 return !jQuery.expr.filters.hidden( elem );27 };

1 // trovare tutti gli <a> cui attributi finiscono in "thinger"2 $("a[rel$='thinger']");

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

16 di 57 24/08/2012 19:45

Page 17: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Per saperne di più su questo argomento, Paul Irish ha fatto una grande presentazione sui miglioramenti delle prestazioni Javascript (in inglese), diverse diapositivecentrate sui selettori.

Verificare Selezioni

Una volta realizzata la selezione degli elementi, si vorrà sapere se detta selezione ha dato alcuni risultati. Per fare questo, si può scrivere qualcosa del genere:

Tuttavia questo non funzionerà. Quando viene effettuata una selezione con $(), restituisce sempre un oggetto, e se essa viene valutata, ritornerrà sempre true. Anche

se la selezione non contiene alcun elemento, il codice all'interno del blocco if viene eseguito.

Invece di utilizzare il codice di prima, la cosa da fare è chiedere il numero di elementi che ha la selezione che è stata eseguita. E' possibile fare usando la proprietàJavaScript, length. Se la risposta è 0, la condizione restituisce false, altrimenti (più di 0 elementi), la condizione è vera.

Esempio 3.9: Valutare se una selezione ha degli elementi

Salvare Selezioni

Ogni volta che viene effettuata una selezione, un sacco di codice viene eseguito. jQuery non salva il risultato da se, quindi se si effettua una selezione che poi si farà dinuovo, è necessario salvare la selezione in una variabile.

Esempio 3.10: Salvare le selezioni su una variab ile

Nota

Nell'esempio "Salvare le selezioni su una variabile", la variabile inizia con il simbolo del dollaro. A differenza di altri linguaggi di programmazione, in JavaScript,questo segno non ha un significato speciale - è solo un altro carattere. Ma qui è usato per indicare che la variabile è un oggetto jQuery. Questa pratica - una sortadi notazione ungherese - è solo una convenzione e non obbligatoria.

Una volta che la selezione è memorizzata nella variabile, può essere utilizzato in combinazione con i metodi di jQuery e il risultato sarà lo stesso se si utilizza la selezioneoriginale.

Nota

La selezione prende solo gli elementi che sono sulla pagina quando tale azione ha avuto luogo. Se poi si aggiungono elementi al documento, sarà necessarioripetere la selezione o aggiungere nuovi elementi alla selezione memorizzata nella variabile. In altre parole, le selezioni salvate non vengono aggiornati"magicamente" quando cambia il DOM.

Affinamento e Filtro delle Selezioni

A volte si può ottenere una selezione che contiene più del necessario, in questo caso, è necessario affinare la selezione. jQuery fornisce diversi modi per ottenereesattamente quello che si desidera.

Esempio 3.11: Affinamento delle selezioni

Selezione di elementi di un Form

jQuery fornisce diverse pseudo-selettori per aiutare a trovare gli elementi nei forms; questi sono particolarmente utili perché a seconda degli stati di ogni elemento otipo, possono essere difficili distinguergli utilizzando i normali selettori CSS.

:button

Seleziona elementi <button> e con l'attributo type="button"

:checkbox

Seleziona elementi <input> con l'attributotype="checkbox"

:checked

Seleziona elementi <input> del tipo checkbox selezionati

:disabled

Seleziona elementi del form che sono disabilitati

1 if ($('div.foo')) { ... }

1 if ($('div.foo').length) { ... }

1 var $divs = $('div');

1 $('div.foo').has('p'); // l'elemento div.foo contiene elementi <p>2 $('h1').not('.bar'); // l'elemento h1 non possiede la clase 'bar'3 $('ul li').filter('.current');// un item di una lista non ordinata che4 // possiede la classe 'current'5 $('ul li').first(); // il primo item de una lista non ordinata6 $('ul li').eq(5); // el sesto item de una lista non ordinata

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

17 di 57 24/08/2012 19:45

Page 18: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

:enabled

Seleziona elementi del formu che sono abilitati

:file

Seleziona elementi <input> con l'attributo type="file"

:image

Seleziona elementi <input> con l'attributo type="image"

:input

Seleziona elementi <input>, <textarea> e <select>

:password

Seleziona elementi <input> con el atributo type="password"

:radio

Seleziona elementi <input> con l'attributo type="radio"

:reset

Seleziona elementi <input> con l'attributo type="reset"

:selected

Seleziona elementi <options> che sono selezionati

:submit

Seleziona elementi <input> con l'attributo type="submit"

:text

Seleziona elementi <input> con l'attributo type="text"

Esempio 3.12: Utilizzando pseudo-selettori sugli elementi dei forms

Lavorare con le selezioni

Una volta realizzata la selezione di elementi, è possibile utilizzareliin in combinazione con diversi metodi. Sono generalmente di due tipi: gli ottenetori (in inglese getters)e gli stabilitori (setters in inglese). I metodi Getter restituiscono una proprietà metodi del elemento selezionato, mentre i metodi Setter fissano una proprietà a tutti glielementi selezionati.

Concatenazione

Se in una selezione viene effettuata una chiamata a un metodo e restituisce un oggetto jQuery, è possibile seguire un metodo "incatenato" nell'oggetto.

Esempio 3.13: Concatenando

D'altra parte, se si sta scrivendo una serie di metodi che includono molti passi, e possibile scriverli linea per linea, rendendo l'aspetto del codice più piacevole da leggere.

Esempio 3.14: Formattazione del codice incatenato

Per tornare alla selezione originale in mezzo alla concatenazione, jQuery fornisce il metodo $.fn.end per farlo.

Esempio 3.15: Ripristinare la selezione originale utilizzando il metodo $.fn.end

1 $('#myForm :input'); // ottiene tutti gli elementi input nel form #myForm

1 $('#content').find('h3').eq(2).html('testo per il terzo elemento h3!');

1 $('#content')2 .find('h3')3 .eq(2)4 .html('testo per il terzo elemento h3!');

1 $('#content')2 .find('h3')3 .eq(2)4 .html('testo per il terzo elemento h3!')5 .end() // ripristina tutti gli elementi h3 in #content6 .eq(0)7 .html('testo per il primo elemento h3!');

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

18 di 57 24/08/2012 19:45

Page 19: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Nota

La concatenazione è molto potente ed è una caratteristica che molte librerria JavaScript hanno adottato da che jQuery è diventato popolare. Tuttavia, dovrebbeessere usato con cautela. Una concatenazione di metodi estensivi può rendere il codice molto difficile da modificare e depurare. Non c'è una regola che indichiquanto lungo o corto dovrebbe essere la concatenazione - ma si dovrebbe prendere in considerazione questo consiglio.

Ottenitori (Getters) & Impostatori (Setters)

jQuery "sovraccarica" i suoi metodi, in altre parole, il metodo per impostare un valore ha lo stesso nome del metodo per ottenere un valore. Quando un metodo vieneutilizzato per impostare un valore, il metodo viene chiamato impostatori (setter inglese). Tuttavia, quando un metodo viene utilizzato per ottenere (o leggere) un valoresi chiama ottenitori (getter in inglese).

Esempio 3.16: Il metodo $.fn.html utilizzato come impostatore

Esempio 3.17: Il metodo html utilizzato come ottenitore

I metodi impostatori restituiscono un oggetto jQuery, che consente di continuare la chiamata sui più metodi nella stessa selezione, mentre i metodi ottenitori restituisceil valore che è stato consultato, ma non possono continuare ad invocare altri metodi su quel valore.

CSS, Stili & Dimensioni

jQuery include un modo utile per ottenere e impostare le proprietà CSS agli elementi.

Nota

Le proprietà CSS che includono un trattino in mezzo come separatore, in JavaScript deve essere trasformato nel suo stile CamelCase. Per Esempio quando laproprietà è usata come un metodo, lo stile CSS font-size dovrà essere espressa come fontSize. Tuttavia, questa regola non viene applicata quando si passa il

nome della proprietà CSS al metodo $.fn.css. - In questo caso, i due formati (in CamelCase o con il trattino in mezzo) funzionano.

Esempio 3.18: Ottenendo le proprietà CSS

Esempio 3.19: Impostando le proprietà CSS

Si noti che lo stile dell'argomento utilizzato nella quarta linea dell'esempio - è un oggetto che contiene più proprietà. Questo è un modo comune per passare argomentia una funzione, e molti metodi impostatori della libreria accettano oggetti per fissare varie proprietà in una sola volta.

Utilizzare Classi per applicare Stili CSS

Per ottenere i valori degli stili applicati a un elemento, il metodo $. $.fn.css è molto utile, tuttavia il suo uso come metodo impostatore (setter) deve essere evitato

(giacché, per applicare degli stili a un elemento, si può fare direttamente da CSS ). Al suo posto, l'ideale sarebbe quello di scrivere le regole CSS da applicare alle classiche descriverebbero i vari stati visuali degli elementi e quindi modificare la classe degli elementi per applicare lo stile che si desidera visualizzare.

Esempio 3.20: Lavorare con le classi

Le classi possono anche essere utile per salvare qualche informazione di stato, per esempio, per indicare che un elemento è stato selezionato.

Dimensioni

jQuery offre una varietà di metodi per ottenere e impostare valori di dimensioni e posizione di un elemento.

Il codice riportato nell'esempio "Dimensioni - Metodi di base" è solo un breve riassunto delle funzionalità sui rapporti dimensionali di jQuery, tutti i dettagli possonoessere trovati http://api.jquery.com/category/dimensions/.

Esempio 3.21: Dimensioni - Metodi di base

1 $('h1').html('ciao mondo');

1 $('h1').html();

1 $('h1').css('fontSize'); // restituisce una stringa come "19px"2 $('h1').css('font-size'); // funziona lo stesso

1 // imposta una proprietà singola CSS2 $('h1').css('fontSize', '100px');3 // imposta molteplici proprietà CSS4 $('h1').css({ 'fontSize' : '100px', 'color' : 'red' });

1 var $h1 = $('h1');2 3 $h1.addClass('big');4 $h1.removeClass('big');5 $h1.toggleClass('big');6 7 if ($h1.hasClass('big')) { ... }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

19 di 57 24/08/2012 19:45

Page 20: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Attributi

Gli attributi degli elementi HTML che costituiscono un'applicazione può contenere informazioni utili, quindi è importante potere impostare e ottenere questeinformazioni.

Il metodo $.fn.attr funge sia da metodo getter che da metodo setter. Inoltre, come metodo di $.fn.css, se usato come metodo setter può accettare una serie di

parole chiave-valore o un oggetto che contiene più serie.

Esempio 3.22: Impostare attributi

Nell'esempio, l'oggetto passato come argomento è scritto in diverse linee. Come spiegato in precedenza, gli spazi non contano in JavaScript, quindi si è liberi di usarliper rendere il codice più leggibile. In ambienti di produzione, è possibile utilizzare strumenti di minimizzazione, che elimina gli spazi in bianco (tra le altre cose) ecomprimere il file di output.

Esempio 3.23: Ottenere attributi

Attraversare il DOM

Una volta ottenuta la selezione, è possibile trovare altri oggetti utilizzando la stessa selezione.

In http://api.jquery.com/category/traversing/ può trovare una documentazione completa sui metodi di attraversamento del DOM (in inglese traversing) che hajQuery.

Nota

Si deve fare attenzione nel percorrere lunghe distanze in un documento — percorsi complessi richiedono che la struttura del documento sia sempre la stessa, cosache è difficile da garantire. Uno - o due - step per il giro va bene, ma generalmente bisogna evitare di attraversare da un contenitore all'altro.

Esempio 3.24: Muoversi attraverso il DOM usando metodi di attraversamento

È possibile interagire con la selezione utilizzando il metodo $.fn.each. Questo metodo interagisce con tutti gli elementi ottenuti nella selezione ed esegue una funzione

per ciascuno. La funzione prende come argomento l'indice dell'elemento corrente e lo stesso elemento. Per impostazione predefinita, all'interno della funzione, èpossibile fare riferimento all'elemento DOM attraverso la dichiarazione this.

Esempio 3.25: Interagire in una selezione

Manipolazione di Elementi

Una volta realizzata la selezione degli elementi che si desidera utilizzare, "inizia il divertimento". È possibile modificare, spostare, rimuovere e duplicare. Anche crearnedi nuovi attraverso una sintassi semplice.

La documentazione completa sui metodi di manipolazione può essere trovata in http://api.jquery.com/category/manipulation/.

1 $('h1').width('50px'); // imposta la larghezza di tutti gli elementi H12 $('h1').width(); // ottiene la larghezza del primo elemento H13 4 $('h1').height('50px');// imposta l'altezza di tutti gli elementi H15 $('h1').height(); // Ottiene l'altezza del primo elemento H16 7 $('h1').position(); // Restituisce un oggetto che contiene informazioni8 // circa la posizione del primo elemento relativo a9 // "offset" (posizione) dal suo elemento genitore

1 $('a').attr('href', 'allMyHrefsAreTheSameNow.html');2 $('a').attr({3 'title' : 'con i titoli è la stessa cosa!',4 'href' : 'somethingNew.html'5 });

1 $('a').attr('href'); // restituisce il primo valore dell'attributo href2 // appartenente al elemento <a> del documento

01 $('h1').next('p'); // seleziona l'elemento successivo <p>02 // immediatamente dopo <h1>03 $('div:visible').parent(); // seleziona il contenitore padre04 // di un elemento <div> visibile05 $('input[name=first_name]').closest('form'); // seleziona dal più06 // vicino <form> un input07 $('#myList').children(); // seleziona tutti gli elementi figlio08 // di #myList09 $('li.selected').siblings(); // seleziona tutti gli elementi fratelli10 // del elemento <li>

1 $('#myList li').each(function(idx, el) {2 console.log(3 'L\'elemento ' + idx +4 'ha il seguente html: ' +5 $(el).html()6 );7 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

20 di 57 24/08/2012 19:45

Page 21: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Ottenre e Impostare Informazioni negli Elementi

Ci sono molti modi in cui è possibile modificare un elemento. Tra le operazioni più comuni ci sono quelle per cambiare l'HTML all'interno o qualche suo attributo. Perquesti compiti, jQuery fornisce metodi semplici e funzionali in tutti i browser moderni. E' anche possibile ottenere informazioni sugli elementi utilizzando gli stessimetodi, ma nel loro metodo come ottenitore getter.

Nota

Apportare modifiche agli elementi, è un lavoro banale, ma ricordate che la modifica interesserà tutti gli elementi nella selezione, quindi se si vuole cambiare unsingolo elemento, è necessario assicurarsi di specificarlo nella selezione prima di chiamare il metodo impostatore setter.

Nota

Quando i metodi agiscono come ottenitori getter, solitamente lavorano solo con il primo elemento della selezione. Inoltre non restituiscono nessun oggetto

jQuery, quindi non è possibile concatenare più metodi su di esso. Un'eccezione è il metodo $.fn.text, che consente di ottenere il testo degli elementi della

selezione.

$.fn.html

Ottiene o imposta il contenuto HTML di un elemento.

$.fn.text

Ottiene o imposta il contenuto in texto piano dell'elemento; nel caso di pasarli come argomento del codice HTML, questo sarà ripulito dai sui tag.

$.fn.attr

Ottiene o imposta il valore di un determinato attributo.

$.fn.width

Ottiene o imposta la larghezza in pixels del primo elemento della selezione come un intero.

$.fn.height

Ottiene o imposta l'altezza in pixeles del primo elemento della selezione come un intero.

$.fn.position

Ottiene un oggetto con informazioni sulla posizione del primo elemento della selezione relativa al primo elemento genitore posizionato. Questo metodo è soloottenitore (getter).

$.fn.val

Ottiene o imposta il valore (value) negli elementi dei forms.

Esempio 3.26: Modificare il codice HTML di un elemento

Spostare, copiare e rimuovere Element

Ci sono diversi modi per spostare gli elementi attraverso del DOM, i quali si possono suddividere in due approcci:

Volere mettere il/gli elementi selezionati rispetto ad altri elementi

Volere mettere un elemento rispetto ad altri elementi selezionati.

Per esempio, jQuery fornisce metodi $.fn.insertAfter e $.fn.after. Il metodo $.fn.insertAfter colloca il/gli elementi selezionati dopo l'elemento che è stato

passato come argomento, mentre il metodo $.fn.after colloca l'elemento passato come argomento dopo l'elemento selezionato. Altri metodi seguono anche questo

modello:$.fn.insertBefore e $.fn.before;

$.fn.appendTo e $.fn.append;

e $.fn.prependTo e $.fn.prepend.

L'uso di uno o un altro metodo dipende dagli elementi che hanno selezionato e il tipo di riferimento che si desidera salvare rispetto all'elemento che si sta muovendo.

Esempio 3.27: Spostare oggetti con differenti approcci

Clonare Elementi

1 $('#myDiv p:first')2 .html('Nuovo <strong>primo</strong> parragrafo!');

1 // fare il che primo elemento della lista sia l'ultimo2 var $li = $('#myList li:first').appendTo('#myList');3 4 // un altro approccio allo stesso problema5 $('#myList').append($('#myList li:first'));6 7 // Va notato che non c'è modo di accedere8 // alla lista degli items che è stata spostata,9 // giacché restituisce la lista stessa

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

21 di 57 24/08/2012 19:45

Page 22: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Quando si utilizza un metodo come $.fn.appendTo, ciò che si sta facendo è spostare all'elemento, ma a volte, anziché questo, si vuole spostare un duplicato

dell'elemento. In questo caso, è possibile utilizzare il metodo $.fn.clone.

Esempio 3.28: Ottenere una copia del elemento

Nota

Se avete bisogno di copiare le informazioni e gli eventi legati al elemento, si deve passare true come argomento di $.fn.clone.

Rimuovere Elementi

Ci sono due modi per rimuovere gli elementi di una pagina: Utilizzando $.fn.remove ó $.fn.detach. Quando si desidera rimuovere l'elemento in modo permanente,

utilizzare il metodo $.fn.remove.

D'altra parte, il $.Fn.detach rimuove anche l'elemento, ma conserva le informazioni e gli eventi associati ad esso, essendo utile in caso di necessità di reinserire

l'elemento nel documento.

Nota

Il metodo $.fn.detach è molto utile quando si manipola fortemente un elemento, giacché è possibile eliminare l'elemento, lavorarlo nel codice e quindi

ripristinarlo nuovamente sulla pagina. Questa forma ha il vantaggio di non toccare il DOM mentre si sta modificando delle informazioni e gli eventi dell'elemento.

D'altra parte, se si desidera mantenere l'elemento, ma si ha bisogno di rimuovere i uso contenuto, è possibile utilizzare il metodo $.fn.empty, il quale "svuoterà" il

contenuto HTML dell'elemento.

Creare nuovi Elementi

jQuery fornisce un modo semplice ed elegante per creare nuovi oggetti utilizzando lo stesso metodo di $() che viene utilizzato per effettuare selezioni.

Esempio 3.29: Creare nuovi elementi

Esempio 3.30: Creare un nuovo elemento con attributi utilizzando un oggetto

Si noti che nell'oggetto che si passa come argomento, la proprietà class è tra virgolette, mentre la proprietà href e html non lo sono. In generale, i nomi delle proprietànon dovrebbero essere tra virgolette, ad eccezione dei nomi che vengono usati come una parola riservata (come nel caso della classe).

Quando si crea un elemento, non è immediatamente aggiunto alla pagina, ma se deve farlo in combinazione con un metodo.

Esempio 3.31: Creare un nuovo elemento nella pagina

A rigor di termini, non è necessario salvare l'elemento creato in una variabile - è possibile chiamare il metodo per aggiungere l'elemento direttamente subito dopo il$().

Tuttavia, la maggior parte delle volte si desidererà fare riferimento all'elemento aggiunto, e quindi, se si salva in una variabile non c'è bisogno di selezionarlo più tardi.

Esempio 3.32: Creare e aggiungere allo stesso tempo un elemento alla pagina

Nota

La sintassi per aggiungere nuovi elementi alla pagina è molto facile da usare, ma si è tentati di dimenticare che esiste un enorme costo in termini di prestazioni

1 // copiare il primo elemento della lista2 // e spostarlo alla fine dello stesso3 $('#myList li:first').clone().appendTo('#myList');

1 $('<p>Questo è un nuovo paragrafo</p>');2 $('<li class="nuovo">nuovo item della lista</li>');

1 $('<a/>', {2 html : 'Questo è un <strong>nuovo</strong> link',3 'class' : 'nuovo',4 href : 'foo.html'5 });

1 var $myNewElement = $('<p>Nuovo elemento</p>');2 $myNewElement.appendTo('#content');3 4 $myNewElement.insertAfter('ul:last');5 // eleminerà l'elemento <p> esistente in #content!6 $('ul').last().after($myNewElement.clone()); 7 // clonare l'elemento <p> per avere due versioni

1 $('ul').append('<li>item della lista</li>');

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

22 di 57 24/08/2012 19:45

Page 23: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

mentre si aggiunge degli elementi al DOM ripetutamente. Se si sta aggiungendo molti elementi allo stesso contenitore, piuttosto che aggiungere ogni elemento unoper volta, il migliore sistema è quella di concatenare tutto l'HTML in una singola catena di stringhe e poi allegarla al contenitore. Una possibile soluzione è quelladi utilizzare un array che contenga tutti gli elementi e poi unirli usando join per finalmente allegarla.

Manipolazione di Attributi

Le capacità per la gestione degli attributi che offre la libreria jQuery sono ampie. L'esecuzione di modifiche di base sono semplici, ma il metodo $.fn.attr consente

manipolazioni complesse.

Esempio 3.33: Manipolazione di un singolo attributo

Esempio 3.34: Manipolazione di più attributi

Esempio 3.35: Utilizzare una funzione per determinare il valore del nuovo attributo

Esercizi

Selezioni

Aprire il file /exercises/index.html nel tuo browser. Eseguire l'esercizio utilizzando il file /exercises/js/sandbox.js o lavorare direttamente con Firebug per

compiere i seguenti punti:

Selezionare tutti gli elementi div che hanno classe "module".1.

Specificare tre selezioni che possono selezionare il terzo item della lista non ordinata #myList. Qual è il migliore da usare e perché?2.

Selezionare l'elemento label dell'elemento input mediante un selettore di attributo.3.

Verificare quanti elementi della pagina sono nascosti (suggerimento:. .length)4.

Verificare quante immagini sulla pagina hanno l'attributo alt.5.

Selezionare tutte le righe dispari del corpo della tabella.6.

Percorrere il DOM

Aprire il file /exercises/index.html nel tuo browser. Eseguire l'esercizio utilizzando il file /exercises/js/sandbox.js o lavorare direttamente con Firebug per

compiere i seguenti punti:

Selezionare tutte le immagini sulla pagina, registrare nella console l'attributo alt di ogni immagine.1.

Selezionare l'elemento di input, poi andare al form e aggiungere una classe ad esso.2.

Selezionare l'item che ha la classe di "current" nella lista #myList e rimuovere la classe, poi aggiungere la classe "current" al successivo item della lista.3.

Selezionare l'elemento select all'interno di #special; per poi dirigersi verso il pulsante submit.4.

Selezionare il primo item della lista nell'elenemto #slideshow; aggiungere la classe "current" ad esso e poi aggiungere la classe "disabled" agli elementi fratelli.5.

Manipolazione

Aprire il file /exercises/index.html nel tuo browser. Eseguire l'esercizio utilizzando il file /exercises/js/sandbox.js o lavorare direttamente con Firebug per

compiere i seguenti punti:

Aggiungere 5 nuovi elementi alla fine della lista non ordinata # myList. Suggerimento:1.

Rimuovere gli elementi dispari dalla lista.2.

Aggiungere un altro elemento h2 e un altro paragrafo all'ultimo div.module.3.

1 var myItems = [], $myList = $('#myList');2 3 for (var i=0; i<100; i++) {4 myItems.push('<li>item ' + i + '</li>');5 }6 7 $myList.append(myItems.join(''));

1 $('#myDiv a:first').attr('href', 'newDestination.html');

1 $('#myDiv a:first').attr({2 href : 'newDestination.html',3 rel : 'super-special'4 });

01 $('#myDiv a:first').attr({02 rel : 'super-special',03 href : function(idx, href) {04 return '/new/' + href;05 }06 });07 08 $('#myDiv a:first').attr('href', function(idx, href) {09 return '/new/' + href;10 });

1 for (var i = 0; i<5; i++) { ... }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

23 di 57 24/08/2012 19:45

Page 24: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Aggiungere un'altra opzione all'elemento select, danno all'opzione aggiunta il valore "Wednesday".4.

Aggiungere un nuovo div.module alla pagina dopo l'ultima pagina; e quindi aggiungere una copia di una delle immagini esistenti nel nuovo div.5.

Torna in cima

Il nucleo di jQuery

$ vs $()

Finora, è stato trattato pienamente con i metodi che vengono chiamati dall'oggetto jQuery. Per Esempio:

Tali metodi fanno parte dello spazio dei nomi (namespace in inglese) $.fn, o prototipo (prototype in inglese) jQuery, e sono considerati come metodi dell'oggetto

jQuery.

Tuttavia, ci sono metodi che fanno parte del namespace $ e sono considerati come metodi del nucleo di jQuery.

Queste distinzioni possono essere molto confuse per i nuovi utenti. Per evitare confusione, ricordare questi due punti:

I metodi utilizzati nelle selezioni si trovano all'interno dello spazio dei nomi $.fn, e automaticamente ricevono e restituiscono una selezione in sè.Metodi nello spazio dei nomi $ sono generalmente metodi per diverse utilità, non lavorano con le selezioni, non vengono passati argomenti e valore di ritornopuò variare.

Ci sono alcuni casi in cui i metodi dell'oggetto e del nucleo hanno gli stessi nomi, come succede con $.each e $.fn.each. In questi casi, è necessario fare attenzione a

leggere attentamente la documentazione per sapere quale oggetto usare in modo corretto.

Metodi di utilità

jQuery fornisce diversi metodi di utilità all'interno dello spazio dei nomi $. Questi metodi sono di grande aiuto per svolgere compiti di routine di programmazione. Di

seguito alcuni esempi, per una documentazione completa visita http://api.jquery.com/category/utilities/.

$.trim

Rimuove gli spazi bianchi all'inizio e alla fine.

$.each

Interagisce negli array e negli oggetti.

Nota

Come accennato in precedenza, c'è un metodo chiamato $.fn.each, che interagisce in una selezione di elementi.

$.inArray

Restituisce l'indice di un valore in una matrice, o -1 se il valore non si trova nella matrice.

$.extend

Cambia le proprietà del primo oggetto utilizzando le proprietà degli oggetti successivi.

Se non si desidera modificare le proprietà di nessun oggetto che vengono utilizzati in $.extend, si deve includere un oggetto vuoto come primo argomento.

1 $('h1').remove();

1 $.trim(' stringa con più spazi vuoti ');2 // restituisce 'stringa con più spazi vuoti'

1 $.each([ 'foo', 'bar', 'baz' ], function(idx, val) {2 console.log('elemento ' + idx + 'es ' + val);3 });4 5 $.each({ foo : 'bar', baz : 'bim' }, function(k, v) {6 console.log(k + ' : ' + v);7 });

1 var myArray = [ 1, 2, 3, 5 ];2 3 if ($.inArray(4, myArray) !== -1) {4 console.log('valore trovato!');5 }

1 var firstObject = { foo : 'bar', a : 'b' };2 var secondObject = { foo : 'baz' };3 4 var newObject = $.extend(firstObject, secondObject);5 console.log(firstObject.foo); // 'baz'6 console.log(newObject.foo); // 'baz'

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

24 di 57 24/08/2012 19:45

Page 25: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

$.proxy

Restituisce una funzione che si eseguirà sempre nel campo di applicazione (scope) fornito - in altre parole, stabilisce il significato di this (incluso all'internodella funzione) come secondo argomento.

Se si dispone di un oggetto con metodi, è possibile passare l'oggetto e il nome di un metodo per restituire una funzione che si eseguirà sempre nell'ambito di taleoggetto.

Verificazione dei Tipi

Come accennato nel capitolo "Concetti di base di JavaScript" jQuery fornisce diversi metodi utili per determinare il tipo di un valore specifico.

Esempio 4.1: Verificare il tipo di un determinato valore

Il Metodo Data

Spesso vi accorgerete che ci sono informazioni su un elemento che ha bisogno di essere salvate. In JavaScript è possibile farlo con l'aggiunta di proprietà all'elementoDOM, ma questa pratica implica avere a che fare con perdite di memoria (memory leaks in inglese) in alcuni browser. jQuery fornisce un modo semplice permemorizzare informazioni relative a un elemento, e la stessa libreria è responsabile per affrontare i problemi che possono nascere dalla mancanza di memoria.

Esempio 4.2: Salvare e recuperare informazioni relative a un elemento

Attraverso il metodo $.fn.data si possono salvare qualunque tipo di informazioni su un elemento, ed è difficile esagerare l'importanza di questo concetto durante lo

sviluppo di un'applicazione complessa.

Per esempio, se si vuole stabilire una relazione tra l'item di una lista e il div che è all'interno di questo item, è possibile farlo ogni volta che si interagisce con l'item, mauna soluzione migliore è farlo una sola volta, salvando un puntatore al div utilizzando il metodo $.fn.data:

Esempio 4.3: Relazione tra gli elementi utilizzando il metodo $.fn.data

E' anche possibile passare al metodo u$.fn.data n oggetto contenente una o più coppie di parole chiave-valore.

1 var firstObject = { foo : 'bar', a : 'b' };2 var secondObject = { foo : 'baz' };3 4 var newObject = $.extend({}, firstObject, secondObject);5 console.log(firstObject.foo); // 'bar'6 console.log(newObject.foo); // 'baz'

1 var myFunction = function() { console.log(this); };2 var myObject = { foo : 'bar' };3 4 myFunction(); // restituisce l'oggetto window5 6 var myProxyFunction = $.proxy(myFunction, myObject);7 myProxyFunction(); // restituisce l'oggetto myObject

01 var myObject = {02 myFn : function() {03 console.log(this);04 }05 };06 07 $('#foo').click(myObject.myFn);08 // registra el elemento DOM #foo09 $('#foo').click($.proxy(myObject, 'myFn'));10 // registra myObject

01 var myValue = [1, 2, 3];02 03 // Utilizzare l'operatore typeof di JavaScript04 // per controllare tipi primitivi05 typeof myValue == 'string'; // false (falso)06 typeof myValue == 'number'; // false (falso)07 typeof myValue == 'undefined'; // false (falso)08 typeof myValue == 'boolean'; // false (falso)09 10 // Utilizzare l'operatore di uguaglianza rigorosa11 // per controllare i valori nulli12 myValue === null; // false (falso)13 14 // Utilizzare metodi di jQuery per testare15 // i tipi non primitivi16 jQuery.isFunction(myValue); // false (falso)17 jQuery.isPlainObject(myValue); // false (falso)18 jQuery.isArray(myValue); // true (vero)

1 $('#myDiv').data('keyName', { foo : 'bar' });2 $('#myDiv').data('keyName'); // { foo : 'bar' }

01 $('#myList li').each(function() {02 var $li = $(this), $div = $li.find('div.content');03 $li.data('contentDiv', $div);04 });05 06 // poi, non si deve tornare a cercare al div;07 // è possibile leggerlo dall'informazione08 // associata all'item della lista09 var $firstLi = $('#myList li:first');10 $firstLi.data('contentDiv').html('nuovo contenuto');

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

25 di 57 24/08/2012 19:45

Page 26: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Rilevamento browser e caratteristiche

Con jQuery, oltre a rimuovere la maggior parte delle caratteristiche di JavaScript tra ogni browser, ci sono dei momenti in cui è necessario eseguire codice su un browserspecifico.

Per tali situazioni, jQuery fornisce l'oggetto $.support e $.browser (quest'ultimo non più utilizzato). Una documentazione completa su questi oggetti si trovano in

http://api.jquery.com/jQuery.support/ e http://api.jquery.com/jQuery.browser/

L'obiettivo di $.support è quello di determinare quali caratteristiche supporta il browser.

L'oggetto $.browser rileva il tipo di browser e la sua versione. Questo oggetto è deprecato (anche se nel breve termine non è previsto l'eliminazione dal nucleo della

libreria) e si raccomanda utilizzare l'oggetto $.support per questi scopi.

Evitare conflitti con altre librerie JavaScript

Se si sta utilizzando jQuery in combinazione con altre librerie JavaScript, i quali utilizzano anche la variabile $, può generare un certo numero di errori. Per risolvere il

problema, è necessario mettere a jQuery in modo "non-conflitto". Questo dovrebbe essere fatto immediatamente dopo che jQuery si carichi sulla pagina e prima che ilcodice venga eseguito.

Quando jQuery è impostato in modo "non-conflitto", la libreria offre la possibilità di assegnare un nome per sostituire la variabile $.

Esempio 4.4: Mettere jQuery in modo non-conflitto

E 'anche possibile continuare a utilizzare $ contenente il codice in una funzione anonima auto-eseguibile. Questo è un modello standard per la creazione di estensioni alla

libreria, dal momento che $ rimane racchiusa all'interno del campo di applicazione della stessa funzione anonima.

Esempio 4.5: Utilizzare $ all'interno di una funzione anonima auto-eseguibile

Torna in cima

Eventi

Introduzione

jQuery fornisce i metodi per associare i gestori di eventi (event handlers in inglese) ai selettori. Quando si verifica un evento, la funzione fornita viene eseguita.

All'interno della funzione, la parola chiave $this fa riferimento all'elemento in cui si verifica l'evento.

Per maggiori dettagli sugli eventi in jQuery, è possibile consultare http://api.jquery.com/category/events/.

La funzione del gestore di eventi è in grado di ricevere un oggetto. Questo oggetto può essere utilizzato per determinare la natura del evento o, per esempio, evitare il suocomportamento predefinito.

Per maggiori informazioni sull'oggetto dell'evento, visitare http://api.jquery.com/category/events/event-object/.

Vincolare Eventi a Elementi

jQuery fornisce metodi per la maggior parte degli eventi — tra questi ci sono $.fn.click, $.fn.focus, $.fn.blur, $.fn.change, etc. Queste ultime sono le versioni

ridotte del metodo $.fn.bind di jQuery. Il metodo bind è utile per vincolare (in inglese binding) la stessa funzione di gestore degli eventi a più eventi, per quando si

desidera fornire le informazioni al gestore di eventi, quando si lavorando con eventi personalizzati o quando si desidera passare un oggetto a più eventi e controllori.

Esempio 5.1: Collegamento di un evento utilizzando un metodo ridotto

1 // la libreria prototype utilizza anche $2 <script src="prototype.js"></script>3 // si carica jquery nella pagina4 <script src="jquery.js"></script>5 // se inizializza $j in modo "non-conflitto"6 <script>var $j = jQuery.noConflict();</script>

1 <script src="prototype.js"></script>2 <script src="jquery.js"></script>3 <script>4 jQuery.noConflict();5 6 (function($) {7 // codice va qui, e può utilizzare $8 })(jQuery);9 </script>

1 $('p').click(function() {2 console.log('click');3 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

26 di 57 24/08/2012 19:45

Page 27: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 5.2: Collegamento di un evento utilizzando il metodo $.fn.b ind

Esempio 5.3: Collegamento di un evento utilizzando il metodo $.fn.b ind con informazione associata

Collegare Eventi per essere eseguiti una sola volta

A volte potrebbe essere necessario che un controller particolare venga eseguito solo una volta - e dopo di questo, abbiamo bisogno che nessun altro si esegua, o fareeseguire uno diverso. A tal fine, jQuery fornisce il metodo $.fn.one.

Esempio 5.4: Cambiare controller usando il metodo $.fn.one method

Il metodo $.fn.one è utile per situazioni in cui è necessario eseguire un certo codice la prima volta che si verifica un evento su un elemento, ma non in eventi

successivi.

Scollegare Eventi

Per scollegare (in inglese unbind) un gestore di eventi, è possibile utilizzare il metodo $.fn.unbind passando il tipo di evento da scollegare. Se si passa come allegato di

una funzione chiamata, è possibile isolare lo scollegamento di tale funzione come secondo argomento.

Esempio 5.5: Scollegare tutti i controllori di evento click in una selezione

Esempio 5.6: Scollegare un controllore di evento particolare click

Spazio di Nomi per gli Eventi

Nello sviluppo di applicazioni complesse o estensioni di jQuery, può essere utile usare i spazi di nomi (in inglese namespace) per gli eventi, e quindi prevenire che siscolleghino eventi quando no lo si desidera.

Esempio 5.7: Spazio di Nomi per gli Eventi

Collegamento di più eventi

Molto spesso, gli elementi in un'applicazione sono collegati ad eventi multipli, ognuno con una funzione diversa. In questi casi è possibile passare un oggetto in$.fn.bind con una o più coppie di nomi chiave/valore. Ogni nome chiave sarà il nome dell'evento, mentre ogni valore sarà la funzione da eseguire quando si verifica

l'evento.

Esempio 5.8: Collegare più eventi a un elemento

1 $('p').bind('click', function() {2 console.log('click');3 });

01 $('input').bind(02 'click change', // è possibile collegare più eventi03 // all'elemento04 { foo : 'bar' }, // deve essere passato come argomento05 // le informazioni associatea06 07 function(eventObject) {08 console.log(eventObject.type, eventObject.data);09 // registra il tipo di evento e l'informazione10 // associata { foo : 'bar' }11 }12 );

1 $('p').one('click', function() {2 console.log('fatto click la prima volta!');3 $(this).click(function() { console.log('fatto click di nuovo!'); });4 });

1 $('p').unbind('click');

1 var foo = function() { console.log('foo'); };2 var bar = function() { console.log('bar'); };3 4 $('p').bind('click', foo).bind('click', bar);5 $('p').unbind('click', bar); // foo è lagato all'evento click

1 $('p').bind('click.myNamespace', function() { /* ... */ });2 $('p').unbind('click.myNamespace');3 $('p').unbind('.myNamespace');4 // scollega tutti gli eventi con5 // lo spazio dei nomi myNamespace

1 $('p').bind({2 'click': function() {3 console.log('fatto click!');4 },5 'mouseover': function() {6 console.log('il mouse è sopra!');7 }8 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

27 di 57 24/08/2012 19:45

Page 28: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Nota

L'opzione di passare un oggetto con più eventi e funzioni a $.fn.bind è stato introdotto in jQuery 1.4.4.

L'Oggetto del Evento

Come accennato nell'introduzione, la funzione di gestore di eventi riceve un oggetto del evento, il quale contiene diversi metodi e proprietà. L'oggetto vienecomunemente utilizzato per prevenire l'azione predefinita del evento attraverso il metodo preventDefault. Tuttavia, contiene anche diverse proprietà e metodi utili:

pageX, pageY

La posizione del mouse quando l'evento si è verificato, relativa la parte superiore e sinistra della pagina.

type

Il tipo di evento (per esempio "click").

which

Il pulsante o tasto premuto.

data

Informazioni passate quando l'evento viene eseguito.

target

L'elemento DOM che ha inizializzato l'evento..

preventDefault()

Annulla l'azione predefinita dell'evento (per esempio: seguire un link).

stopPropagation()

Ferma la diffusione dell'evento su altri elementi.

D'altra parte, il funzione controller ha anche accesso all'elemento DOM che ha inizializzato l'evento attraverso la parola chiave this. Per convertire l'elemento DOM in

un oggetto jQuery (e potere utilizzare i metodi della libreria) deve essere scritto $(this), come illustrato di seguito:

Esempio 5.9: Annullare che facendo click su un link, questo si esegua

Esecuzione automatica dei Controllori di Eventi

Attraverso il metodo $.fn.trigger, JQuery fornisce un modo per attivare i gestori di eventi su un elemento senza richiedere intervento dell'utente. Anche se questo

metodo ha i suoi usi, non dovrebbe essere utilizzato per chiamare semplicemente una funzione che può essere eseguito con un clic dell'utente. Invece, si dovrebbesalvare la funzione che è necessario chiamare in una variabile e quindi passare il nome della variabile quando si effettua il collegamento (binding). In questo modo, èpossibile chiamare la funzione ogni volta che si vuole invece di eseguire $.fn.trigger.

Esempio 5.10: Sparare un gestore di eventi nel modo giusto

Incrementare le prestazioni con la delegazione di Eventi

Quando si lavora con jQuery, spesso si aggiungono nuovi elementi alla pagina, e quando lo si fa, è necessario collegare eventi a di questi elementi — eventi che erano giàcollegati agli elementi nella pagina. Piuttosto che ripetere l'operazione ogni volta che si aggiunge un elemento, si può usare la delega di eventi. Con questo, è possibileassociare un evento a un elemento contenitore, e poi, quando si verifica l'evento, è possibile vedere in quale elemento succede. Se tutto questo suona complicato,fortunatamente jQuery lo rende facile attraverso i metodi $.fn.live e $.fn.delegate.

La delega di eventi ha alcuni benefici, anche se non avete in programma di aggiungere altri elementi alla pagina. Il tempo necessario per legare i gestori di eventi acentinaia di elementi non è un lavoro banale; se si dispone di un grande insieme di elementi, è consigliabile utilizzare la delegazione di eventi a un elemento contenitore.

1 var $this = $(this);

1 $('a').click(function(e) {2 var $this = $(this);3 if ($this.attr('href').match('evil')) {4 e.preventDefault();5 $this.addClass('evil');6 }7 });

01 var foo = function(e) {02 if (e) {03 console.log(e);04 } else {05 console.log('questa azione non proviene da un evento!');06 }07 };08 09 10 $('p').click(foo);11 12 foo(); // invece di eseguire $('p').trigger('click')

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

28 di 57 24/08/2012 19:45

Page 29: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Nota

Il metodo $.fn.live è stato introdotto dalla versione 1.3 della libreria e poi, solo determinati tipi di eventi erano supportati. A partire dalla versione 1.4.2, si è

introdotto $.fn.delegate che è preferito a $. Fn.live.

Esempio 5.11: Delegare un evento con $.fn.delegate

Esempio 5.12: Delegare un evento con $.fn.live

Scollegare Eventi Delegati

Se è necessario rimuovere gli eventi delegati, non lo si può semplicemente scollegare. Per questo, utilizzare il $.fn.undelegate per gli eventi connessi con

$.fn.delegate, e $.fn.die per gli eventi connessi con $.fn.live. Come quando si effettua un legame, opzionalmente, è possibile passare il nome di una funzione

legata.

Esempio 5.13: Scollegare Eventi Delegati

Funzioni ausiliarie degli Eventi

jQuery fornisce due funzioni ausiliarie per lavorare con gli eventi:

$.fn.hover

Il metodo $.fn.hover permette passare una o due funzioni da eseguire quando si verificano gli eventi mouseenter e mouseleave. Se si passa una sola funzione, questa

sarà eseguita in entrambi gli eventi, ma invece se si passano due, la prima sarà eseguita quando si verifica l'evento mouseenter, mentre la seconda sarà eseguita quando

si verifica mouseleave.

Nota

Dalla versione 1.4 di jQuery, il metodo richiede due funzioni obbligatorie.

Esempio 5.14: La funzione ausiliaria hover

$.fn.toggle

Come il metodo precedente, $.fn.toggle riceve due o più funzioni, ogni volta che si verifica un evento, la funzione seguente nella lista verrà eseguita. In generale,

$.fn.toggle viene utilizzata con solo due funzioni. Se si utilizzano più di due funzioni, fate attenzione, perché può essere difficile eseguire il debug del codice.

Esempio 5.15: La funzione ausiliaria toggle

Esercizi

Creare un "Tip" per una casella di immissione testo

Aprire il file /exercises/index.html dal browser. Eseguire ejericio utilizzando il file /exercises/js/inputHint.js o lavorare direttamente con Firebug. Il

compito è quello di utilizzare etichetta di testo dell'elemento label e applicare un "suggerimento" nella casella di immissione testo. I passi da seguire sono:

Impostare il valore dell'elemento input uguale al valore dell'elemento label;1.

1 $('#myUnorderedList').delegate('li', 'click', function(e) {2 var $myListItem = $(this);3 // ...4 });

1 $('#myUnorderedList li').live('click', function(e) {2 var $myListItem = $(this);3 // ...4 });

1 $('#myUnorderedList').undelegate('li', 'click');2 $('#myUnorderedList li').die('click');

1 $('#menu li').hover(function() {2 $(this).toggleClass('hover');3 });

1 $('p.expander').toggle(2 function() {3 $(this).prev().addClass('open');4 },5 function() {6 $(this).prev().removeClass('open');7 }8 );

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

29 di 57 24/08/2012 19:45

Page 30: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Aggiungere la classe "hint" all'elemento input;2.

Remuover l'elemento label;3.

Collegare un evento focus nell'elemento input per rimuovere il testo di suggerimento e la classe "hint";4.

Collegare un evento blur nel input per ripristinare il testo di suggerimento e la classe "hint" nel caso in cui un testo non hintviene inserito.5.

Quali altre considerazioni si dovrebbero prendere in considerazione se si desidera applicare questa funzionalità a un sito vero e proprio?

Aggiungere una navigazione a schede

Aprire il file /exercises/index.html dal browser. Eseguire ejericio utilizzando il file /exercises/js/tabs.js o lavorare direttamente con Firebug. Il compito è

quello di creare una navigazione a schede per gli elementi div.module. I passi sono da seguire sono:

Nascondere titti gli elementi div.module;1.

Creare una lista non ordinata prima del primo div.module per utilizzarla come schede;2.

Interagire con ogni div.module usando $.fn.each. Per ciascuna, utilizzare il testo dell'elemento h2 come testo per l'elemento della lista non ordinata;Interactuar con cada div utilizando $.fn.each.

3.

Collegare un evento click per ogni elemento nella lista in modo che:

Visualizzare il div corrispondente e nascondere l'altro;

Aggiungere la classe "current" al ítem selezionato;

Rimuovere la classe "current" su l'altro item della lista;

4.

Infine, mostrare la prima scheda.5.

Torna in cima

Effetti

Introduzione

Con jQuery, aggiungere effetti ad una pagina è facile. Questi effetti hanno una impostazione di default, ma si può anche fornire impostazioni personalizzate. E' anchepossibile creare animazioni impostando valori di proprietà specifici del CSS.

Per la documentazione completa sui diversi tipi di effetti si possono visitare http://api.jquery.com/category/effects/.

Effetti incorporati nella Libreria

Gli effetti più comuni sono già incorporati nella libreria sotto forma di metodi:

$.fn.show

Visualizza l'elemento selezionato.

$.fn.hide

Nasconde l'elemento selezionato.

$.fn.fadeIn

In forma animata, modifica l'opacità dell'elemento selezionato al 100%

$.fn.fadeOut

In forma animata, modifica l'opacità dell'elemento selezionato al 0%

$.fn.slideDown

Consente di visualizzare l'elemento selezionato con un movimento a scorrimento verticale.

$.fn.slideUp

Nasconde l'elemento selezionato con un movimento a scorrimento verticale.

$.fn.slideToggle

Visualizza o nasconde l'elemento selezionato con un movimento a scorrimento verticale, a seconda che l'elemento sia correntemente visibile o meno.

Esempio 6.1: Utilizzo di base di un effetto incorporato

1 $('h1').show();

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

30 di 57 24/08/2012 19:45

Page 31: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Cambiare la durata degli effetti

Con l'eccezione di $.fn.show e $.fn.hide, tutti i metodi hanno una durata predefinita dell'animazione di 400ms. Questo valore è possibile cambiarlo.

Esempio 6.2: Impostare la durata degli effetti

jQuery.fx.speeds

jQuery è un oggetto che contiene in jQuery.fx.speeds la velocità predefinita per la durata di un effetto, così come i valori per le definizioni "slow" e "fast".

Pertanto, è possibile sovrascrivere o aggiungere nuovi valori all'oggetto. Per Esempio, quando si vuole cambiare l'effetto predefinito o aggiungere una velocitàpersonalizzata.

Esempio 6.3: Aumentare la velocità con jQuery.fx.speeds

Eseguire un'azione quando un effetto è stato eseguito

Spesso, si desidera eseguire l'azione una volta che l'animazione sia finita — perché se si esegue l'azione prima che l'animazione sia terminata, possono alterare la qualitàdegli effetti o influenzare gli elementi che ne fanno parte. [Definizione: Le funzioni di retrochiamata (callback functions in inglese) forniscono un modo per eseguirecodice quando un evento si è concluso.] In questo caso, l'evento che risponderà alla funzione sarà la conclusione dell'animazione. All'interno della funzione di ritorno, laparola chiave this fa riferimento all'elemento cui è stato eseguito l'effetto, e come accade con gli eventi, è possibile trasformarlo in un oggetto jQuery utilizzando

$(this).

Esempio 6.4: Eseguire del codice quando un'animazione è completata

Si noti che se la selezione non restituisce alcun elemento, la funzione non potrà mai essere eseguita. Questo problema può essere risolto controllando se la selezionerestituisce un oggetto; e in caso contrario eseguire la funzione di retrochiamata immediatamente.

Esempio 6.5: Eseguire una funzione di retrochiamata, anche se non c'è nessun elemento da animare

Effetti personalizzati con $.fn.animate

Le animazioni sono possibili realizzarle utilizzando il metodo $.fn.animate. Questo metodo permette realizzare un'animazione impostando i valori alle proprietà CSS o

cambiando il loro valore corrente.

Esempio 6.6: Effetti personalizzati con $.fn.animate

Nota

LE proprietà relative al colore non possono essere animate con il metodo $.fn.animate, ma è possibile farlo attraverso l'estensione color plugin. Più tardi nel

libro si discuterà l'uso delle estensioni.

Easing

1 $('h1').fadeIn(300); // dissolvenza in 300ms2 $('h1').fadeOut('slow'); // utilizzo di una definizione di velocità interna

1 speeds: {2 slow: 600,3 fast: 200,4 // Velocità predefinita5 _default: 4006 }

1 jQuery.fx.speeds.blazing = 100;2 jQuery.fx.speeds.turtle = 2000;

1 $('div.old').fadeOut(300, function() { $(this).remove(); });

01 var $thing = $('#nonexistent');02 03 var cb = function() {04 console.log('realizzato!');05 };06 07 if ($thing.length) {08 $thing.fadeIn(300, cb);09 } else {10 cb();11 }

1 $('div.funtimes').animate(2 {3 left : "+=50",4 opacity : 0.255 },6 300, // durata7 function() { console.log('done!'); // retrochiamata8 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

31 di 57 24/08/2012 19:45

Page 32: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

[Definizione: Il concetto di Easing descrive il modo come un effetto si verifica - cioè, se la velocità durante l'animazione è costante o meno]. JQuery comprende solo duemetodi di allentamento: swing e linear. Per ulteriori transizioni naturali nelle animazioni, ci sono molte estensioni che lo permettono.

Dalla versione 1.4 della libreria, è possibile impostare il tipo di transizione per ogni proprietà utilizzando il metoso $.fn.animate.

Esempio 6.7: Transiz ione easing per ogni proprietà

Per maggiori dettagli sulle opzioni di easing, si veda http://api.jquery.com/animate/.

Gestione degli Effetti

jQuery offre diversi strumenti per gestire le animazioni.

$.fn.stop

Interrompe le animazioni che sono in esecuzione sull'elemento selezionato.

$.fn.delay

Attende un periodo di tempo specificato prima di eseguire l'animazione successiva.

jQuery.fx.off

Se il valore è vero (true), non ci saranno transizioni per le animazioni e agli elementi si stabilirà lo stato finale dell'animazione. Questo metodo può essereparticolarmente utile quando si lavora con i vecchi browser.

Esercizi

Visualizzare il testo nascosto

Aprire il il file /exercises/index.html nel browser web. Eseguire ejericio utilizzando il file /exercises/js/blog.js. Il compito è quello di aggiungere un po

'interattività alla sezione blog della pagina:

Cliccando su uno qualsiasi dei titolari del div #blog, si dovrebbe visualizzare il testo con un effetto scorrevole;

Facendo clic su un altro titolo, si dovrebbe nascondere il paragrafo mostrato con un effetto di scorrimento e mostrare di nuovo il paragrafo corrispondenteanche con un effetto di scorrimento.

Suggerimento: Non dimenticare di usare il selettore :visible.

Creare una Menù a tendina (Drop Down)

Aprire il file /exercises/index.html nel browser web. Eseguire ejericio utilizzando il file /exercises/js/navigation.js. Il compito è quello di visualizzare le voci

di menu in cima alla pagina:

Passando il mouse su una voce del menu, si dovrebbe visualizzare un sottomenu se esiste;

Quando non è posizionato sopra un item, il sottomenu si dovrebbe nascondere.

Per fare questo, utilizzare il metodo $.fn.hover per aggiungere o rimuovere una classe al sottomenu per controllare se deve essere nascosto o visibile (Il file

/exercises/css/styles.css include una classe "hover" per questo scopo).

Creare un Slideshow

Aprire il file /exercises/index.html nel browser web. Eseguire l'esercizio utilizzando il file /exercises/js/slideshow.js. Il compito è quello di aggiungere uno

slideshow alla pagina con JavaScript.

Spostare l'elemento #slideshow alla parte superiore della pagina;1.

Scrivere un codice per la visualizzazione degli items in maniera ciclica, mostrando un item per alcuni secondi, poi nasconderlo con un effetto fade out emostrare il seguente item con l'effetto di dissolvenza fade in;

2.

Una volta raggiunto l'ultimo elemento della lista, ricominciare con il primo;3.

Per una sfida più grande, creare un area di navigazione sotto lo slideshow che mostra quante immagini ci sono e su quale si trova (suggerimento: $.fn.prevAll può

essere utile).

Torna in cima

1 $('div.funtimes').animate(2 {3 left : [ "+=50", "swing" ],4 opacity : [ 0.25, "linear" ]5 },6 3007 );

1 $('h1').show(300).delay(1000).hide(300);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

32 di 57 24/08/2012 19:45

Page 33: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Ajax

Introduzione

Il metodo XMLHttpRequest (XHR) consente ai browser di comunicare con il server senza ricaricare la pagina. Questo metodo, noto anche come Ajax (AsincronoJavaScript e XML, in inglese Asynchronous JavaScript and XML), consente alle applicazioni di creare interattività.

Le richieste Ajax vengono eseguite dal codice JavaScript, il quale invia una richiesta a un URL e quando riceve una risposta, una funzione di ritorno può essere eseguitail quale riceve come argomento la risposta del server e ne fa qualcosa con questa. Visto che la risposta è asincrona, il resto del codice dell'applicazione continua afunzionare, quindi è imperativo che una funzione di ritorno venga eseguita per gestire la risposta.

Attraverso vari metodi, jQuery fornisce il supporto per AJAX, che consente astrarre le differenze che possono esistere tra i browser. I metodi in questione sono$.get(), $.getScript(), $.getJSON(), $.post() e $().load().

Sebbene la definizione di Ajax ha la parola "XML", la maggior parte delle applicazioni non utilizzare questo formato per il trasporto dei dati, ma al suo posto utilizza testoformato HTML o informazioni in JSON (JavaScript Object Notation).

In generale, l'Ajax non funziona in domini diversi. Tuttavia, ci sono delle eccezioni, come i servizi che forniscono informazioni in formato JSONP (JSON with Padding),che permettono funzionalità limitate in domini diversi.

Concetti chiave

L'uso corretto dei metodi di Ajax richiede in primo luogo la comprensione di alcuni concetti chiave.

GET vs. POST

I due metodi HTTP più comuni per l'invio di una richiesta a un server sono GET e POST. E 'importante capire l'uso di ciascuno.

Il metodo GET dovrebbe essere utilizzato per operazioni non distruttive - cioè, operazioni in cui si sta "ottenendo" dati dal server, e non "modificando". Per Esempio,una query per una ricerca potrebbe essere una richiesta GET. D'altra parte, le richieste GET possono essere memorizzate nella cache del browser e può generarecomportamenti imprevedibili se non attesi. In generale, le informazioni inviate al server, vengono inviati in una stringa di dati (in inglese query string).

Il metodo POST dovrebbe essere utilizzato per operazioni distruttive - cioè operazioni in cui vengono incorporate informazioni nel server. Per Esempio, quando unutente salva un articolo in un blog, questa azione dovrebbe usare POST. D'altra parte, con questo tipo di metodo non viene memorizzato nella cache del browser.Inoltre, una stringa di query può essere parte della URL, ma le informazioni tendono ad essere inviate separatamente.

Tipi de Dati

In generale, jQuery ha bisogno alcune istruzioni sul tipo di informazioni da ricevere quando si effettua una richiesta Ajax. In alcuni casi, il tipo di dati è specificato dalnome del metodo, ma in altri casi dovrebbe essere specificato come perte della configurazione del metodo:

text

Per il trasporto di semplici stringhe.

html

Per il trasporto di blocchi di codice in HTML che verranno inseriti nella pagina.

script

Per aggiungere un nuovo script con codice JavaScript alla pagina.

json

Per trasportare le informazioni in formato JSON, il quale può includere stringhe, array e oggetti.

Nota

Dalla versione 1.4 della libreria, se l'informazione JSON non è correttamente formattata, la richiesta potrebbe non riuscire. Visita http://json.org per idettagli sulla corretta formattazione dei dati JSON.

Si consiglia di utilizzare i meccanismi che possiede il linguaggio lato server per generare le informazioni in JSON.

jsonp

Per trasportare le informazioni JSON da un dominio all'altro.

xml

Per trasportare le informazioni in formato XML.

Nonostante i diversi tipi di dati che possono essere utilizzati, è raccomandato utilizzare il formato JSON, dal momento che è molto flessibile, consentendo per esempio,inviare al tempo stesso informazioni piatte e HTML.

Asincronismo

Perché, per impostazione predefinita, le chiamate Ajax sono asincrone, la risposta del server non è immediatamente disponibile. Per ssempio, il seguente codice nondovrebbe funzionare:

1 var response;2 $.get('foo.php', function(r) { response = r; });3 console.log(response); // undefined - indefinito!

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

33 di 57 24/08/2012 19:45

Page 34: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Invece, è necessario specificare una funzione di ritorno, questa funzione verrà eseguita quando la richiesta si sia conclusa correttamente in quanto è allora che larisposta del server è pronta.

Politiche di Stessa Origine e JSONP

In generale, le richieste Ajax sono limitati a usare lo stesso protocollo (http o https), la stessa porta e lo stesso dominio di origine. Questa limitazione non si applica agliscript caricati tramite i metodi di jQuery Ajax.

L'altra eccezione è quando si fa una richiesta di riceverà una risposta in formato JSONP. In questo caso, il fornitore della risposta dovrebbe rispondere alla richiesta conuno script che può essere caricato utilizzando il tag <script>, evitando così la limitazione ad effettuare richieste dallo stesso dominio. Questa risposta avrà le

informazioni richieste, contenuta in una funzione.

Ajax e Firebug

Firebug (o l'ispettore WebKit che viene in Chrome o Safari) sono strumenti essenziali per lavorare con le richieste Ajax, giacché è possibile osservare dalla schedaconsole di Firebug (o andando in Risorse > Pannello XHR dalla finestra di ispezione Webkit) e vedere i dettagli di queste richieste. Se qualcosa non va a buon finequando si lavora con l'Ajax, questo è il primo posto dive si dovrebbe andare per sapere quale è il problema.

Metodi Ajax de jQuery

Come indicato sopra, jQuery ha diversi metodi per lavorare con Ajax. Tuttavia, tutti si basano sul metodo $.ajax, quindi, la sua comprensione è obbligatoria. Di seguito

si spiegherà il metodo e poi s'indicherà un breve riassunto sugli altri metodi.

E 'generalmente preferibile utilizzare il metodo $.ajax piuttosto che altri, visto che offre più funzionalità e la sua configurazione è molto comprensibile.

$.ajax

Il metodo $.ajax è configurato attraverso un oggetto che contiene tutte le istruzioni che necessita jQuery per completare la richiesta. Questo metodo è particolarmente

utile perché offre la possibilità di specificare azioni se la richiesta sia riuscita o meno. Inoltre, essendo impostato attraverso un oggetto, è possibile impostare leproprietà separatamente, rendendo più facile il riutilizzo del codice. È possibile visitare http://api.jquery.com/jQuery.ajax/ per consultare la documentazione sulleopzioni disponibili nel metodo.

Esempio 7.1: Utilizzare il metodo $.ajax

Nota

Un chiarimento sul parametro dataType: se il server restituisce informazioni differenti dal formato specificato, il codice fallirà e la ragione perché lo faccia non è

sempre chiara, perché la risposta HTTP non mostrerà alcun errore. Quando si lavora con le richieste Ajax, assicurarsi che il server invii il tipo di informazioniche si richiede e verificare che il Content-type sia esattamente al tipo di dati richiesti. Per esempio, per le informazioni in formato JSON, il Content-typedovrebbe essere application/json.

Opzioni del metodo $.ajax

Il metodo $.Ajax ha molte opzioni di configurazione, ed è proprio questa caratteristica che lo rende un metodo molto utile. Per un elenco completo delle opzionidisponibili, consultare http://api.jquery.com/jQuery.ajax/; le seguenti sono le più comuni:

1 $.get('foo.php', function(response) { console.log(response); });

01 $.ajax({02 // l'URL per la richiesta03 url : 'post.php',04 05 // invio di informazioni06 // (è anche possibile utilizzare una stringa di dati)07 data : { id : 123 },08 09 // specificare se si tratta di una richiesta POST o GET10 type : 'GET',11 12 // il tipo di informazioni13 // che ci si attende come risposta14 dataType : 'json',15 16 // codice da eseguire se la richiesta viene accettata;17 // la risposta è passata come argomento alla funzione18 success : function(json) {19 $('<h1/>').text(json.title).appendTo('body');20 $('<div class="content"/>')21 .html(json.html).appendTo('body');22 },23 24 // codice da eseguire se la richiesta fallisce;25 // sono passati come argomenti alla funzione26 // l'oggetto della petizione in codice grezzo27 // e lo stato della richiesta28 error : function(xhr, status) {29 alert('Spiacente, c\'è stato un problema!');30 },31 32 // codice da eseguire indipendentemente dal33 // fatto se la richiesta riesca.34 complete : function(xhr, status) {35 alert('Richiesta fatta!');36 }37 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

34 di 57 24/08/2012 19:45

Page 35: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

async

Imposta se la richiesta è asincrona o meno. Di default il valore è true. È necessario essere consapevoli che se l'opzione è impostata su false, la richiesta

bloccherà l'esecuzione di altri codici fino a quando la richiesta sia completata.

cache

Impostare se la richiesta viene memorizzata nella cache del browser web. Di default è true per tutti i dataType fatta eccezione per "script" e "jsonp". Quando il

valore è false, si aggiunge una stringa anti-cache alla fine della URL della richiesta.

complete

Imposta una funzione di retrochiamata che viene eseguita quando la richiesta sia stata completata, anche se ha fallito. La funzione riceve come argomentil'oggetto della richiesta in grazzo e il codice di status della stessa richiesta.

context

Imposta l'ambito in cui vengono eseguite le funzioni di retrochiamata. (per Esempio definisce il significato di this all'interno delle funzioni). Di default this fa

riferimento all'oggetto passato in origine al metodo $.ajax.

data

Consente di impostare le informazioni da inviare al server. Questo può essere un oggetto come una stringa di dati (per esempio foo=bar&baz=bim).

dataType

Consente di impostare il tipo di informazioni da ricevere in risposta dal server. Se nessun valore è specificato, per impostazione predefinita, jQuery controlla iltipo MIME che ha la risposta.

error

Imposta una funzione di retrociamata da eseguire se si tratta di un errore nella petizione. Detta funzione prende come argomenti l'oggetto della richiesta grezzae il codice di status della richiesta stessa.

jsonp

Imposta il nome della funzione di retrochiamata da inviare quando viene effettuata una richiesta JSONP. Di default il nome è "callback".

success

Imposta una funzione da eseguire se la richiesta ha avuto successo. Questa funzione prende come argomenti le informazioni della richiesta (convertito in unoggetto JavaScript nel caso sia dataType o JSON), lo status della stessa e l'oggetto della petizione in grezzo.

timeout

Imposta il tempo in millisecondi da considerare per una richiesta non riuscita.

traditional

Se il suo valore è true, viene utilizzato lo stile di serializzazione di dati utilizzati nelle versioni di jQuery prima della 1.4. Per maggiori dettagli visitatehttp://api.jquery.com/jQuery.param/.

type

Il tipo di richiesta, "POST" o "GET". Di default il suo valore è "GET". Altre tipi di richieste possono anche essere utilizzati come (come PUT e DELETE), mapossono non essere supportati da tutti i browser.

url

Imposta l'URL in cui è presentata la richiesta.

L'opzione url è obbligatoria per il metodo $.ajax.

Metodi convenienti

Se non si desidera utilizzare il metodo $.ajax, e non necessita manipolare o gestire gli errori, esistono altri metodi più adatti per le richieste Ajax (sebbene, come notato

in precedenza, questi sono basati al metodo $.ajax con valori prestabiliti di configurazione).

I metodi che fornisce la libreria sono:

$.get

Fa una richiesta GET a un URL previsto.

$.post

Fa una richiesta POST a un URL previsto.

$.getScript

Aggiunge uno script alla pagina.

$.getJSON

Fa una richiesta GET a un URL previsto e si aspetta che un dato JSON venga restituito.

I metodi devono avere i seguenti argomenti, in ordine:

url

L'URL in cui si farà la richiesta. Il suo valore è obbligatorio.

data

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

35 di 57 24/08/2012 19:45

Page 36: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Le informazioni inviate al server. Il suo valore è facoltativo e può essere sia un oggetto o una stringa di dati (per esempio foo=bar&baz=bim).

Nota

Questa opzione è valida per il metodo $.getScript.

success callback

Una funzione opzionale che viene eseguita in caso la richiesta ha avuto successo. Questa funzione prende come argomenti le informazioni della richiesta el'oggetto grezzo della petizione.

data type

Il tipo di dati che dovrebbero essere ricevuti dal server. Il suo valore è facoltativo.

Nota

Questa opzione è applicabile solo per i metodi dove non sia specificato il tipo di dati nel nome dello stesso metodo.

Esempio 7.2: Utilizzare metodi appropriati nelle richieste Ajax

$.fn.load

Il metodo $.fn.load è l'unico che può essere chiamato da una selezione. Questo metodo ottiene il codice HTML da un URL e riempire gli elementi selezionati con le

informazioni ottenute. In concomitanza con l'URL, è possibile specificare facoltativamente un selettore, il quale otterrà il codice specificato in questa selezione.

Esempio 7.3: Utilizzare il metodo $.fn.load per riempire un elemento

Esempio 7.4: Utilizzare il metodo $.fn.load per riempire un elemento basato su una selezione.

Ajax e Forms

Le funzionalità di jQuery con Ajax possono essere particolarmente utili per lavorare con i forms. Per esempio, il plugin jQuery Form Plugin è una estensione peraggiungere le funzionalità di Ajax sui forms. Ci sono due metodi che bisogna tenere conto quando si lavora con $.ajax sui forms: $.fn.serialize e

$.fn.serializeArray.

Esempio 7.5: Trasformare le informazioni da una form in una stringa di dati

Esempio 7.6: Creare un array di oggetti che contengono informazioni da un form

Lavorare con JSONP

In tempi recenti, l'introduzione di JSONP, ha permesso la creazione di applicazioni ibride di contenuti. Molti siti offrono importanti offrono JSONP come servizio diinformazione, cui si accede attraverso un'API (Application programming interface in inglese) predefinita. Un particolare servizio che fornisce informazioni in formato

01 // ottiene il testo piano o html02 $.get('/users.php', { userId : 1234 }, function(resp) {03 console.log(resp);04 });05 06 // aggiunge uno script alla pagina e quindi07 // esegue la funzione specificata08 $.getScript('/static/js/myScript.js', function() {09 functionFromMyScript();10 });11 12 // ottiene i dati in formato JSON dal server13 $.getJSON('/details.php', function(resp) {14 $.each(resp, function(k, v) {15 console.log(k + ' : ' + v);16 });17 });

1 $('#newContent').load('/foo.html');

1 $('#newContent').load('/foo.html #myDiv h1:first', function(html) {2 alert('Contenuto aggiornato!');3 });

1 $('#myForm').serialize();

1 $('#myForm').serializeArray();2 3 // crea una struttura come questa:4 [5 { name : 'field1', value : 123 },6 { name : 'field2', value : 'hello world' }7 ]

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

36 di 57 24/08/2012 19:45

Page 37: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

JSONP è Yahoo! Query Language, che lo utilizza per ottenere, per esempio, notizie sui gatti:

Esempio 7.7: Usare YQL e JSONP

jQuery si occupa di risolvere tutti gli aspetti complessi della richiesta JSONP. Tutto quello che si deve fare è specificare il nome della funzione di ritorno (in questo caso"callback", come da specifica YQL) e il risultato finale sarà come una normale richiesta Ajax.

Eventi Ajax

Spesso si desidera eseguire una funzione quando una petizione si avvia o finisca, come per esempio, mostrare o nascondere un indicatore. Invece di definire questefunzioni all'interno di ogni richiesta, jQuery offre la possibilità di vincolare gli eventi Ajax agli elementi selezionati. Per un elenco completo degli eventi Ajax, èdisponibile la pagina http://docs.jquery.com/Ajax_Events.

Esempio 7.8: Mostra/Nascondi un indicatore utilizzando Eventi di Ajax

Esercizi

Caricare contenuto esterno

Open the file /exercises/index.html in your browser. Use the file /exercises/js/load.js. Your task is to load the content of a blog item when a user clicks on the

title of the item.

Creare un elemento div dopo il titolo di ogni titolo di articolo del blog e salvare un riferimento ad essi nell'elemento titolo utilizzando $.fn.data.1.

Vinculare un evento click al titolo, il quale utilizzerà il metodo $.fn.load per caricare in ogni div creato il contenuto appropriato dal file /exercises

/data/blog.html. Non dimenticare di disattivare il comportamento predefinito dell'evento click.

2.

Da notare che ogni titolo di articolo del blog in index.html include un link a questo articolo. Sfruttare l'attributo href di ogni link per ottenere il contenuto particolare diblog.html. Dopo aver ottenuto il valore dell'attributo, utilizzare il seguente form per elaborare le informazioni e convertirla in un selettore per l'uso in combinazione con$.fn.load:

Ricordatevi di usare console.log per assicurarsi che si sta facendo la cosa giusta.

Carricare contenuto utilizzando JSON

Aprire il file /exercises/index.html nel browser web. Eseguire ejericio utilizzando il file /exercises/js/specials.js. Il compito è quello di mostrare i dati

dell'utente in un particolare giorno quando viene selezionato dal menù a discesa.

Aggiungere un elemento div dopo il form all'interno dell'elemento #specials; sarà lì il luogo dove si metteranno le informazioni da ottenere.1.

Vincolare l'evento change sull'elemento select; quando si apporta una modifica nella selezione, inviare una richiesta Ajax a /exercises

/data/specials.json.

2.

Quando la richiesta restituisce una risposta, utilizzare il valore selezionato nella select (suggerimento: $.fn.val) per trovare le informazioni appropriate nella

risposta JSON.

3.

Aggiungere un po' di HTML con le informazioni ottenute nel div creato in precedenza.4.

Infine rimuovere il pulsante di invio (submit) del form.5.

Notare che ogni volta che cambia la selezione, si esegue una richiesta Ajax. Come si potrebbe modificare il codice per eseguire solo una richiesta e salvare leinformazioni per trarre vantaggio quando si torna a modificare la selezione?

01 $.ajax({02 url : 'http://query.yahooapis.com/v1/public/yql',03 04 // viene aggiunto come parametro il nome della funzione05 // di ritorno, come specificato nel servizio di YQL06 jsonp : 'callback',07 08 // si indica jQuery che è atteso informazioni09 // in formato JSONP10 dataType : 'jsonp',11 12 // si indica al servizio di YQL quale è l'informazione13 // che si desidera e che la si vuole in formato JSON14 data : {15 q : 'select title,abstract,url from search.news where query="cat"',16 format : 'json'17 },18 19 // si esegue una funzione se20 // la richiesta è andata a buon fine21 success : function(response) {22 console.log(response);23 }24 });

1 $('#loading_indicator')2 .ajaxStart(function() { $(this).show(); })3 .ajaxStop(function() { $(this).hide(); });

1 var href = 'blog.html#post1';2 var tempArray = href.split('#');3 var id = '#' + tempArray[1];

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

37 di 57 24/08/2012 19:45

Page 38: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Torna in cima

Estensioni

Cos'è un estensione?

Un'estensione di jQuery è semplicemente un nuovo metodo da utilizzare per estendere il prototipo (prototype) dell'oggetto jQuery. Quando si estende il prototipo, tuttigli oggetti jQuery ereditano i metodi aggiunti. Pertanto, quando viene effettuata una chiamata jQuery(), viene creato un nuovo oggetto jQuery con tutti i metodi

ereditati.

Lo scopo di un'estensione è di eseguire un'azione utilizzando un insieme di elementi, proprio come fanno, per esempio, i metodi fadeOut o addClass della libreria.

È possibile effettuare le proprie estensioni e usarle privatamente nel progetto o è anche possibile pubblicarli in modo che altri potranno usufruire.

Come creare di una estensione di base

Il codice per creare un'estensione di base è il seguente:

L'estensione del prototipo dell'oggetto jQuery si verifica nella seguente riga:

Il quale è racchiusa in una funzione auto-eseguibile

Questo ha il vantaggio di creare un'ambito "privato", che consente di utilizzare il simbolo del dollaro, senza timore che un'altra libreria utilizzi anche lo stesso segno.

Per ora, internamente l'estensione è:

In esso, la parola chiave this si riferisce all'oggetto jQuery in cui è chiamata l'estensione.

L'oggetto jQuery di solito contiene diversi riferimenti agli elementi DOM, ed è per questo che sono spesso definiti come una collezione.

Per interagire con l'insieme di elementi, è necessario fare un ciclo, che è facilmente ottenibile con il metodo each():

Come gli altri metodi, each() restituisce un oggetto jQuery, permettendo il concatenamento dei metodi utilizzati ($(...).css().attr()...). Per evitare di rompere

questa convenzione, l'estensione da creare dovrà ritornare l'oggetto this per consentire di continuare con la catena. Di seguito è riportato un piccolo esempio:

L'estensione modificherà tutti i link all'interno della collezione di oggetti e aggiungerà il valore attributo del suo attributo href tra parentesi.

1 (function($){2 $.fn.myNewPlugin = function() {3 return this.each(function(){4 // fare qualcosa5 });6 };7 }(jQuery));

1 $.fn.myNewPlugin = function() { //...

1 (function($){2 //...3 }(jQuery));

1 $.fn.myNewPlugin = function() {2 return this.each(function(){3 // fare qualcosa4 });5 };

1 var somejQueryObject = $('#something');2 3 $.fn.myNewPlugin = function() {4 alert(this === somejQueryObject);5 };6 7 somejQueryObject.myNewPlugin();8 // mostra un avviso con 'true'

1 $.fn.myNewPlugin = function() {2 return this.each(function(){3 4 });5 };

01 (function($){02 $.fn.showLinkLocation = function() {03 return this.filter('a').each(function(){04 $(this).append(05 ' (' + $(this).attr('href') + ')'06 );07 });08 };09 }(jQuery));10 11 // Esempio di utilizzo:12 $('a').showLinkLocation();

1 <!-- Prima che l'estensione sia chiamata: -->2 <a href="page.html">Foo</a>3

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

38 di 57 24/08/2012 19:45

Page 39: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

È anche possibile ottimizzare l'estensione:

Il metodo append permette specificare una funzione di ritorno (callback), e il valore di ritorno determinerà ciò che verrà aggiunto ad ogni elemento. Si noti anche che

non viene utilizzato il metodo attr, perché l'API nativa del DOM consente un facile accesso alla proprietà href.

Di seguito è riportato un altro eEsempio di estensione. In questo caso, non è tenuto a fare un ciclo su ogni elemento perché la funzionalità è delegata direttamente in unaltro metodo di jQuery:

Individuare e valutare estensioni

Uno degli aspetti più popolari di jQuery è la diversità di estensioni che esistono.

Tuttavia, la qualità può variare notevolmente tra le estensioni. Molti sono ampiamente testati e ben mantenute, ma alcuni sono state create in fretta e poi ignorate, senzaseguire le buone prassi.

Google è il miglior strumento per trovare le estensioni (anche se il team di jQuery sta lavorando per migliorare la sua repository di estensioni). Una volta trovatal'estensione, si consiglia di consultare la newsletter di jQuery o il canale IRC #jquery per ottenere il parere di altri circa l'estensione.

Assicurarsi che l'estensione sia ben documentata, e che offono esempi di utilizzo. Stare attenti anche con le estensioni che fanno più del necessario, queste possonoarrivare a sovraccaricare la pagina. Per ulteriori suggerimenti su come individuare un'estensione mediocre, è possibile leggere l'articolo (in inglese) I segni di un pluginper jQuery scritto male da Remy Sharp.

Dopo aver selezionato l'estensione, è necessario aggiungerla alla pagina. In primo luogo, scaricare l'estensione, scompattarla (se necessario) e spostarla nella cartelladell'applicazione. Infine inserirla utilizzando l'elemento script (dopo l'inclusione di jQuery).

Scrivere estensioni

A volte si vuole fare una funzionalità disponibile in tutto il codice, per esempio, un metodo che possa essere chiamato da una selezione il quale realizzi una serie dioperazioni.

La maggior parte delle estensioni sono metodi creati all'interno del namespace $.fn. jQuery assicura che un metodo chiamato sull'oggetto jQuery sia in grado di

accedere a detto oggetto attraverso this. In contrasto, l'estensione dovrebbe garantire per restituire lo stesso oggetto ricevuto (salvo diversa indicazione).

Di seguito si mostra un esempio:

Esempio 8.1: Creare una estensione per aggiungere e rimuovere una clesse in un elemento quando accade l'evento hover

Per ulteriori informazioni sullo sviluppo di estensioni, vedere l'articolo (in inglese) A Plugin Development Pattern di Mike Alsup. In questo articolo, si sviluppaun'estensione chiamata $.fn.hilight, che fornisce un supporto per l'estensione metadata (se presente) e fornisce un metodo decentrato per impostare opzioni globali

o istanze dell'estensione.

Esempio 8.2: Il modello di sviluppo di estensioni per jQuery spiegato da Mike Alsup

4 <!-- Dopo che l'estensione sia chiamata: -->5 <a href="page.html">Foo (page.html)</a>

1 (function($){2 $.fn.showLinkLocation = function() {3 return this.filter('a').append(function(){4 return ' (' + this.href + ')';5 });6 };7 }(jQuery));

01 (function($){02 $.fn.fadeInAndAddClass = function(duration, className) {03 return this.fadeIn(duration, function(){04 $(this).addClass(className);05 });06 };07 }(jQuery));08 09 // Esempio di utilizzo:10 $('a').fadeInAndAddClass(400, 'finishedFading');

01 // definizione dell'estensione02 (function($){03 $.fn.hoverClass = function(c) {04 return this.hover(05 function() { $(this).toggleClass(c); }06 );07 };08 })(jQuery);09 10 // utilizzare l'estensione11 $('li').hoverClass('hover');

01 //02 // creare una chiusura03 //04 (function($) {05 //06 // definizione dell'estensione07 //08 $.fn.hilight = function(options) {09 debug(this);10 // generazione delle opzioni principali11 // prima di interagire12 var opts = $.extend({}, $.fn.hilight.defaults, options);13 // ittera e riformatta ogni elemento14 return this.each(function() {15 $this = $(this);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

39 di 57 24/08/2012 19:45

Page 40: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Scrivere estensioni con mantenimento di stato utilizzando Widget Factory di jQuery UI

Nota

Questa sezione è basata, con il permesso dell'autore, dall'articolo Building Stateful jQuery Plugins di Scott Gonzalez.

Mentre la maggior parte delle estensioni per jQuery sono esenti da manutenzione dello stato (stateless in inglese) - vale a dire, estensioni che vengono eseguiti su un soloelemento, essendo l'unica interazione - c'è un grande numero di funzionalità che non si utilizzano nello schema di base dove si sviluppano estensioni.

Per colmare questa lacuna, jQuery UI (jQuery User Interface) ha implementato un sistema più avanzato di estensioni. Questo sistema permette di gestire gli stati eammette più funzioni da essere esposte in una singola estensione. Questo sistema è chiamato widget factory e fa parte della versione 1.8 di jQuery UI attraversojQuery.widget, ma può essere utilizzato anche senza dipendere da jQuery UI.

Per dimostrare le capacità di widget factory, si creerà un'estensione che avrà come funzionalità sarà barra di avanzamento.

Per ora, l'estensione permetterà solo d'impostare il valore della barra di avanzamento una volta. Questo sarà fatto chiamando jQuery.widget con due parametri: il

nome dell'estensione da creare e un oggetto letterale contenente le funzioni supportate. Quando l'estensione sarà chiamata, una sua istanza verrà creata e tutte lefunzioni si eseguiranno nel contesto di tale istanza.

Ci sono due differenze importanti rispetto a una estensione standard per jQuery: in primo luogo, il contesto è un oggetto, non un elemento DOM; in secondo luogo, ilcontesto è sempre un unico oggetto, mai una collezione.

Esempio 8.3: Una semplice estensione con mantenimento dello stato utilizzando widget factory di jQuery UI

Il nome dell'estensione deve contenere uno spazio di nomi, in questo caso viene utilizzato nmk. Gli spazi di nomi sono limitati ad un solo livello di profondità - il che

significa, per esempio, che non poò essere utilizzato nmk.foo. Come si può vedere nell'esempio, widget factory fornisce due proprietà da utilizzare. La prima,

this.element è un oggetto jQuery che contiene esattamente un elemento. Nel caso in cui l'estensione venga eseguita su più di una voce, un'istanza separata

dell'estensione verrà creata per ogni elemento e ciascuno avrà il suo propria this.element. La seconda proprietà, this.options, è un insieme di coppie

chiave/valore con tutte le opzioni dell'estensione. Queste opzioni possono essere passate all'estensione come segue:

Nota

Quando si creano le proprie estensioni si consiglia di utilizzare il proprio spazio di nomi, giacchhé mette in chiaro da dove proviene l'estensione e se fa parte diuna collezione più ampia. D'altra parte, lo spazio dei nomi ui è riservato per le estensioni ufficiali di jQuery UI.

16 // generazione delle opzioni specifiche17 // per ogni elemento18 var o = $.meta ? $.extend({}, opts, $this.data()) : opts;19 // aggiornamento degli stili per ogni elemento20 $this.css({21 backgroundColor: o.background,22 color: o.foreground23 });24 var markup = $this.html();25 // si chiama la funzione per la formattazione26 markup = $.fn.hilight.format(markup);27 $this.html(markup);28 });29 };30 //31 // funzione privata per la depurazione32 //33 function debug($obj) {34 if (window.console && window.console.log)35 window.console.log('hilight selection count: ' + $obj.size());36 };37 //38 // definire ed esporre la funzione di formattazione39 //40 $.fn.hilight.format = function(txt) {41 return '<strong>' + txt + '</strong>';42 };43 //44 // opzioni predefinite45 //46 $.fn.hilight.defaults = {47 foreground: 'red',48 background: 'yellow'49 };50 //51 // fine della chiusura52 //53 })(jQuery);

1 $.widget("nmk.progressbar", {2 _create: function() {3 var progress = this.options.value + "%";4 this.element5 .addClass("progressbar")6 .text(progress);7 }8 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

40 di 57 24/08/2012 19:45

Page 41: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 8.4: Passare opzioni al widget

Quando si chiama a jQuery.widget si estende jQuery aggiungendo il metodo a jQuery.fn (nello stesso modo come quando si crea una estensione standard). Il nome

della funzione che viene aggiunto è basato sul nome che si passa a jQuery.widget, senza lo spazio dei nomi (in questo caso il nome sarà jQuery.fn.progressbar).

Come si mostra sotto, è possibile specificare valori predefiniti per ogni opzione. Questi valori dovrebbero essere basati sull'uso più comune dell'estensione.

Esempio 8.5: Impostare le opzioni di default per un widget

Aggiungere metodi a un Widget

Ora è possibile inizializzare l'estensione, è necessario aggiungere le capacità di eseguire azioni attraverso metodi definiti nell'estensione. Per definire un metodonell'estensione è necessario includere la funzione di retrochiamata nell'oggetto letterale da passare a jQuery.widget. I metodi possono anche essere definiti "privati"

anteponendo un carattere di sottolineatura al nome della funzione.

Esempio 8.6: Creare metodi nel Widget

Per chiamare un metodo su un'istanza dell'estensione, è necessario passare il nome del metodo all'estensione. Se si chiama un metodo che accetta parametri questidevono essere passati subito dopo il nome del metodo.

Esempio 8.7: Chiamare i metodi in un'istanza dell'estensione

1 $("<div></div>")2 .appendTo( "body" )3 .progressbar({ value: 20 });

01 $.widget("nmk.progressbar", {02 // opzioni predefinite03 options: {04 value: 005 },06 07 _create: function() {08 var progress = this.options.value + "%";09 this.element10 .addClass( "progressbar" )11 .text( progress );12 }13 });

01 $.widget("nmk.progressbar", {02 options: {03 value: 004 },05 06 _create: function() {07 var progress = this.options.value + "%";08 this.element09 .addClass("progressbar")10 .text(progress);11 },12 13 // crea un metodo pubblico14 value: function(value) {15 // non si passa alcun valore,16 // agisce quindi come metodo ottenitore (getter)17 if (value === undefined) {18 return this.options.value;19 // passando un valore, agisce quindi20 // come metodo impostatore (setter)21 } else {22 this.options.value = this._constrain(value);23 var progress = this.options.value + "%";24 this.element.text(progress);25 }26 },27 28 // crea un metodo privato29 _constrain: function(value) {30 if (value > 100) {31 value = 100;32 }33 if (value < 0) {34 value = 0;35 }36 return value;37 }38 });

01 var bar = $("<div></div>")02 .appendTo("body")03 .progressbar({ value: 20 });04 05 // ottiene il valore corrente06 alert(bar.progressbar("value"));07 08 // aggiorna il valore09 bar.progressbar("value", 50);10 11 // ottiene di nuovo il valore12 alert(bar.progressbar("value"));

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

41 di 57 24/08/2012 19:45

Page 42: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Nota

Eseguire il metodo passando il nome del metodo allla stessa funzione jQuery che viene utilizzata per inizializzare l'estensione può sembrare strano, ma è fatto cosìper evitare "le contaminazioni" dello spazio di nomi di jQuery, mantenendo, allo stesso tempo, la possibilità di chiamare i metodi in catena o concatenati.

Lavorare con le opzioni del Widget

Uno dei metodi disponibili automaticamente per l'estensione è option. Questo metodo permette di ottenere e impostare opzioni dopo l'inizializzazione e funziona

esattamente come i metodi attr e css di jQuery: passando unicamente un nome come argomento il metodo funziona come un getter, invece passando uno o più insiemi dicoppie di nomi e valori il metodo funziona come setter. Se utilizzato come metodo getter, l'estensione restituirà il valore corrente dell'opzione corrispondente al nomepassato come argomento. D'altra parte, se usato come metodo setter, il metodo _setOption dell'estensione sarà chiamato da ogni opzione che si desidera impostare.

Esempio 8.8: Risponde quando l'opzione è impostata

Aggiungere funzioni di callback

Uno dei modi più semplici per estendere un'estensione è quello di aggiungere funzioni di callback, in modo che l'utente possa reagire quando lo stato dell'estensionecambia. Di seguito viene riportato come aggiungere una funzione di callback all'estensione creata per indicare quando la barra di progresso raggiunge il 100%. Il metodo_trigger riceve tre parametri: il nome della funzione di callback, l'oggetto evento nativo che inizializza la funzione di callback e una serie di informazioni relative

all'evento. Il nome della funzione di retrochiamata (callback in inglese) è l'unico parametro richiesto, ma altre possono essere molto utile se l'utente vuole implementarefunzionalità personalizzate.

Esempio 8.9: Fornire funzioni di (callback) retrochiamata

Le funzioni di callback sono essenzialmente solo opzioni aggiuntive e possono essere impostate come qualsiasi altra opzione. Ogni volta che una funzione di callbackviene eseguita, allo stesso tempo si attiva un evento corrispondente. Il tipo di evento si determina concatenando il nome dell'estensione e il nome della funzione dicallback. Questa funzione ed evento ricevono gli stessi parametri: un oggetto evento e una serie di informazioni relative all'evento.

Se l'estensione avrà qualche funzionalità che potrebbero essere annullate dall'utente, il modo migliore è quello di creare funzioni di callback annullabile. L'utente puòannullare una funzione di callback o il suo evento associato nello stesso modo che viene annullato qualunque evento nativo: chiamando a event.preventDefault() o

usando return false.

Esempio 8.10: Vincolare a eventi del widget

01 $.widget("nmk.progressbar", {02 options: {03 value: 004 },05 06 _create: function() {07 this.element.addClass("progressbar");08 this._update();09 },10 11 _setOption: function(key, value) {12 this.options[key] = value;13 this._update();14 },15 16 _update: function() {17 var progress = this.options.value + "%";18 this.element.text(progress);19 }20 });

01 $.widget("nmk.progressbar", {02 options: {03 value: 004 },05 06 _create: function() {07 this.element.addClass("progressbar");08 this._update();09 },10 11 _setOption: function(key, value) {12 this.options[key] = value;13 this._update();14 },15 16 _update: function() {17 var progress = this.options.value + "%";18 this.element.text(progress);19 if (this.options.value == 100) {20 this._trigger("complete", null, { value: 100 });21 }22 }23 });

01 var bar = $("<div></div>")02 .appendTo("body")03 .progressbar({04 complete: function(event, data) {05 alert( "Funzione di callback" );06 }07 })

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

42 di 57 24/08/2012 19:45

Page 43: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

In profondità: Widget Factory

Quando si chiama a jQuery.widget, questa crea una funzione costruttrice per l'estensione e imposta l'oggetto letterale che viene passato come il prototipo per tutte le

istanze dell'l'estensione. Tutte le caratteristiche che automaticamente si aggiungono all'estensione provvengono dal prototipo base del widget, il quale è definito comejQuery.Widget.prototype. Quando si crea un'istanza dell'estensione, questa viene salvata nell'elemento originale del DOM utilizzando jQuery.data, con il nome

dell'estensione come parola chiave.

Perché l'istanza dell'estensione è direttamente legata all'elemento DOM, è possibile accedere all'istanza dell'estensione direttamente. Questo permette di chiamare imetodi direttamente nell'istanza dell'estensione invece di passare il nome del metodo come una stringa, dando la possibilità di accedere alle proprietà dell'estensione.

Uno dei maggiori vantaggi di avere un costruttore e un prototipo per l'estensione è la facilità di estendere l'estensione. Il fatto di aggiungere o modificare metodi nelprototipo dell'estensione permette di modificarli anche in tutte le istanze dell'estensione. Per esempio, se vogliamo aggiungere un metodo all'estensione della barra diavanzamento per permettere di resettare il progresso a 0%, è possibile farlo aggiungendo questo metodo al prototipo e sarà automaticamente disponibile per esserechiamato da qualsiasi istanza dell'estensione.

Pulizia

In alcuni casi, ha senso consentire agli utenti di applicare e disapplicare l'estensione. Questo può essere fatto attraverso il metodo destroy. Con questo metodo, è

possibile annullare tutto quello che si è fatto con l'estensione. Questo metodo è anche chiamato automaticamente se l'elemento vincolato all'estensione viene rimossodal DOM (e così è anche possibile usarlo per la raccolta di spazzatura o in inglese "garbage collection"). Il metodo destroy predefinito rimuove il collegamento tra

l'elemento DOM e l'istanza dell'estensione.

Esempio 8.11: Aggiungere un metodo destroy al widget

Conclusione

L'utilizzo di Widget factory è solo un modo per creare estensioni con la manutenzione dello stato. Ci sono modelli diversi che possono essere usati e ognuno di loro ha isuoi vantaggi e svantaggi. Widget factory risolve molti problemi comuni, migliorando significativamente la produttività e il riutilizzo del codice.

Esercizi

Creare una tabella ordinabile

Per questo esercizio, il compito è quello di individuare, scaricare e implementare un'estensione che permetta di ordinare la tabella esistente nella pagina index.html.Quando è pronto, tutte le colonne della tabella dovrebbero essere in grado di essere ordinabili.

08 .bind("progressbarcomplete", function(event, data) {09 alert("Eventi bolla e molti gestori di supporto per una flessibilità estrema.");10 alert("Il valore della barra di avanzamento è " + data.value);11 });12 13 bar.progressbar("option", "value", 100);

01 var bar = $("<div></div>")02 .appendTo("body")03 .progressbar()04 .data("progressbar" );05 06 // chiamare un metodo direttamente07 // nell'istanza dell'estensione08 bar.option("value", 50);09 10 // accedere alle proprietà11 // nell'istanza dell'estensione12 alert(bar.options.value);

1 $.nmk.progressbar.prototype.reset = function() {2 this._setOption("value", 0);3 };

01 $.widget( "nmk.progressbar", {02 options: {03 value: 004 },05 06 _create: function() {07 this.element.addClass("progressbar");08 this._update();09 },10 11 _setOption: function(key, value) {12 this.options[key] = value;13 this._update();14 },15 16 _update: function() {17 var progress = this.options.value + "%";18 this.element.text(progress);19 if (this.options.value == 100 ) {20 this._trigger("complete", null, { value: 100 });21 }22 },23 24 destroy: function() {25 this.element26 .removeClass("progressbar")27 .text("");28 29 // chiama alla funzione base destroy30 $.Widget.prototype.destroy.call(this);31 }32 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

43 di 57 24/08/2012 19:45

Page 44: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Scrivere un'estensione per cambiare il colore di sfondo nelle tabelle

Aprire il file /exercises/index.html nel browser web. Eseguire l'esercizio utilizzando il file /exercises/js/stripe.js. Il compito è quello di scrivere

un'estensione chiamata "stripe", il quale potrà essere chiamata da qualsiasi elemento table e dovrà cambiare il colore di sfondo delle righe dispari nel corpo della tabella.Il colore potrà essere specificato come parametro dell'estensione.

Non dimenticare di restituire la tabella in modo che altri metodi possano essere concatenati dopo la chiamata all'estensione.

Torna in cima

Best practice per migliorare le prestazioni

Questo capitolo tratta molte migliori pratiche JavaScript e jQuery, senza un particolare ordine. Molte di queste pratiche si basano sulla presentazione jQueryAnti-Patterns for Performance (in inglese) di Paul irlandese.

Salva la lunghezza del loops

In un ciclo, è necessario accedere alla lunghezza di un array ogni volta che viene valutata la condizione; tale valore può essere memorizzato in anticipo in una variabile.

Aggiungere nuovi contenuti fuori da un ciclo

Se si sta inserendo molti elementi nel DOM, fatelo tutti in una volta, non uno per volta.

Non Ripetersi

Nessuna ricorrenza; fare le cose una volta e solo una, altrimenti è sbagliato.

1 $('#myTable').stripe('#cccccc');

1 var myLength = myArray.length;2 3 for (var i = 0; i < myLength; i++) {4 // fare delle cose5 }

01 // male02 $.each(myArray, function(i, item) {03 var newListItem = '<li>' + item + '</li>';04 $('#ballers').append(newListItem);05 });06 07 // meglio: fare questo08 var frag = document.createDocumentFragment();09 10 $.each(myArray, function(i, item) {11 var newListItem = '<li>' + item + '</li>';12 frag.appendChild(newListItem);13 });14 $('#ballers')[0].appendChild(frag);15 16 // o questo17 var myHtml = '';18 19 $.each(myArray, function(i, item) {20 html += '<li>' + item + '</li>';21 });22 $('#ballers').html(myHtml);

01 // MALE02 if ($eventfade.data('currently') != 'showing') {03 $eventfade.stop();04 }05 06 if ($eventhover.data('currently') != 'showing') {07 $eventhover.stop();08 }09 10 if ($spans.data('currently') != 'showing') {11 $spans.stop();12 }13 14 // BENE15 var $elems = [$eventfade, $eventhover, $spans];16 $.each($elems, function(i,elem) {17 if (elem.data('currently') != 'showing') {18 elem.stop();19 }20 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

44 di 57 24/08/2012 19:45

Page 45: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Attenzione alle funzioni anonime

Non è consigliabile utilizzare abbondantemente le funzioni anonime. Queste sono difficili da eseguire in debug, per la manutenzione, il test e suo riutilizzo. Al suo posto,utilizzare un valore letterale per organizzare e nominare i suoi controllori e le funzioni di retrochiamata (callback).

Ottimizzazione dei selettori

L'ottimizzazione dei selettori è meno importante di una volta, grazie all'implementazione in alcuni browser web document.querySelectorAll(), passando il peso di

jQuery verso browser web. Tuttavia, ci sono alcuni consigli da tenere a mente.

Selettori basati sugli ID

È sempre meglio iniziare le selezioni con un ID.

L'esempio che utilizza $.fn.find è più veloce perché la prima selezione utilizza il motore di selezione interno Sizzle -. Mentre la selezione realizzata unicamente per ID

utilizza document.getElementById(), che è estremamente veloce grazie alla è una funzione nativa del browser web.

Specificità

Cercate di essere specifico per il lato destro della selezione e meno specifici per il sinistro.

Utilizzare il più possibile tag.classe del lato destro della selezione, e solo tag o .classe a sinistra.

Evitare specificità eccessiva

La seconda selezione ha prestazioni migliori perché attraversa meno strati per individuare l'elemento.

Evitare il selettore universale

Selezioni dove si specifica implicita o esplicitamente una selezione universale che può essere molto lento.

Utilizzare la delegazione di Eventi

La delega di eventi permette vincolare un gestore eventi a un elemento contenitore (per esempio, una lista non ordinata) in luogo di molteplici elementi contenuti (peresempio, gli elementi in una lista). jQuery rende rende questo lavoro facile attraverso $.fn.live e $.fn.delegate. Se possibile, si raccomanda utilizzare

01 // MALE02 $(document).ready(function() {03 $('#magic').click(function(e) {04 $('#yayeffects').slideUp(function() {05 // ...06 });07 });08 09 $('#happiness').load(url + ' #unicorns', function() {10 // ...11 });12 });13 14 // MEGLIO15 var PI = {16 onReady : function() {17 $('#magic').click(PI.candyMtn);18 $('#happiness').load(PI.url + ' #unicorns', PI.unicornCb);19 },20 21 candyMtn : function(e) {22 $('#yayeffects').slideUp(PI.slideCb);23 },24 25 slideCb : function() { ... },26 27 unicornCb : function() { ... }28 };29 30 $(document).ready(PI.onReady);

1 // veloce2 $('#container div.robotarm');3 4 // super-veloce5 $('#container').find('div.robotarm');

1 // non ottimizzato2 $('div.data .gonzalez');3 4 // ottimizzato5 $('.data td.gonzalez');

1 $('.data table.attendees td.gonzalez');2 3 // molto meglio: eliminare il mezzo, se possibile,4 $('.data td.gonzalez');

1 $('.buttons > *'); // molto lento2 $('.buttons').children(); // molto meglio3 4 $('.gender :radio'); // selezione universale implicita5 $('.gender *:radio'); // stesa cosa, ma in modo esplicito6 $('.gender input:radio'); // molto meglio

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

45 di 57 24/08/2012 19:45

Page 46: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

$.fn.delegate anziché $.fn.live, giacché elimina la necessità di una selezione e il suo contesto esplicito riduce il carico di circa il 80%.

Inoltre, la delegazione di eventi permette di aggiungere nuovi elementi contenitori alla pagina, senza dover vincolare i loro gestori di eventi.

Separare elementi per lavorare con loro

Se possibile, evitare la manipolazione del DOM. Per contribuire a questo scopo, dalla versione 1.4 jQuery introduce $.fn.detach il quale permette lavorare con gli

elementi del DOM in forma separata per poi inserirli.

Utilizzare stili a cascata per modificare il Css tra vari elementi

Se si modifica il CSS in più di 20 elementi con $.fn.css, considerate le modifiche agli stili con l'aggiunta di un tag style. Ciò consentirà di aumentare le prestazioni del

60%.

Utilizzare $.data anziché $.fn.data

Utilizzare $.data in un elemento DOM invece di $.fn.data in una selezione può essere fino a 10 volte più veloce. Prima di farlo, assicuratevi di capire la differenza tra

un elemento DOM e una selezione jQuery.

Non agire su elementi inesistenti

jQuery non ci dirà se si cerca di eseguire un codice su una selezione vuota - questo verrà eseguito come se nulla fosse. Dipende da noi vedere se la selezione contieneelementi.

Questo consiglio è particolarmente adatto per i widget jQuery UI, i quali hanno un carico pesante, anche quando la selezione non contiene elementi.

Definizione di variabili

Le variabili possono essere definite in una unica dichiarazione, invece di più volte.

Nelle funzioni di autoeseguibili, le definizioni di variabili possono essere passate tutte insieme.

1 // sbagliato (se ci sono molti elementi nella lista)2 $('li.trigger').click(handlerFn);3 4 // meglio: delegazione di eventi con $ fn.live.5 $('li.trigger').live('click', handlerFn);6 7 // molto meglio:. delegazione di evento con $ fn.delegate8 // permette specificare un contesto in modo facile9 $('#myList').delegate('li.trigger', 'click', handlerFn);

1 var $table = $('#myTable');2 var $parent = $table.parent();3 4 $table.detach();5 // ... si aggiungono molte celle alla tabella6 $parent.append($table);

1 // corretto fino a 20 elementi, lento dopo i 20 elementi2 $('a.swedberg').css('color', '#asd123');3 $('<style type="text/css">a.swedberg { color : #asd123 }</style>')4 .appendTo('head');

1 // regolare2 $(elem).data(key,value);3 4 // 10 volte più veloce5 $.data(elem,key,value);

01 // SBAGLIATO: il codice esegue tre funzioni02 // senza verificare se ci sono03 // nella selezione04 $('#nosuchthing').slideUp();05 06 // MEGLIO07 var $mySelection = $('#nosuchthing');08 if ($mySelection.length) { $mySelection.slideUp(); }09 10 // MOLTO MEGLIO: aggiunge una estensione doOnce11 jQuery.fn.doOnce = function(func){12 this.length && func.apply(this);13 return this;14 }15 16 $('li.cartitems').doOnce(function(){17 // fare qualcosa18 });

1 // antico2 var test = 1;3 var test2 = function() { ... };4 var test3 = test2(test);5 6 // migliore modo7 var test = 1,8 test2 = function() { ... },9 test3 = test2(test);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

46 di 57 24/08/2012 19:45

Page 47: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Condizionali

Non trattare jQuery come se fosse una scatola nera

Utilizzare il codice sorgente della libreria come se fosse la sua documentazione - salva il link http://bit.ly/jqsource come marcatore per usarlo come riferimento.

Torna in cima

Organizzazione del codice

introduzione

Quando si intraprende il compito di realizzare applicazioni complesse sul lato client, è necessario considerare come organizzare il codice. Questo capitolo è dedicato adanalizzare alcuni modelli di organizzazione del codice da utilizzare in un'applicazione realizzata con jQuery ed esplorare il sistema di gestione di dipendenze di RequireJS.

Concetti chiave

Prima di iniziare con i modelli organizzativi di codice, è importante capire alcuni concetti chiave.

Il codice deve essere suddiviso in unità funzionali - moduli, servizi, ecc. E devono evitare la tentazione di avere tutto in un unico blocco$(document).ready(). Questo concetto è noto come incapsulamento.

Non ripetere il codice. Identificare pezzi simili e utilizzare tecniche di eredità.

Sebbene la natura di jQuery, non tutte le applicazioni JavaScript si trovano nel DOM e non tutte le parti di funzionalità hanno la necessità di avere unrappresentanzio nel DOM.

Le unità di funzionalità devono avere un giunto flessibile (in inglese loosely coupled) - una unità di funzionalità dovrebbe essere in grado di esistere da sé e lacomunicazione con altre unità dovrebbe avvenire attraverso un sistema di messaggi come eventi personalizzati o pub/sub. E per quanto possibile, tenerelontana la comunicazione diretta le unità funzionali.

Il concetto di giunto (o articolazione) flessibile può essere particolarmente problematico per gli sviluppatori che fanno la loro prima incursione in applicazionicomplesse, quindi se siete di partenza, cercate di essere consapevoli di questo concetto.

Incapsulamento

Il primo passo per l'organizzazione del codice è di separare l'applicazione in diversi pezzi; anche se a volte, questo sforzo è sufficiente.

L'Oggetto Letterale

Un oggetto letterale è forse il modo più semplice per incapsulare il codice correlato. Questo non fornisce alcuna privacità per proprietà o metodi, ma è utile pereliminare le funzioni anonime, centralizzare le opzioni di configurazione, e facilitare la via per il riutilizzo e il rifattorizzazione.

Esempio 10.1: Un oggetto letterale

1 (function(foo, bar) { ... })(1, 2);

1 // antico2 if (type == 'foo' || type == 'bar') { ... }3 4 // migliore5 if (/^(foo|bar)$/.test(type)) { ... }6 7 // ricerca in oggetto letterale8 if (({ foo : 1, bar : 1 })[type]) { ... }

01 var myFeature = {02 myProperty : 'ciao',03 04 myMethod : function() {05 console.log(myFeature.myProperty);06 },07 08 init : function(settings) {09 myFeature.settings = settings;10 },11 12 readSettings : function() {13 console.log(myFeature.settings);14 }15 };16 17 myFeature.myProperty; // 'ciao'18 myFeature.myMethod(); // registra 'ciao'19 myFeature.init({ foo : 'bar' });20 myFeature.readSettings(); // registra { foo : 'bar' }

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

47 di 57 24/08/2012 19:45

Page 48: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

L'oggetto ha una proprietà e vari metodi, i quali sono pubblici, in modo che ogni parte dell'applicazione li può vedere.

Come è possibile applicare questo schema nel codice jQuery? Per esempio, nel codice seguente scritto nello stile tradizionale di jQuery:

Se l'esempio illustrato rappresenta il 100% della richiesta, si consiglia di lasciare così com'è. Tuttavia, se il pezzo è solo una parte di una applicazione più grande, sarebbebene separare questa funzionalità dalle altre non correlate. Per esempio è conveniente spostare l'URL a cui viene fatta la richiesta al di fuori del codice e passarla all'areadi configurazione. Anche spezzare la catena di metodi per rendere dopo più facile la sua modifica o manutensione.

Esempio 10.2: Utilizzare un oggetto letterale per una funzionalità jQuery

La prima caratteristica da notare è che il codice è più lungo da quello originale - come affermato in precedenza, se questo è il campo dell'applicazione, utilizzare unoggetto letterale sarebbe probabilmente una esagerazione.

I vantaggi sono:

Separazione di ogni funzionalità in piccoli metodi. In futuro, se si desidera cambiare la modo di visualizzare il contenuto, ci sarà chiaro dove farlo. Nel codice

01 // Facendo clic su un item della lista02 // si carica un certo contenuto.03 // Utilizzando l'ID dell'item e a sua04 // volta nasconde gli altri item fratelli.05 $(document).ready(function() {06 $('#myFeature li')07 .append('<div/>')08 .click(function() {09 var $this = $(this);10 var $div = $this.find('div');11 $div.load('foo.php?item=' +12 $this.attr('id'),13 function() {14 $div.show();15 $this.siblings()16 .find('div').hide();17 }18 );19 });20 });

01 var myFeature = {02 init : function(settings) {03 myFeature.config = {04 $items : $('#myFeature li'),05 $container : $('<div class="container"></div>'),06 urlBase : '/foo.php?item='07 };08 09 // permete di sovrascrivere10 // la configurazione predefinita11 $.extend(myFeature.config, settings);12 13 myFeature.setup();14 },15 16 setup : function() {17 myFeature.config.$items18 .each(myFeature.createContainer)19 .click(myFeature.showItem);20 },21 22 createContainer : function() {23 var $i = $(this),24 $c = myFeature.config.$container.clone()25 .appendTo($i);26 27 $i.data('container', $c);28 },29 30 buildUrl : function() {31 return myFeature.config.urlBase +32 myFeature.$currentItem.attr('id');33 },34 35 showItem : function() {36 var myFeature.$currentItem = $(this);37 myFeature.getContent(myFeature.showContent);38 },39 40 getContent : function(callback) {41 var url = myFeature.buildUrl();42 myFeature.$currentItem43 .data('container').load(url, callback);44 },45 46 showContent : function() {47 myFeature.$currentItem48 .data('container').show();49 myFeature.hideContent();50 },51 52 hideContent : function() {53 myFeature.$currentItem.siblings()54 .each(function() {55 $(this).data('container').hide();56 });57 }58 };59 60 $(document).ready(myFeature.init);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

48 di 57 24/08/2012 19:45

Page 49: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

originale, questo passaggio è molto più difficile da individuare.

Si rimuovono gli usi di funzioni anonime.

Le opzioni di configurazione ssi sono spostate in una posizione centrale.

Si eliminano le limitazioni che hanno catene di metodi, rendendo il codice più facile da rifattorare, mescolare e riordinare.

Grazie alle sue caratteristiche, l'uso di oggetti letterali consente un netto miglioramento per lunghi tratti di codice inseriti in un blocco $(document).ready().

Tuttavia, no sono più avanzati che avere diverse dichiarazioni di funzioni all'interno di un blocco $(document).ready().

Il Modello Modulare

Il modello modulare supera alcune delle limitazioni dell'oggetto letterale, offrendo privacità a variabili e funzioni, esponendo a sua volta un API pubblica se lo sidesidera.

Esempio 10.3: Il modello modulare

Nell'esempio, si autoesegue un funzione anonima che restituisce un oggetto. All'interno della funzione, si definiscono alcune variabili. Visto che sono definite all'internodella funzione, dall'esterno non hanno accesso a meno che non si mettano dentro l'oggetto che viene restituito. Questo significa che nessun codice al di fuori dellafunzione ha accesso alla variabile privateThing o alla funzione sayPrivateThing. Tuttavia, sayPrivateThing ha accesso a privateThing e changePrivateThing

perche sono definiti nello stesso ambito.

Il modello è potente perché permette di avere variabili e funzioni private, esponendo una API limitata che consente la retituzione di proprietà e metodi di un oggetto.

Di seguito è riportato una revisione dell'esempio visto prima, con le stesse caratteristiche, ma esponendo un unico metodo pubblico del modulo, showItemByIndex().

Esempio 10.4: Utilizzare il modello modulare per una funzionalità jQuery

01 var feature =(function() {02 03 // variabili e funzioni private04 var privateThing = 'segreto',05 publicThing = 'non segreto',06 07 changePrivateThing = function() {08 privateThing = 'super segreto';09 },10 11 sayPrivateThing = function() {12 console.log(privateThing);13 changePrivateThing();14 };15 16 // API pubblica17 return {18 publicThing : publicThing,19 sayPrivateThing : sayPrivateThing20 }21 22 })();23 24 feature.publicThing; // registra 'non segreto'25 26 feature.sayPrivateThing();27 // registra 'segreto' e cambia il valore28 // di privateThing a 'super segreto'

01 $(document).ready(function() {02 var feature = (function() {03 04 var $items = $('#myFeature li'),05 $container = $('<div class="container"></div>'),06 $currentItem,07 08 urlBase = '/foo.php?item=',09 10 createContainer = function() {11 var $i = $(this),12 $c = $container.clone().appendTo($i);13 14 $i.data('container', $c);15 },16 17 buildUrl = function() {18 return urlBase + $currentItem.attr('id');19 },20 21 showItem = function() {22 var $currentItem = $(this);23 getContent(showContent);24 },25 26 showItemByIndex = function(idx) {27 $.proxy(showItem, $items.get(idx));28 },29 30 getContent = function(callback) {31 $currentItem.data('container').load(buildUrl(), callback);32 },33 34 showContent = function() {35 $currentItem.data('container').show();36 hideContent();37 },38

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

49 di 57 24/08/2012 19:45

Page 50: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Gestione delle dipendenze

Nota

Questa sezione si basa sulla eccellente documentazione di RequireJS http://requirejs.org/docs/jquery.html ed è utilizzato con il permesso di James Burke,autore di RequireJS.

Quando un progetto raggiunge una certa dimensione, cominicia a diventare difficile la gestione dei moduli in un'applicazione, giacché è necessario sapere ordinarli inmodo corretto, e cominciare a combinarli in un unico file per ottenere il minor numero di richieste. È anche possibile che si voglia caricare codice "al volo" dopo ilcaricamento della pagina.

RequireJS è uno strumento per la gestione delle dipendenze creato da James Burke, che aiuta a gestire i moduli, caricarli nel giusto ordine e combinarli con facilità,senza dover apportare alcuna modifica. A sua volta, fornisce un modo semplice per caricare il codice una volta caricata la pagina, permettendo di minimizzare il tempodi download.

RequireJS possiede un sistema modulare, ma non c'è bisogno di seguirlo per ottenere i sui benefici. Il formato modulare di RequireJS permette la scrittura del codiceincapsulato, incorporazione dell'internazionalizzazione (i18n) ai pacchetti (per consentirne l'uso in diverse lingue) e anche l'uso dei servizi JSONP come dipendenze.

Ottenere RequireJS

Il modo più semplice per usare il pacchetto RequireJS con jQuery è quello di scaricare el paquete de jQuery con RequireJS già incorporato. Questo pacchetto escludeporzioni di codice che duplicano funzioni di jQuery. È anche utile scaricare un esempio di progetto jQuery che utilizza RequireJS.

Utilizzare RequireJS con jQuery

Utilizzare RequireJS è semplice, basta inserire nella pagina la versione jQuery che ha costruito RequireJS includendo e quindi richiedere i files dell'applicazione. Diseguito, l'esempio presuppone che sia jQuery come gli altri files siano all'interno della cartella scripts/.

Esempio 10.5: Usare RequireJS: un semplice esempio

La chiamata a require(["app"]) comunica a RequireJS che carichi il file scripts/app.js. RequireJS caricherà qualsiasi dipendenza passata a require() senza

l'estensione .js dalla stessa cartella in cui si trova il file require-jquery.js, ma è anche possibile specificare il percorso così come segue:

Il file app.js è un'altra chiamata al file require.js per caricare tutti i file necessari per l'applicazione. Nel seguente esempio, app.js si richiedono due estensioni

jquery.alpha.js e jquery.beta.js (non sono estensioni reali, solo esempi). Queste estensioni sono nella stessa cartella del file require-jquery.js:

Esempio 10.6: Un semplice file JavaScript con dipendenze

Creare moduli riutilizzabili con RequireJS

RequireJS rende facile definire moduli riutilizzabili attraverso require.def(). Un modulo RequireJS può avere dipendenze che possono essere utilizzati per definire

un modulo così come per restituire un valore - un oggetto, una funzione o qualcos'altro - che può essere utilizzato anche su altri moduli.

Se il modulo non ha dipendenze, solo si deve specificare il il nome come primo argomento di require.def(). Il secondo argomento è un oggetto letterale che definisce

le proprietà del modulo. Per esempio:

39 hideContent = function() {40 $currentItem.siblings()41 .each(function() {42 $(this).data('container').hide();43 });44 };45 46 $items47 .each(createContainer)48 .click(showItem);49 50 return { showItemByIndex : showItemByIndex };51 })();52 53 feature.showItemByIndex(0);54 });

01 <!DOCTYPE html>02 <html>03 <head>04 <title>jQuery+RequireJS pagina di esempio</title>05 <script src="scripts/require-jquery.js"></script>06 <script>require(["app"]);</script>07 </head>08 <body>09 <h1>jQuery+RequireJS pagina di esempio</h1>10 </body>11 </html>

1 <script>require(["scripts/app.js"]);</script>

1 require(["jquery.alpha", "jquery.beta"], function() {2 // le estensioni jquery.alpha.js y jquery.beta.js3 // sono state caricate.4 $(function() {5 $('body').alpha().beta();6 });7 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

50 di 57 24/08/2012 19:45

Page 51: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Esempio 10.7: Definizione di un modulo RequireJS che non ha dipendenze

L'esempio deve essere salvato nel file my/simpleshirt.js.

Se il modulo ha dipendenze, si può specificare nel secondo argomento di require.def() attraverso un array e poi passare una funzione come terzo argomento. Questa

funzione sarà chiamata per definire il modulo una volta caricate tutte le dipendenze. Questa funzione riceve i valori restituiti dalle dipendenze come argomento (nellostesso ordine in cui sono dichiarate nell'array), allora la stessa deve restituire un oggetto che definisca il modulo.

Esempio 10.8: Definizione di un modulo RequireJS con dipendenze

In questo esempio, il modulo my/shirt viene creato. Questo dipende da my/cart e my/inventory. Sul disco, i files sono strutturati come segue:

La funzione che definisce my/shirt non viene chiamata fino a che my/cart e my/inventory siano stati caricati, e questa funzione riceve come argomenti i moduli cart

e inventory. L'ordine degli argomenti della funzione deve corrispondere all'ordine in cui le dipendenze si richiedono nell'array. L'oggetto restituito definisce il modulo

my/shirt. Definendo i moduli in questo modo, my/shirt non esiste come un oggetto globale, giacché più moduli possono esistere nella pagina allo stesso tempo.

I moduli non devono per forza restituire un oggetto, qualsiasi tipo di valore è permesso.

Esempio 10.9: Definizione di un modulo RequireJS che restituisce una funzione

Un solo modulo dovrebbe essere richiesto per il file JavaScript.

Ottimizzare il codice con gli strumenti di RequireJS

Una volta incorporato RequireJS per la gestione delle dipendenze, ottimizzazione del codice è semplice. Scarica il pacchetto RequireJS e salvarlo, preferibilmente al difuori dell'area di sviluppo web. Ai fini del presente esempio, il pacchetto RequireJS si trova in una cartella parallela alla cartella webapp (che contiene la pagina HTML e

tutti i file JavaScript dell'applicazione). La struttura della cartella è la seguente:

Poi, nella cartella degli script che ha require-jquery.js e app.js creare un file chiamato app.build.js o con il seguente contenuto:

File di configurazione per gli strumenti di ottimizzazione di RequireJS

1 require.def("my/simpleshirt",2 {3 color: "black",4 size: "unisize"5 }6 );

01 require.def("my/shirt",02 ["my/cart", "my/inventory"],03 function(cart, inventory) {04 // restituisce un oggetto che definisce05 // il modulo "my/shirt".06 return {07 color: "blue",08 size: "large"09 addToCart: function() {10 inventory.decrement(this);11 cart.add(this);12 }13 }14 }15 );

1 my/cart.js2 my/inventory.js3 my/shirt.js

01 require.def("my/title",02 ["my/dependency1", "my/dependency2"],03 function(dep1, dep2) {04 // restituisce una funzione per definire "my/title".05 // Questo restituisce o imposta06 // il titolo della finestra07 return function(title) {08 return title ? (window.title = title) : window.title;09 }10 }11 );

1 requirejs/ (utilizzayo per eseguire gli strumenti)2 webapp/app.html3 webapp/scripts/app.js4 webapp/scripts/require-jquery.js5 webapp/scripts/jquery.alpha.js6 webapp/scripts/jquery.beta.js

01 {02 appDir: "../",03 baseUrl: "scripts/",04 dir: "../../webapp-build",05 // Commentare la riga seguente se volete06 // minimizzare il codice dal compilatore07 // in modalità "semplice"08 optimize: "none",

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

51 di 57 24/08/2012 19:45

Page 52: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Per utilizzare lo strumento, è necessario installare Java 6. Closure Compiler viene utilizzato per minimizzare il codice (nel caso optimize: "none" non sia

commentato).

Per avviare l'elaborazione dei files, aprire una finestra di comando, andare alla cartella webapp/scripts ed eseguire:

Una volta eseguito, il file app.js nella cartella webapp-build conterrà tutto il codice di app.js più quello di jquery.alpha.js e jquery.beta.js. Se viene aperto il

file app.html (anche nella cartella webapp-build) si noterà che nessuna richiesta si realizza per caricare jquery.alpha.js e jquery.beta.js.

Esercizi

Creare un modulo Portlet

Aprire il file /exercises/portlets.html nel browser web. Eseguire l'esercizio utilizzando il file /exercises/js/portlets.js. L'esercizio è quello di creare una

funzione che crea portlet che utilizza il modello modulare, in modo che il codice che segue funzioni:

Ogni portlet deve essere un div con un titolo, uno spazio per il contenuto, un pulsante per aprire/chiudere il portlet, un pulsante per rimuoverlo e un altro per

aggiornarlo. Il portlet restituito dalla funzione deve avere la seguente API pubblicha:

Torna in cima

Eventi personalizzati

Introduzione agli Eventi personalizzati

Ormai yutti conoscono gli elementi di base - click, mouseover, focus, blur, submit, etc. - derivanti dall'interazione dell'utente con il browser web.

Gli eventi personalizzati consentono di farsi un'idea del mondo della programmazione orientata a oggetti (in inglese event-driven programming). In questo capitolouseremo il sistema di eventi personalizzati di jQuery per creare una semplice applicazione di ricerca Twitter.

In un primo momento può essere difficile da capire il requisito di utilizzare eventi personalizzati, visto che gli eventi convenzionali permettono di soddisfare tutte leesigenze. Tuttavia, gli eventi personalizzati offrono un modo nuovo di pensare la programmazione in JavaScript. Invece di concentrarsi sull'elemento che esegueun'azione, gli eventi personalizzati pongono l'attenzione sull'elemento in cui si verifica l'azione. Questo concetto offre diversi vantaggi:

Il comportamento dell'elemento obiettivo può essere eseguito da diversi elementi utilizzando lo stesso codice.

I comportamenti possono essere eseguiti in più o simili elementi obiettivi alla volta.

I comportamenti sono associati più chiaramente con l'elemento di obiettivo, rendendo il codice più facile da leggere e manutenere.

Un esempio è il modo migliore per spiegare la questione. Supponiamo di avere una lampada a incandescenza in una stanza di una casa. La lampada è attualmente accessa.La stessa è controllata da due interruttori a tre posizioni e un clapper (switch attivato per applausi):

Eseguendo il clapper o qualcuno degli interruttori, lo stato della lampada cambia. Agli interruttori o al clapper non si curano se la lampada è accesa o spenta, voglionosolo cambiare il loro stato.

Senza l'utilizzo di eventi personalizzati, è possibile scrivere la routine come segue:

09 10 modules: [11 {12 name: "app"13 }14 ]15 }

1 # per sistemi non-Windows2 ../../requirejs/build/build.sh app.build.js3 4 # per sistemi Windows5 ..\..\requirejs\build\build.bat app.build.js

1 var myPortlet = Portlet({2 title : 'Curry',3 source : 'data/html/curry.html',4 initialState : 'open' // or 'closed'5 });6 7 myPortlet.$element.appendTo('body');

1 myPortlet.open(); // forza per aprire2 myPortlet.close(); // forza per chiudere3 myPortlet.toggle(); // alterna gli stati4 // tra aperto e chiuso5 myPortlet.refresh(); // aggiorna il contenuto6 myPortlet.destroy(); // rimuove il porlet dalla pagina7 myPortlet.setSource('data/html/onions.html');8 // cambia il codice

1 <div class="room" id="kitchen">2 <div class="lightbulb on"></div>3 <div class="switch"></div>4 <div class="switch"></div>5 <div class="clapper"></div>6 </div>

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

52 di 57 24/08/2012 19:45

Page 53: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

D'altra parte, con gli eventi personalizzati, il codice appare così:

Qualcosa di importante è successo: il comportamento della lampada è stata cambiata, prima erano sugli interruttori e nel clapper, ora si trova nella stessa lampada.

E 'anche possibile fare un esempio po' più interessante. Supponiamo di aggiungere un'altra stanza nella casa, insieme ad uno switch generale, come illustrato di seguito:

Se c'è una lampada accesa in casa, è possibile spegnerla tramite l'interruttore generale, nello stesso modo quando ci sono luci spente, è possibile accenderle con questointerruttore. Per fare questo, si aggiungono due eventi personalizzati in più alla lampada: turnOn e turnOff. Attraverso una logica nell'evento changeState si decide

quale evento personalizzato usare:

Si noti come il comportamento dell'interruttore generale è stato collegato all'interruttore, mentre il comportamento delle lampade appartenengo alle lampade.

Nota

Se siete abituati alla programmazione orientata agli oggetti, è possibile pensare gli eventi personalizzati come metodi degli oggetti. In generale, l'oggetto cheappartiene al metodo si crea dal selettore jQuery. Vincolare l'evento personalizzato changeState a tutti gli elementi $('.light') è simile ad avere una classe

chiamata Light con un metodo changeState, e poi istanziare nuovi oggetti Light per ogni elemento.

Ricapitolando:. $.fn.bind e $.fn.trigger

Nel mondo di eventi personalizzati, ci sono due metodi importanti di jQuery:. $.fn.bind e $.fn.trigger. Ne capitolo dedicato agli eventi è stato spiegato l'uso di

questi due metodi per lavorare con gli eventi dell'utente, in questo capitolo è importante ricordare due punti:

Il metodo $.fn.bind prende come argomenti un tipo di evento e una funzione di gestione degli eventi. Opzionalmente, può ricevere informazioni associateall'evento come secondo argomento, spostando come terzo argomento la funzione gestore degli eventi. Qualunque informazione passata sarà disponibile allafunzione attraverso della proprietà data dell'oggetto dell'evento. A sua volta, la funzione del gestore degli eventi riceve l'oggetto dell'evento come primoargomento.Il metodo $.fn.trigger prende come argomenti il tipo di evento e facoltativamente può prendere un array di valori. Questi valori saranno passati alla

1 $('.switch, .clapper').click(function() {2 var $light = $(this).parent().find('.lightbulb');3 if ($light.hasClass('on')) {4 $light.removeClass('on').addClass('off');5 } else {6 $light.removeClass('off').addClass('on');7 }8 });

01 $('.lightbulb').bind('changeState', function(e) {02 var $light = $(this);03 if ($light.hasClass('on')) {04 $light.removeClass('on').addClass('off');05 } else {06 $light.removeClass('off').addClass('on');07 }08 });09 10 $('.switch, .clapper').click(function() {11 $(this).parent().find('.lightbulb').trigger('changeState');12 });

01 <div class="room" id="kitchen">02 <div class="lightbulb on"></div>03 <div class="switch"></div>04 <div class="switch"></div>05 <div class="clapper"></div>06 </div>07 <div class="room" id="bedroom">08 <div class="lightbulb on"></div>09 <div class="switch"></div>10 <div class="switch"></div>11 <div class="clapper"></div>12 </div>13 <div id="master_switch"></div>

01 $('.lightbulb')02 .bind('changeState', function(e) {03 var $light = $(this);04 if ($light.hasClass('on')) {05 $light.trigger('turnOff');06 } else {07 $light.trigger('turnOn');08 }09 })10 .bind('turnOn', function(e) {11 $(this).removeClass('off').addClass('on');12 })13 .bind('turnOff', function(e) {14 $(this).removeClass('off').addClass('on');15 });16 17 $('.switch, .clapper').click(function() {18 $(this).parent().find('.lightbulb').trigger('changeState');19 });20 21 $('#master_switch').click(function() {22 if ($('.lightbulb.on').length) {23 $('.lightbulb').trigger('turnOff');24 } else {25 $('.lightbulb').trigger('turnOn');26 }27 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

53 di 57 24/08/2012 19:45

Page 54: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

funzione del gestore degli eventi come argomentidopo dell'oggetto dell'evento.

Di seguito è riportato un esempio d'uso di $.fn.bind e $.fn.trigger in cui si utilizza le informazioni personali in entrambi i casi:

Un esempio di applicazione

Per dimostrare la potenza di eventi personalizzati, svilupperà un semplice strumento per la ricerca di Twitter. Questo strumento offrirà diversi modi per effettuare unaricerca dall'utente: inserirendo il termine da ricercare in una casella di testo o consultando i "temi caldi" di Twitter.

I risultati di ciascun termine verranno visualizzati in un contenitore di risultati; questi risultati si potranno espandere, comprimere, aggiornare e rimuovere,singolarmente o l'insieme.

l risultato finale dell'applicazione sarà la seguente:

Figure 11.1. L'applicazione terminata

Iniziazione

Inizia con un HTML di base:

1 $(document).bind('myCustomEvent', { foo : 'bar' }, function(e, arg1, arg2) {2 console.log(e.data.foo); // 'bar'3 console.log(arg1); // 'bim'4 console.log(arg2); // 'baz'5 });6 7 $(document).trigger('myCustomEvent', [ 'bim', 'baz' ]);

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

54 di 57 24/08/2012 19:45

Page 55: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

L'HTML ha un contenitore (#twitter) per il widget, un modello per i risultati (nascosto con i CSS) e un semplice modulo in cui l'utente può digitare il termine di ricerca.

Ci sono due tipi di elementi su cui agire: il contenitore di risultati e il contenitore Twitter.

I contenitori di risultati è cuore dell'applicazione. Si creerà un'estensione per preparare ogni contenitore una volta che questo viene aggiunto al contenitore Twitter.Inoltre, tra le altre cose, l'estensione vincolerà gli eventi personalizzati per ogni contenitore e aggiungerà, in alto a destra di ogni contenitore, pulsanti che eseguirannoazioni. Ogni contenitore di risultati dovrà avere i seguenti eventi personalizzati:

refresh

Segnala che l'informazione del contenitore si sta aggiornando e spara la petizione che cerca i dati correlato al termine di ricerca.

populate

Ricevere l'informazione in JSON e l'utilizza per riempire il contenitore.

remove

Rimuove il contenitore dalla pagina dopo che l'utente conferma l'azione. Tale conferma può essere omessa se si passa true come secondo parametro al gestore

degli eventi. L'evento rimuove anche il termine associato nel contenitore di risultati dell'oggetto globale che contiene i termini di ricerca.

collapse

Aggiunge una classe al contenitore, il quale nesconderà il risultato attraverso i CSS. Cambierà anche il testo del pulsante da "Colapse" a "Expand".

expand

Rimuovere la classe al contenitore che aggiunge l'evento collapse. Cambierà anche il testo del pulsante da "Expand" a "Colapse".

Inoltre, l'estensione è responsabile per l'aggiunta dei pulsanti di azione al contenitore, vincolando un evento click per ogni pulsante e utilizzando la classe di ogni item

per determinare quale evento personalizzato verrà eseguito su ogni contenitore di risultati.

01 <h1>Twitter Search</h1>02 <input type="button" id="get_trends"03 value="Load Trending Terms" />04 05 <form>06 <input type="text" class="input_text"07 id="search_term" />08 <input type="submit" class="input_submit"09 value="Add Search Term" />10 </form>11 12 <div id="twitter">13 <div class="template results">14 <h2>Search Results for15 <span class="search_term"></span></h2>16 </div>17 </div>

001 $.fn.twitterResult = function(settings) {002 return this.each(function() {003 var $results = $(this),004 $actions = $.fn.twitterResult.actions =005 $.fn.twitterResult.actions ||006 $.fn.twitterResult.createActions(),007 $a = $actions.clone().prependTo($results),008 term = settings.term;009 010 $results.find('span.search_term').text(term);011 012 $.each(013 ['refresh', 'populate', 'remove', 'collapse', 'expand'],014 function(i, ev) {015 $results.bind(016 ev,017 { term : term },018 $.fn.twitterResult.events[ev]019 );020 }021 );022 023 // utilizza la classe di ogni azione per024 // determinare quale evento si svolgerà025 // nel riquadro dei risultati026 $a.find('li').click(function() {027 // passa l'elemento <li> cliccato028 // sulla funzione in modo da poterlo029 // manipolare, se necessario030 $results.trigger($(this).attr('class'), [ $(this) ]);031 });032 });033 };034 035 $.fn.twitterResult.createActions = function() {036 return $('<ul class="actions" />').append(037 '<li class="refresh">Refresh</li>' +038 '<li class="remove">Remove</li>' +039 '<li class="collapse">Collapse</li>'040 );041 };042 043 $.fn.twitterResult.events = {044 refresh : function(e) {045 // indica che i risultati sono046 // in fase di aggiornamento047 var $this = $(this).addClass('refreshing');048 049 $this.find('p.tweet').remove();050 $results.append('<p class="loading">Loading ...</p>');

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

55 di 57 24/08/2012 19:45

Page 56: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Il contenitore Twitter, ha solo due eventi personalizzati:

getResults

Riceve un termine di ricerca e verifica se c'è un contenitore di risultati per il termine. Se non esiste, aggiunge un contenitore utilizzando il modello dei risultati,lo configura utilizzando l'estensione $.fn.twitterResult (vedi sopra) e quindi esegue l'evento refresh per caricare correttamente i risultati. Infine, salva il

termine di ricerca per evitare di dover richiedere i dati per il termine..

getTrends

Consulta a Twitter l'elenco delle prime 10 "parole calde", interagisce con loro ed esegue l'evento getResults su ciascuno, in modo che si aggiunga un

contenitore di risultati per ciascun termine.

Collegamenti nel contenitore Twitter:

051 052 // ottiene le informazioni da Twitter053 // in formato jsonp054 $.getJSON(055 'http://search.twitter.com/search.json?q=' +056 escape(e.data.term) + '&rpp=5&callback=?',057 function(json) {058 $this.trigger('populate', [ json ]);059 }060 );061 },062 063 populate : function(e, json) {064 var results = json.results;065 var $this = $(this);066 067 $this.find('p.loading').remove();068 069 $.each(results, function(i,result) {070 var tweet = '<p class="tweet">' +071 '<a href="http://twitter.com/' +072 result.from_user +073 '">' +074 result.from_user +075 '</a>: ' +076 result.text +077 ' <span class="date">' +078 result.created_at +079 '</span>' +080 '</p>';081 $this.append(tweet);082 });083 084 // indica che i risultati085 // sono già stati aggiornati086 $this.removeClass('refreshing');087 },088 089 remove : function(e, force) {090 if (091 !force &&092 !confirm('Rimuovere pannello per il termine ' + e.data.term + '?')093 ) {094 return;095 }096 $(this).remove();097 098 // indica che si non avrà099 // un pannello per il termine100 search_terms[e.data.term] = 0;101 },102 103 collapse : function(e) {104 $(this).find('li.collapse').removeClass('collapse')105 .addClass('expand').text('Expand');106 107 $(this).addClass('collapsed');108 },109 110 expand : function(e) {111 $(this).find('li.expand').removeClass('expand')112 .addClass('collapse').text('Collapse');113 114 $(this).removeClass('collapsed');115 }116 };

01 $('#twitter')02 .bind('getResults', function(e, term) {03 // si verifica che non ci sia 04 // un contenitore per il termine05 if (!search_terms[term]) {06 var $this = $(this);07 var $template = $this.find('div.template');08 09 // fa una copia del modello div e la inserisce10 // come il primo contenitore di risultati11 $results = $template.clone().12 removeClass('template').13 insertBefore($this.find('div:first')).14 twitterResult({15 'term' : term16 });17 18 // carica il contenuto utilizzando 19 // l'evento personalizzato "refresh"

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

56 di 57 24/08/2012 19:45

Page 57: Fondamentali di jQuery - dionegro.weebly.comdionegro.weebly.com/.../1/6/1/6/16160584/fondamentali_di_jquery_3.pdf · Esempio 10.9: Definizione di un modulo RequireJS che restituisce

Finora, si è scritto un sacco di codice che non fa nulla, che non è male. Si sono specificati tutti i comportamenti che si desiderano per gli elementi essenziali e si è creatouna base solida per creare rapidamente l'interfaccia.

Di seguito, si collega la casella di ricerca e pulsante per caricare i "temi caldi". Nella casella, il termine digitato viene catturato e passato, allo stesso tempo che si eseguegetResults. D'altra parte, cliccando sul pulsante per caricare i "temi caldi", si esegue l'evento getTrends:

Aggiugendo pulsanti con un ID apropriato, è possibile rimuovere, collassare, espandere e aggiornare tutti i contenitori di risultati, allo stesso tempo. Per il pulsante cherimuove il contenitore, notare che si sta passando true al gestore di eventi come il secondo argomento, indicando che non si vuole una conferma da parte dell'utente per

rimuovere il contenitore.

Conclusione

Gli eventi personalizzati rappresentano un modo nuovo di pensare il codice: essi sottolineano l'obiettivo di un comportamento e non nell'elemento che lo attiva. Se siprende il tempo dall'inizio per spiegare le parti della vostra applicazione, così come i comportamenti che queste parti hanno bisogno di esibire, gli eventi personalizzatiforniscono un potente strumento per "parlare" con quelle parti, sia uno alla volta o in massa.

Una volta che i comportamenti sono stati descritti, diventa banale da eseguire da qualunque luogo, consentendo la creazione rapida e la sperimentazione di opzioni diinterfaccia. Infine, eventi personalizzati sono in grado di migliorare la leggibilità del codice e la sua manutenzione, rendendo chiara la relazione tra un elemento e il suocomportamento.

È possibile visualizzare l'applicazione completa dei files demos/custom-events/custom-events.html e demos/custom-events/js/custom-events.js che

compongono questo libro.

20 // vincolato al contenitore dei risultati21 $results.trigger('refresh');22 search_terms[term] = 1;23 }24 })25 .bind('getTrends', function(e) {26 var $this = $(this);27 $.getJSON('http://search.twitter.com/trends.json?callback=?', function(json) {28 var trends = json.trends;29 $.each(trends, function(i, trend) {30 $this.trigger('getResults', [ trend.name ]);31 });32 });33 });

1 $('form').submit(function(e) {2 e.preventDefault();3 var term = $('#search_term').val();4 $('#twitter').trigger('getResults', [ term ]);5 });6 7 $('#get_trends').click(function() {8 $('#twitter').trigger('getTrends');9 });

1 $.each(['refresh', 'expand', 'collapse'], function(i, ev) {2 $('#' + ev).click(function(e) { $('#twitter div.results').trigger(ev); });3 });4 5 $('#remove').click(function(e) {6 if (confirm('Remove all results?')) {7 $('#twitter div.results').trigger('remove', [ true ]);8 }9 });

Fondamentali di jQuery http://rhadrix.net/guest/book/index.html

57 di 57 24/08/2012 19:45