Fondamentali di jQuery

Transcript

Fondamentali di jQuery
Fondamentali di jQuery
1 di 57
http://rhadrix.net/guest/book/index.html
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
24/08/2012 19:45
Fondamentali di jQuery
2 di 57
http://rhadrix.net/guest/book/index.html
Esempio 2.51: Utilizzando una chiusura per accedere simultaneamente ad istanze di oggetti interni ed esterni
Esempio 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 anonima
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
Esempio 3.9: Valutare se una selezione ha degli elementi
Esempio 3.10: Salvare le selezioni su una variabile
Esempio 3.11: Affinamento delle selezioni
Esempio 3.12: Utilizzando pseudo-selettori sugli elementi dei forms
Esempio 3.13: Concatenando
Esempio 3.14: Formattazione del codice incatenato
Esempio 3.15: Ripristinare la selezione originale utilizzando il metodo $.fn.end
Esempio 3.16: Il metodo $.fn.html utilizzato come impostatore
Esempio 3.17: Il metodo html utilizzato come ottenitore
Esempio 3.18: Ottenendo le proprietà CSS
Esempio 3.19: Impostando le proprietà CSS
Esempio 3.20: Lavorare con le classi
Esempio 3.21: Dimensioni - Metodi di base
Esempio 3.22: Impostare attributi
Esempio 3.23: Ottenere attributi
Esempio 3.24: Muoversi attraverso il DOM usando metodi di attraversamento
Esempio 3.25: Interagire in una selezione
Esempio 3.26: Modificare il codice HT ML di un elemento
Esempio 3.27: Spostare oggetti con differenti approcci
Esempio 3.28: Ottenere una copia del elemento
Esempio 3.29: Creare nuovi elementi
Esempio 3.30: Creare un nuovo elemento con attributi utilizzando un oggetto
Esempio 3.31: Creare un nuovo elemento nella pagina
Esempio 3.32: Creare e aggiungere allo stesso tempo un elemento alla pagina
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
Esempio 4.1: Verificare il tipo di un determinato valore
Esempio 4.2: Salvare e recuperare informazioni relative a un elemento
Esempio 4.3: Relazione tra gli elementi utilizzando il metodo $.fn.data
Esempio 4.4: Mettere jQuery in modo non-conflitto
Esempio 4.5: Utilizzare $ all'interno di una funzione anonima auto-eseguibile
Esempio 5.1: Collegamento di un evento utilizzando un metodo ridotto
Esempio 5.2: Collegamento di un evento utilizzando il metodo $.fn.bind
Esempio 5.3: Collegamento di un evento utilizzando il metodo $.fn.bind con informazione associata
Esempio 5.4: Cambiare controller usando il metodo $.fn.one method
Esempio 5.5: Scollegare tutti i controllori di evento click in una selezione
Esempio 5.6: Scollegare un controllore di evento particolare click
Esempio 5.7: Spazio di Nomi per gli Eventi
Esempio 5.8: Collegare più eventi a un elemento
Esempio 5.9: Annullare che facendo click su un link, questo si esegua
Esempio 5.10: Sparare un gestore di eventi nel modo giusto
Esempio 5.11: Delegare un evento con $.fn.delegate
Esempio 5.12: Delegare un evento con $.fn.live
Esempio 5.13: Scollegare Eventi Delegati
Esempio 5.14: La funzione ausiliaria hover
Esempio 5.15: La funzione ausiliaria toggle
Esempio 6.1: Utilizzo di base di un effetto incorporato
Esempio 6.2: Impostare la durata degli effetti
Esempio 6.3: Aumentare la velocità con jQuery.fx.speeds
Esempio 6.4: Eseguire del codice quando un'animazione è completata
Esempio 6.5: Eseguire una funzione di retrochiamata, anche se non c'è nessun elemento da animare
Esempio 6.6: Effetti personalizzati con $.fn.animate
Esempio 6.7: T ransizione easing per ogni proprietà
Esempio 7.1: Utilizzare il metodo $.ajax
Esempio 7.2: Utilizzare metodi appropriati nelle richieste Ajax
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.
Esempio 7.5: T rasformare le informazioni da una form in una stringa di dati
Esempio 7.6: Creare un array di oggetti che contengono informazioni da un form
Esempio 7.7: Usare YQL e JSONP
Esempio 7.8: Mostra/Nascondi un indicatore utilizzando Eventi di Ajax
Esempio 8.1: Creare una estensione per aggiungere e rimuovere una clesse in un elemento quando accade l'evento hover
Esempio 8.2: Il modello di sviluppo di estensioni per jQuery spiegato da Mike Alsup
Esempio 8.3: Una semplice estensione con mantenimento dello stato utilizzando widget factory di jQuery UI
Esempio 8.4: Passare opzioni al widget
Esempio 8.5: Impostare le opzioni di default per un widget
Esempio 8.6: Creare metodi nel Widget
Esempio 8.7: Chiamare i metodi in un'istanza dell'estensione
Esempio 8.8: Risponde quando l'opzione è impostata
Esempio 8.9: Fornire funzioni di (callback) retrochiamata
Esempio 8.10: Vincolare a eventi del widget
Esempio 8.11: Aggiungere un metodo destroy al widget
Esempio 10.1: Un oggetto letterale
Esempio 10.2: Utilizzare un oggetto letterale per una funzionalità jQuery
Esempio 10.3: Il modello modulare
Esempio 10.4: Utilizzare il modello modulare per una funzionalità jQuery
Esempio 10.5: Usare RequireJS: un semplice esempio
Esempio 10.6: Un semplice file JavaScript con dipendenze
Esempio 10.7: Definizione di un modulo RequireJS che non ha dipendenze
Esempio 10.8: Definizione di un modulo RequireJS con dipendenze
24/08/2012 19:45
Fondamentali di jQuery
3 di 57
http://rhadrix.net/guest/book/index.html
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 panoramica
della 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 apprendimento
ulteriore. 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 anche
essere banali, mentre altre non lo sono. L'obiettivo è quello di imparare a risolvere in maniera semplice, ciò che normalmente si risolverebbe con jQuery. Soluzioni per
tutti 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 il
codice 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 FT P/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 esterno
utilizzando 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ù file
JavaScript, devono essere combinati in un unico file.
Esempio 1.1: Esempio di codice JavaScript in linea
1
2
3
<script>
console.log('ciao');
</script>
Esempio 1.2: Esempio d'inclusione di un file esterno JavaScript
1
<script src='/js/jquery.js'></script>
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 un
sistema 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 punti
d'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 JavaScript
dopo 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
24/08/2012 19:45
Fondamentali di jQuery
4 di 57
http://rhadrix.net/guest/book/index.html
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 sta
ottenendo 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 cosa
dovrà 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 processo
di 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
1
// Il codice di esempio apparirà in questo modo
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 siti
potrebbe 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 su
jQuery, 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 (in
formato non compresso) una documentazione completa attraverso i commenti. La biblioteca non è una scatola nera - la sua comprensione aumenterà in modo
esponenziale 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.
24/08/2012 19:45
Fondamentali di jQuery
5 di 57
http://rhadrix.net/guest/book/index.html
Sintassi di base
Comprendere dichiarazioni, nomi di variabile, spaziatura, e altre sintassi di base JavaScript
Esempio 2.1: Dichiarazione semplice di una variab ile
1
var foo = 'ciao mondo';
Esempio 2.2: Gli spazi non hanno alcun valore al di fuori delle virgolette
1
var foo =
'ciao mondo';
Esempio 2.3: Le parentesi indicano la priorità
1
2
2 * 3 + 5;
2 * (3 + 5);
// ritorna 11; il prodotto si esegue prima
// ritorna 16; per le parentesi, la somma si esegue prima
Esempio 2.4: La tab ulazione migliora la lettura del codice, ma non ha un significato speciale
1
2
3
var foo = function() {
console.log('ciao');
};
Operatori
Operatori di base
Gli operatori di base permettono la manipolazione di valori.
Esempio 2.5: Concatenazione
1
2
3
4
var foo = 'ciao';
var bar = 'mondo';
console.log(foo + ' ' + bar); // 'ciao mondo'
Esempio 2.6: Moltiplicazione e divisione
1
2
2 * 3;
2 / 3;
Esempio 2.7: Incremento e decremento
1
2
3
4
var i = 1;
var j = ++i;
var k = i++;
// incremento anticipato: j è uguale a 2; i è uguale a 2
// incremento posticipato: k è uguale a 2; i è uguale a 3
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
1
2
3
4
var foo = 1;
var bar = '2';
console.log(foo + bar);
// errore: la console di debug mostra 12
Esempio 2.9: Forzare una stringa ad agire come un numero
1
2
3
4
5
6
var foo = 1;
var bar = '2';
// il costruttore 'Number' obbliga alla
// stringa di comportarsi come un numero
console.log(foo + Number(bar)); // la console di debug mostra 3
Il costruttore Number, quando viene chiamato come una funzione (come nell'esempio) obbliga al suo argomento a comportarsi come un numero. È inoltre possibile
utilizzare l'operatore somma unaria, che ritorna lo stesso risultato:
Esempio 2.10: Forzare una stringa per agire come un numero (somma unaria)
1
console.log(foo + +bar);
Operatori Logici
Gli operatori logici permettono valutare una serie di operandi utilizzando operazioni AND e OR.
Esempio 2.11: Operatori Logici AND e OR
24/08/2012 19:45
Fondamentali di jQuery
6 di 57
01
02
03
04
05
06
07
08
09
10
http://rhadrix.net/guest/book/index.html
var foo = 1;
var bar = 0;
var baz = 2;
foo || bar;
bar || foo;
// ritorna 1, il quale è vero (true)
// ritorna 1, il quale è vero (true)
foo && bar;
foo && baz;
baz && foo;
// ritorna 0, il quale è falso (false)
// ritorna 2, il quale è vero (true)
// ritorna 1, il quale è vero (true)
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:
1
2
3
4
5
6
7
// fare qualcosa con foo se foo è vero
foo && doSomething(foo);
// stabilire bar uguale a baz se baz è vero;
// caso contrario, stabilire bar uguale al
// valore di createBar()
var bar = baz || createBar();
Questo stile dichiarazione è molto elegante e concisa, ma può essere difficile da leggere (specialmente per i principianti). È per questo si esplicita, per
riconoscerlo 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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
var
var
var
var
foo
bar
baz
bim
=
=
=
=
1;
0;
'1';
2;
foo == bar;
foo != bar;
foo == baz;
// ritorna false
// ritorna true
// ritorna true; fare attenzione!
foo === baz;
foo !== baz;
foo === parseInt(baz);
foo > bim;
bim > baz;
foo <= baz;
// ritorna false
// ritorna true
// ritorna true
// ritorna false
// ritorna true
// ritorna true
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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
var foo = true;
var bar = false;
if (bar) {
// questo codice non verrà mai eseguito
console.log('ciao!');
}
if (bar) {
// questo codice non si eseguirà
} else {
if (foo) {
// questo codice si eseguirà
} else {
// si eseguirà se foo e bar sono falsi (false)
}
}
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.
24/08/2012 19:45
Fondamentali di jQuery
7 di 57
http://rhadrix.net/guest/book/index.html
È 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 finiscono
per essere un'altra.
Esempio 2.14: Valori che ritornano il vero true
1
2
3
4
5
'0';
'qualunque stringa';
[]; // un array vuoto
{}; // un oggetto vuoto
1;
// qualsiasi numero diverso da zero
Esempio 2.15: Valori che ritornano il falso false
1
2
3
4
5
0;
''; // una stringa vuota
NaN; // la variabile JavaScript "not-a-number" (non è un numero)
null; // un valore nullo
undefined; // // fare attenzione -- (undefined) può essere ridefinito
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, altrimenti
restituisce un valore diverso]
Esempio 2.16: L'operatore ternario
1
2
3
// imposta foo uguale a 1 se bar è vero;
// caso contrario, imposta foo uguale a 0
var foo = bar ? 1 : 0;
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 una
variabile o espressione ed esegue diferenti blocchi di codice a seconda di quel valore.]
Esempio 2.17: Una dichiarazione Switch
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
switch (foo) {
case 'bar':
alert('il valore è bar');
break;
case 'baz':
alert('il valore è baz');
break;
default:
alert('impostazione predefinita, questo codice verrà eseguito');
break;
}
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:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
var stuffToDo = {
'bar' : function() {
alert('il valore è bar');
},
'baz' : function() {
alert('il valore è baz');
},
'default' : function() {
alert('impostazione predefinita, questo codice verrà eseguito');
}
};
if (stuffToDo[foo]) {
stuffToDo[foo]();
} else {
stuffToDo['default']();
}
Più avanti si tratterà il concetto di oggetti.
24/08/2012 19:45
Fondamentali di jQuery
8 di 57
http://rhadrix.net/guest/book/index.html
Cicli
I cicli (loops in inglese) permettono eseguire un blocco di codice un certo numero di volte.
Esempio 2.18: Cicli
1
2
3
4
// mostra nella console 'tentativo 0', 'tentativo 1', ..., 'tentativo 4'
for (var i=0; i<5; i++) {
console.log('tentativo ' + i);
}
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:
1
2
for ([espressioneIniziale]; [condizione]; [incrementoDellaEspressione])
[corpoCiclo]
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 un
valore 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 stato
comporta 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
1
2
3
4
5
6
for (var i = 0, limit = 100; i < limit; i++) {
// Questo blocco di codice viene eseguito 100 volte
console.log('Attualmente a ' + i);
// Nota: L'ultimo record da visualizzare
// nella console sarà "Attualmente a 99"
}
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.
1
while ([condizione]) [corpoCiclo]
Un típico bucle utilizzando while:
Esempio 2.20: Un típico b ucle utilizzando while
1
2
3
4
5
6
7
8
9
var i = 0;
while (i < 100) {
// Questo blocco di codice verrà eseguito 100 volte
console.log('Attualmente a ' + i);
i++; // incrementa la variabile i
}
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, come
illustrato di seguito:
Esempio 2.21: Ciclo utilizzando while con la comb inazione della condizione e l'incremento
1
2
3
4
5
var i = -1;
while (++i < 100) {
// Questo blocco di codice verrà eseguito 100 volte
console.log('Attualmente a ' + i);
}
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.
1
do [corpoCiclo] while ([condizione])
Esempio 2.22: Un ciclo do-while
1
2
do {
24/08/2012 19:45
Fondamentali di jQuery
9 di 57
3
4
5
6
7
8
http://rhadrix.net/guest/book/index.html
// Anche quando la condizione è falsa
// il corpo del ciclo viene eseguito almeno una volta.
alert('Ciao!');
} while (false);
T ali 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 ciclo
utilizzando l'istruzione break all'interno del corpo.
Esempio 2.23: Fermare un ciclo con b reak
1
2
3
4
5
for (var i = 0; i < 10; i++) {
if (qualcosa) {
break;
}
}
Può anche accadere che si desidera continuare il ciclo senza dover eseguire più dichiarazioni del corpo del ciclo. Questo può essere fatto utilizzando l'istruzione
continue.
Esempio 2.24: Saltare alla seguente iterazione di un ciclo
01
02
03
04
05
06
07
08
09
10
11
for (var i = 0; i < 10; i++) {
if (qualcosa) {
continue;
}
// La seguente dichiarazione sarà eseguita
// se la condizione 'something' non si compie
console.log('I have been reached');
}
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 bisogno
per 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
24/08/2012 19:45
Fondamentali di jQuery
10 di 57
http://rhadrix.net/guest/book/index.html
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 per
memorizzare 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
1
var myArray = [ 'ciao', 'mondo' ];
Esempio 2.26: Accedere agli elementi dell'array attraverso il suo indice
1
2
var myArray = [ 'ciao', 'mondo', 'foo', 'bar' ];
console.log(myArray[3]);
// mostra 'bar' nella console
Esempio 2.27: Ottenere il numero di elementi dell'array
1
2
var myArray = [ 'ciao', 'mondo' ];
console.log(myArray.length);
// mostra '2' nella console
Esempio 2.28: Modificare il valore di un elemento di un array
1
2
var myArray = [ 'ciao', 'mondo' ];
myArray[1] = 'modificato';
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
1
2
var myArray = [ 'ciao', 'mondo' ];
myArray.push('nuovo');
Esempio 2.30: Lavorando con gli array
1
2
3
var myArray = [ 'c', 'i', 'a', 'o' ];
var myString = myArray.join('');
// 'ciao'
var mySplit = myString.split(''); // [ 'c', 'i', 'a', 'o' ]
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 o
numero 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"
01
02
03
04
05
06
07
08
09
10
11
12
var myObject = {
sayHello : function() {
console.log('ciao');
},
myName : 'Rebecca'
};
myObject.sayHello();
console.log(myObject.myName);
//
//
//
//
si chiama il metodo sayHello, che
visualizza sulla console 'Ciao'
si chiama la proprietà myName, che
mostra 'Rebecca' nella console
Nota
Si noti che quando si creano oggetti letterali, il nome della proprietà può essere qualsiasi identificatore JavaScript, una stringa (racchiusa tra virgolette) o un
numero:
24/08/2012 19:45
Fondamentali di jQuery
11 di 57
1
2
3
4
5
http://rhadrix.net/guest/book/index.html
var myObject = {
validIdentifier: 123,
'qualche stringa': 456,
99999: 789
};
Gli oggetti letterali possono essere molto utile per l'organizzazione del codice, per maggiori informazioni potete leggere l'articolo (in inglese) Using Objects to
Organize Y our 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ò restituire
un valore.
Le funzioni possono essere creati in diversi modi:
Esempio 2.32: Dichiarazione di una funzione
1
function foo() { /* fa qualcosa */ }
Esempio 2.33: Dichiarare una funzione denominata
1
var foo = function() { /* fa qualcosa */ }
È preferibile il metodo della funzione denominata a causa di alcuni motivi tecnici profondo. Probabilmente troverete i due metodi quando si revisiona il codice
JavaScript.
Utilizzo delle Funzioni
Esempio 2.34: Una semplice funzione
1
2
3
4
5
6
7
var greet = function(person, greeting) {
var text = greeting + ', ' + person;
console.log(text);
};
greet('Rebecca', 'Ciao');
Esempio 2.35: Una funzione che restituisce un valore
1
2
3
4
5
6
var greet = function(person, greeting) {
var text = greeting + ', ' + person;
return text;
};
console.log(greet('Rebecca','ciao'));
Esempio 2.36: Una funzione che restituisce un'altra funzione
1
2
3
4
5
6
7
8
var greet = function(person, greeting) {
var text = greeting + ', ' + person;
return function() { console.log(text); };
};
var greeting = greet('Rebecca', 'Ciao');
greeting();
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
1
2
3
4
5
6
(function(){
var foo = 'Ciao mondo';
})();
console.log(foo);
// indefinito (undefined)
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, passare
funzioni come argomenti è una pratica molto comune.
Esempio 2.38: Passare una funzione anonima come argomento
1
2
3
var myFn = function(fn) {
var result = fn();
console.log(result);
24/08/2012 19:45
Fondamentali di jQuery
12 di 57
4
5
6
7
http://rhadrix.net/guest/book/index.html
};
// mostra nella console 'Ciao mondo'
myFn(function() { return 'Ciao mondo'; });
Esempio 2.39: Passare una chiamata di funzione come argomento
01
02
03
04
05
06
07
08
09
10
11
var myFn = function(fn) {
var result = fn();
console.log(result);
};
var myOtherFn = function() {
return 'Ciao mondo';
};
// mostra nella console 'Ciao mondo'
myFn(myOtherFn);
Determinazione del tipo di variabile
JavaScript offre un modo per verificare il "tipo" (in inglese type) di una variabile. T uttavia, 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 variab ili
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var myFunction = function() {
console.log('ciao');
};
var myObject = {
foo : 'bar'
};
var myArray = [ 'a', 'b', 'c' ];
var myString = 'ciao;
var myNumber = 3;
typeof
typeof
typeof
typeof
typeof
myFunction;
myObject;
myArray;
myString;
myNumber;
typeof null;
//
//
//
//
//
ritorna
ritorna
ritorna
ritorna
ritorna
'function'
'object'
'object' -- fare attenzione
'string';
'number'
// ritorna 'object' -- fare attenzione
if (myArray.push && myArray.slice && myArray.join) {
// probabilmente è un array
// (questo stile è chiamato, in inglese, "duck typing")
}
if (Object.prototype.toString.call(myArray) === '[object Array]') {
// definitivamente è un array;
// questa è considerata la forma più robusta
// per determinare se un valore è un array.
}
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:
1. 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);
2. 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;
3. Se la funzione è invocata come metodo di un oggetto, this farà riferimento a detto oggetto;
4. Altrimenti, se la funzione viene invocata come una funzione indipendente, non legata ad alcun oggetto, this farà riferimento all'oggetto globale.
Esempio 2.41: Una funzione invocata utilizzando Function.call
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
var myObject = {
sayHello : function() {
console.log('Ciao! il mio nome è ' + this.myName);
},
myName : 'Rebecca'
};
var secondObject = {
myName : 'Colin'
};
myObject.sayHello();
// registra 'Ciao, il mio nome è Rebecca'
myObject.sayHello.call(secondObject);
// registra 'Ciao, il mio nome è Colin'
24/08/2012 19:45
Fondamentali di jQuery
13 di 57
http://rhadrix.net/guest/book/index.html
Esempio 2.42: Una función creada utilizando Function.b ind
01
02
03
04
05
06
07
08
09
10
11
12
13
14
var myName = 'the global object',
sayHello = function () {
console.log('Ciao, il mio nome è ' + this.myName);
},
myObject = {
myName : 'Rebecca'
};
var myObjectHello = sayHello.bind(myObject);
sayHello();
myObjectHello();
// registra 'Ciao, il mio nome è oggetto globale'
// registra 'Ciao, il mio nome è Rebecca'
Esempio 2.43: Una funzione vincolata ad un oggetto
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
var myName = 'oggetto globale',
sayHello = function() {
console.log('Ciao, il mio nome è ' + this.myName);
},
myObject = {
myName : 'Rebecca'
},
secondObject = {
myName : 'Colin'
};
myObject.sayHello = sayHello;
secondObject.sayHello = sayHello;
sayHello();
myObject.sayHello();
secondObject.sayHello();
// registra 'Ciao, il mio nome è oggetto globale'
// registra 'Ciao, il mio nome è Rebecca'
// registra 'Ciao, il mio nome è Colin'
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 riferimento
alla funzione corrente in una variabile più breve ed accessibile. T uttavia, è importante non farlo nelle istanze dei metodi, giacché possono portare all'esecuzione
del codice errato. Per Esempio:
01
02
03
04
05
06
07
08
09
10
11
12
13
var myNamespace = {
myObject : {
sayHello : function() {
console.log('Ciao, il mio nome è ' + this.myName);
},
myName : 'Rebecca'
}
};
var hello = myNamespace.myObject.sayHello;
hello();
// registra 'Ciao, il mio nome è undefined'
Per evitare che questi errori si verifichino, è necessario fare riferimento all'oggetto dove il metodo e invocato:
01
02
03
04
05
06
07
08
09
10
11
12
13
var myNamespace = {
myObject : {
sayHello : function() {
console.log('Ciao!, il mio nome è ' + this.myName);
},
myName : 'Rebecca'
}
};
var obj = myNamespace.myObject;
obj.sayHello();
// registra 'Ciao!, il mio nome è Rebecca'
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 variab ili definite all'interno dello stesso amb ito
1
var foo = 'Ciao';
24/08/2012 19:45
Fondamentali di jQuery
14 di 57
2
3
4
5
6
7
8
http://rhadrix.net/guest/book/index.html
var sayHello = function() {
console.log(foo);
};
sayHello();
console.log(foo);
// mostra nella console 'Ciao'
// mostra anche nella console 'Ciao'
Esempio 2.45: Il codice esterno non può accedere alla variab ile definita all'interno della funzione
1
2
3
4
5
6
7
var sayHello = function() {
var foo = 'Ciao';
console.log(foo);
};
sayHello();
console.log(foo);
// mostra nella console 'Ciao'
// non mostra niente nella console
Esempio 2.46: Variab ili con nomi identici ma diversi valori possono esistere in diversi amb iti
1
2
3
4
5
6
7
8
9
var foo = 'mondo';
var sayHello = function() {
var foo = 'ciao';
console.log(foo);
};
sayHello();
console.log(foo);
// mostra nella console 'ciao'
// mostra nella console 'mondo'
Esempio 2.47: Le funzioni possono "vedere" le modifiche nelle variab ili prima che la funzione sia definita
01
02
03
04
05
06
07
08
09
10
11
12
13
14
var myFunction = function() {
var foo = 'Ciao';
var myFn = function() {
console.log(foo);
};
foo = 'mondo';
return myFn;
};
var f = myFunction();
f(); // registra 'mondo' -- errore
Esempio 2.48: Amb ito folle
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
// a self-executing anonymous function
(function() {
var baz = 1;
var bim = function() { alert(baz); };
bar = function() { alert(baz); };
})();
console.log(baz); // La console non mostra nulla,
// visto che baz è definita nell'ambito
// della funzione anonima
bar();
//
//
//
//
//
//
//
bar è definita al di fuori della funzione
anonima dopo essere stata dichiarata senza la
parola chiave var; inoltre, come è stata
definita all'interno della stessa portata di
baz, è possibile interrogare il valore del baz,
anche se questa sia definita all'interno
della portata della funzione anonima
bim();
// bim non è definito per essere accessibile
// al di fuori della funzione anonima,
// quindi viene visualizzato un errore
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'ambito
in 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 dei
cicli - la funzione "osserva" il cambiamento nella variabile, anche dopo che la funzione sia stata definita, risultando che ad ogni click appaia una finestra di avviso
mostrando il valore 5.
Esempio 2.49: Come impostare il valore di i?
1
2
3
4
5
6
7
/* questo non si comporta come desiderato */
/* ogni click visualizzerà una finestra di avviso con il valore 5 */
for (var i=0; i<5; i++) {
$('<p>click me</p>').appendTo('body').click(function() {
alert(i);
});
}
Esempio 2.50: Impostare il valore di i utilizzando una chiusura
24/08/2012 19:45
Fondamentali di jQuery
15 di 57
1
2
3
4
5
6
7
8
http://rhadrix.net/guest/book/index.html
/* soluzione: "clausurare" il valor di i all'interno di createFunction */
var createFunction = function(i) {
return function() { alert(i); };
};
for (var i=0; i<5; i++) {
$('<p>click me</p>').appendTo('body').click(createFunction(i));
}
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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var outerObj = {
myName : 'esterno',
outerFunction : function () {
// fornisce un riferimento allo stesso oggetto outerObj
// da utilizzare all'interno di innerFunction
var self = this;
var innerObj = {
myName : 'interno',
innerFunction : function () {
console.log(self.myName, this.myName);
// registra 'esterno interno'
}
};
innerObj.innerFunction();
console.log(this.myName);
// registra 'esterno'
}
};
outerObj.outerFunction();
Questo meccanismo può essere utile quando si lavora con funzioni di richiamo o retro-chiamate (callbacks in inglese). T uttavia, in questi casi è preferibile usare
Function.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 questo
stato 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()
1
2
3
$(document).ready(function() {
console.log('il ocumento è pronto!');
});
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 ab b reviata per $(document).ready()
1
2
3
$(function() {
console.log('il ocumento è pronto!');
});
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
1
2
3
4
5
6
function readyFn() {
// codice da eseguire quando il documento è pronto
}
$(document).ready(readyFn);
Selezione di elementi
24/08/2012 19:45
Fondamentali di jQuery
16 di 57
http://rhadrix.net/guest/book/index.html
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 non
standardizzati. 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 b ase al loro ID
1
$('#myId'); // si noti che l'ID deve essere univoco per ogni pagina
Esempio 3.5: Selezione di elementi in b ase al nome della classe
1
2
$('div.myClass'); // se si specifica il tipo di elemento,
// si migliora le prestazioni della selezione
Esempio 3.6: Selezione di elementi per il suo attrib uto
1
$('input[name=first_name]'); // attenzione, che può essere molto lento
Esempio 3.7: Selezione di elementi in forma di selettore CSS
1
$('#contents ul.people li');
Esempio 3.8: Pseudo-selettori
1
2
3
4
5
6
$('a.external:first');
$('tr:odd');
$('#myForm :input');
$('div:visible');
$('div:gt(2)');
$('div:animated');
//
//
//
//
//
//
il primo elemento <a> con la classe 'external'
gli elementi <tr> dispari di una tabella
gli elementi del tipo input
gli elementi <div> visibili
gli elementi <div> tranne i primi tre
gli elementi <div> attualmente animati
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. T uttavia, 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 stati
inseriti per rendere più chiara la sua comprensione:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
jQuery.expr.filters.hidden = function( elem ) {
var width = elem.offsetWidth, height = elem.offsetHeight,
skip = elem.nodeName.toLowerCase() === "tr";
// Scelta di Selettori ha 0 di altezza,
// 0 di larghezza e non è <tr>?
return width === 0 && height === 0 && !skip ?
// allora deve essere nascosto (hidden)
true :
// ma se ha larghezza e l'altezza e non è un <tr>
width > 0 && height > 0 && !skip ?
// allora deve essere visibile
false :
// se siamo qui è perché l'elemento ha larghezza
// e altezza, ma è anche un <tr>, quindi verifica
// il valore dello stile display applicato attraverso
// i CSS per decidere se è nascosto o meno
jQuery.curCSS(elem, "display") === "none";
};
jQuery.expr.filters.visible = function( elem ) {
return !jQuery.expr.filters.hidden( elem );
};
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 delle
espressioni regolari.
1
2
// trovare tutti gli <a> cui attributi finiscono in "thinger"
$("a[rel$='thinger']");
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.
24/08/2012 19:45
Fondamentali di jQuery
17 di 57
http://rhadrix.net/guest/book/index.html
Per saperne di più su questo argomento, Paul Irish ha fatto una grande presentazione sui miglioramenti delle prestazioni Javascript (in inglese), diverse diapositive
centrate 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:
1
if ($('div.foo')) { ... }
T uttavia 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
1
if ($('div.foo').length) { ... }
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à di
nuovo, è necessario salvare la selezione in una variabile.
Esempio 3.10: Salvare le selezioni su una variab ile
1
var $divs = $('div');
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 sorta
di 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 selezione
originale.
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à necessario
ripetere 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 ottenere
esattamente quello che si desidera.
Esempio 3.11: Affinamento delle selezioni
1
2
3
4
5
6
$('div.foo').has('p');
//
$('h1').not('.bar');
//
$('ul li').filter('.current');//
//
//
$('ul li').first();
$('ul li').eq(5);
//
l'elemento div.foo contiene elementi <p>
l'elemento h1 non possiede la clase 'bar'
un item di una lista non ordinata che
possiede la classe 'current'
il primo item de una lista non ordinata
el sesto item de una lista non ordinata
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 o
tipo, 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
24/08/2012 19:45
Fondamentali di jQuery
18 di 57
http://rhadrix.net/guest/book/index.html
: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
1
$('#myForm :input'); // ottiene tutti gli elementi input nel form #myForm
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 gli
elementi 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
1
$('#content').find('h3').eq(2).html('testo per il terzo elemento h3!');
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
1
2
3
4
$('#content')
.find('h3')
.eq(2)
.html('testo per il terzo elemento h3!');
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
2
3
4
5
6
7
$('#content')
.find('h3')
.eq(2)
.html('testo per il terzo elemento h3!')
.end() // ripristina tutti gli elementi h3 in #content
.eq(0)
.html('testo per il primo elemento h3!');
24/08/2012 19:45
Fondamentali di jQuery
19 di 57
http://rhadrix.net/guest/book/index.html
Nota
La concatenazione è molto potente ed è una caratteristica che molte librerria JavaScript hanno adottato da che jQuery è diventato popolare. T uttavia, dovrebbe
essere usato con cautela. Una concatenazione di metodi estensivi può rendere il codice molto difficile da modificare e depurare. Non c'è una regola che indichi
quanto 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 viene
utilizzato per impostare un valore, il metodo viene chiamato impostatori (setter inglese). Tuttavia, quando un metodo viene utilizzato per ottenere (o leggere) un valore
si chiama ottenitori (getter in inglese).
Esempio 3.16: Il metodo $.fn.html utilizzato come impostatore
1
$('h1').html('ciao mondo');
Esempio 3.17: Il metodo html utilizzato come ottenitore
1
$('h1').html();
I metodi impostatori restituiscono un oggetto jQuery, che consente di continuare la chiamata sui più metodi nella stessa selezione, mentre i metodi ottenitori restituisce
il 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 la
proprietà è 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
1
2
$('h1').css('fontSize'); // restituisce una stringa come "19px"
$('h1').css('font-size'); // funziona lo stesso
Esempio 3.19: Impostando le proprietà CSS
1
2
3
4
// imposta una proprietà singola CSS
$('h1').css('fontSize', '100px');
// imposta molteplici proprietà CSS
$('h1').css({ 'fontSize' : '100px', 'color' : 'red' });
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 argomenti
a 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 classi
che 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
1
2
3
4
5
6
7
var $h1 = $('h1');
$h1.addClass('big');
$h1.removeClass('big');
$h1.toggleClass('big');
if ($h1.hasClass('big')) { ... }
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 possono
essere trovati http://api.jquery.com/category/dimensions/.
Esempio 3.21: Dimensioni - Metodi di b ase
24/08/2012 19:45
Fondamentali di jQuery
20 di 57
1
2
3
4
5
6
7
8
9
http://rhadrix.net/guest/book/index.html
$('h1').width('50px'); // imposta la larghezza di tutti gli elementi H1
$('h1').width();
// ottiene la larghezza del primo elemento H1
$('h1').height('50px');// imposta l'altezza di tutti gli elementi H1
$('h1').height();
// Ottiene l'altezza del primo elemento H1
$('h1').position();
// Restituisce un oggetto che contiene informazioni
// circa la posizione del primo elemento relativo a
// "offset" (posizione) dal suo elemento genitore
Attributi
Gli attributi degli elementi HT ML che costituiscono un'applicazione può contenere informazioni utili, quindi è importante potere impostare e ottenere queste
informazioni.
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 attrib uti
1
2
3
4
5
$('a').attr('href', 'allMyHrefsAreTheSameNow.html');
$('a').attr({
'title' : 'con i titoli è la stessa cosa!',
'href' : 'somethingNew.html'
});
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 usarli
per rendere il codice più leggibile. In ambienti di produzione, è possibile utilizzare strumenti di minimizzazione, che elimina gli spazi in bianco (tra le altre cose) e
comprimere il file di output.
Esempio 3.23: Ottenere attrib uti
1
2
$('a').attr('href');
// restituisce il primo valore dell'attributo href
// appartenente al elemento <a> del documento
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 ha
jQuery.
Nota
Si deve fare attenzione nel percorrere lunghe distanze in un documento — percorsi complessi richiedono che la struttura del documento sia sempre la stessa, cosa
che è 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
01
02
03
04
05
06
07
08
09
10
$('h1').next('p');
// seleziona l'elemento successivo <p>
// immediatamente dopo <h1>
// seleziona il contenitore padre
// di un elemento <div> visibile
$('input[name=first_name]').closest('form'); // seleziona dal più
// vicino <form> un input
// seleziona tutti gli elementi figlio
$('#myList').children();
// di #myList
$('li.selected').siblings(); // seleziona tutti gli elementi fratelli
// del elemento <li>
$('div:visible').parent();
È 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
1
2
3
4
5
6
7
$('#myList li').each(function(idx, el) {
console.log(
'L\'elemento ' + idx +
'ha il seguente html: ' +
$(el).html()
);
});
Manipolazione di Elementi
Una volta realizzata la selezione degli elementi che si desidera utilizzare, "inizia il divertimento". È possibile modificare, spostare, rimuovere e duplicare. Anche crearne
di nuovi attraverso una sintassi semplice.
La documentazione completa sui metodi di manipolazione può essere trovata in http://api.jquery.com/category/manipulation/.
24/08/2012 19:45
Fondamentali di jQuery
21 di 57
http://rhadrix.net/guest/book/index.html
Ottenre e Impostare Informazioni negli Elementi
Ci sono molti modi in cui è possibile modificare un elemento. T ra le operazioni più comuni ci sono quelle per cambiare l'HT ML all'interno o qualche suo attributo. Per
questi compiti, jQuery fornisce metodi semplici e funzionali in tutti i browser moderni. E' anche possibile ottenere informazioni sugli elementi utilizzando gli stessi
metodi, 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 un
singolo 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 HT ML, 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 è solo
ottenitore (getter).
$.fn.val
Ottiene o imposta il valore (value) negli elementi dei forms.
Esempio 3.26: Modificare il codice HTML di un elemento
1
2
$('#myDiv p:first')
.html('Nuovo <strong>primo</strong> parragrafo!');
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
1
2
3
4
5
6
7
8
9
// fare il che primo elemento della lista sia l'ultimo
var $li = $('#myList li:first').appendTo('#myList');
// un altro approccio allo stesso problema
$('#myList').append($('#myList li:first'));
// Va notato che non c'è modo di accedere
// alla lista degli items che è stata spostata,
// giacché restituisce la lista stessa
Clonare Elementi
24/08/2012 19:45
Fondamentali di jQuery
22 di 57
http://rhadrix.net/guest/book/index.html
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
1
2
3
// copiare il primo elemento della lista
// e spostarlo alla fine dello stesso
$('#myList li:first').clone().appendTo('#myList');
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 HT ML 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
1
2
$('<p>Questo è un nuovo paragrafo</p>');
$('<li class="nuovo">nuovo item della lista</li>');
Esempio 3.30: Creare un nuovo elemento con attrib uti utilizzando un oggetto
1
2
3
4
5
$('<a/>', {
html : 'Questo è un <strong>nuovo</strong> link',
'class' : 'nuovo',
href : 'foo.html'
});
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
1
2
3
4
5
6
7
var $myNewElement = $('<p>Nuovo elemento</p>');
$myNewElement.appendTo('#content');
$myNewElement.insertAfter('ul:last');
// eleminerà l'elemento <p> esistente in #content!
$('ul').last().after($myNewElement.clone());
// clonare l'elemento <p> per avere due versioni
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
$().
T uttavia, 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
1
$('ul').append('<li>item della lista</li>');
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
24/08/2012 19:45
Fondamentali di jQuery
23 di 57
http://rhadrix.net/guest/book/index.html
mentre si aggiunge degli elementi al DOM ripetutamente. Se si sta aggiungendo molti elementi allo stesso contenitore, piuttosto che aggiungere ogni elemento uno
per volta, il migliore sistema è quella di concatenare tutto l'HTML in una singola catena di stringhe e poi allegarla al contenitore. Una possibile soluzione è quella
di utilizzare un array che contenga tutti gli elementi e poi unirli usando join per finalmente allegarla.
1
2
3
4
5
6
7
var myItems = [], $myList = $('#myList');
for (var i=0; i<100; i++) {
myItems.push('<li>item ' + i + '</li>');
}
$myList.append(myItems.join(''));
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 attrib uto
1
$('#myDiv a:first').attr('href', 'newDestination.html');
Esempio 3.34: Manipolazione di più attrib uti
1
2
3
4
$('#myDiv a:first').attr({
href : 'newDestination.html',
rel : 'super-special'
});
Esempio 3.35: Utilizzare una funzione per determinare il valore del nuovo attrib uto
01
02
03
04
05
06
07
08
09
10
$('#myDiv a:first').attr({
rel : 'super-special',
href : function(idx, href) {
return '/new/' + href;
}
});
$('#myDiv a:first').attr('href', function(idx, href) {
return '/new/' + href;
});
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:
1. Selezionare tutti gli elementi div che hanno classe "module".
2. Specificare tre selezioni che possono selezionare il terzo item della lista non ordinata #myList. Qual è il migliore da usare e perché?
3. Selezionare l'elemento label dell'elemento input mediante un selettore di attributo.
4. Verificare quanti elementi della pagina sono nascosti (suggerimento:. .length)
5. Verificare quante immagini sulla pagina hanno l'attributo alt.
6. Selezionare tutte le righe dispari del corpo della tabella.
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:
1. Selezionare tutte le immagini sulla pagina, registrare nella console l'attributo alt di ogni immagine.
2. Selezionare l'elemento di input, poi andare al form e aggiungere una classe ad esso.
3. 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.
4. Selezionare l'elemento select all'interno di #special; per poi dirigersi verso il pulsante submit.
5. Selezionare il primo item della lista nell'elenemto #slideshow; aggiungere la classe "current" ad esso e poi aggiungere la classe "disabled" agli elementi fratelli.
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:
1. Aggiungere 5 nuovi elementi alla fine della lista non ordinata # myList. Suggerimento:
1
for (var i = 0; i<5; i++) { ... }
2. Rimuovere gli elementi dispari dalla lista.
3. Aggiungere un altro elemento h2 e un altro paragrafo all'ultimo div.module.
24/08/2012 19:45
Fondamentali di jQuery
24 di 57
http://rhadrix.net/guest/book/index.html
4. Aggiungere un'altra opzione all'elemento select, danno all'opzione aggiunta il valore "Wednesday".
5. Aggiungere un nuovo div.module alla pagina dopo l'ultima pagina; e quindi aggiungere una copia di una delle immagini esistenti nel nuovo div.
Torna in cima
Il nucleo di jQuery
$ vs $()
Finora, è stato trattato pienamente con i metodi che vengono chiamati dall'oggetto jQuery. Per Esempio:
1
$('h1').remove();
T ali 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.
T uttavia, 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 ritorno
può 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.
1
2
$.trim('
stringa con più spazi vuoti
');
// restituisce 'stringa con più spazi vuoti'
$.each
Interagisce negli array e negli oggetti.
1
2
3
4
5
6
7
$.each([ 'foo', 'bar', 'baz' ], function(idx, val) {
console.log('elemento ' + idx + 'es ' + val);
});
$.each({ foo : 'bar', baz : 'bim' }, function(k, v) {
console.log(k + ' : ' + v);
});
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.
1
2
3
4
5
var myArray = [ 1, 2, 3, 5 ];
if ($.inArray(4, myArray) !== -1) {
console.log('valore trovato!');
}
$.extend
Cambia le proprietà del primo oggetto utilizzando le proprietà degli oggetti successivi.
1
2
3
4
5
6
var firstObject = { foo : 'bar', a : 'b' };
var secondObject = { foo : 'baz' };
var newObject = $.extend(firstObject, secondObject);
console.log(firstObject.foo); // 'baz'
console.log(newObject.foo);
// 'baz'
Se non si desidera modificare le proprietà di nessun oggetto che vengono utilizzati in $.extend, si deve includere un oggetto vuoto come primo argomento.
24/08/2012 19:45
Fondamentali di jQuery
25 di 57
1
2
3
4
5
6
http://rhadrix.net/guest/book/index.html
var firstObject = { foo : 'bar', a : 'b' };
var secondObject = { foo : 'baz' };
var newObject = $.extend({}, firstObject, secondObject);
console.log(firstObject.foo); // 'bar'
console.log(newObject.foo);
// 'baz'
$.proxy
Restituisce una funzione che si eseguirà sempre nel campo di applicazione (scope) fornito - in altre parole, stabilisce il significato di this (incluso all'interno
della funzione) come secondo argomento.
1
2
3
4
5
6
7
var myFunction = function() { console.log(this); };
var myObject = { foo : 'bar' };
myFunction(); // restituisce l'oggetto window
var myProxyFunction = $.proxy(myFunction, myObject);
myProxyFunction(); // restituisce l'oggetto myObject
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 tale
oggetto.
01
02
03
04
05
06
07
08
09
10
var myObject = {
myFn : function() {
console.log(this);
}
};
$('#foo').click(myObject.myFn);
// registra el elemento DOM #foo
$('#foo').click($.proxy(myObject, 'myFn'));
// registra myObject
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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
var myValue = [1, 2, 3];
// Utilizzare l'operatore typeof di JavaScript
// per controllare tipi primitivi
typeof myValue == 'string';
// false (falso)
typeof myValue == 'number';
// false (falso)
typeof myValue == 'undefined'; // false (falso)
typeof myValue == 'boolean';
// false (falso)
// Utilizzare l'operatore di uguaglianza rigorosa
// per controllare i valori nulli
myValue === null; // false (falso)
// Utilizzare metodi di jQuery
// i tipi non primitivi
jQuery.isFunction(myValue);
jQuery.isPlainObject(myValue);
jQuery.isArray(myValue);
per testare
// false (falso)
// false (falso)
// true (vero)
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'elemento
DOM, ma questa pratica implica avere a che fare con perdite di memoria (memory leaks in inglese) in alcuni browser. jQuery fornisce un modo semplice per
memorizzare 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
1
2
$('#myDiv').data('keyName', { foo : 'bar' });
$('#myDiv').data('keyName'); // { foo : 'bar' }
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, ma
una 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
01
02
03
04
05
06
07
08
09
10
$('#myList li').each(function() {
var $li = $(this), $div = $li.find('div.content');
$li.data('contentDiv', $div);
});
// poi, non si deve tornare a cercare al div;
// è possibile leggerlo dall'informazione
// associata all'item della lista
var $firstLi = $('#myList li:first');
$firstLi.data('contentDiv').html('nuovo contenuto');
E' anche possibile passare al metodo u$.fn.data n oggetto contenente una o più coppie di parole chiave-valore.
24/08/2012 19:45
Fondamentali di jQuery
26 di 57
http://rhadrix.net/guest/book/index.html
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 browser
specifico.
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 il
codice 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
1
2
3
4
5
6
// la libreria prototype utilizza anche $
<script src="prototype.js"></script>
// si carica jquery nella pagina
<script src="jquery.js"></script>
// se inizializza $j in modo "non-conflitto"
<script>var $j = jQuery.noConflict();</script>
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-eseguib ile
1
2
3
4
5
6
7
8
9
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script>
jQuery.noConflict();
(function($) {
// codice va qui, e può utilizzare $
})(jQuery);
</script>
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 suo
comportamento 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
2
3
$('p').click(function() {
console.log('click');
});
24/08/2012 19:45
Fondamentali di jQuery
27 di 57
http://rhadrix.net/guest/book/index.html
Esempio 5.2: Collegamento di un evento utilizzando il metodo $.fn.b ind
1
2
3
$('p').bind('click', function() {
console.log('click');
});
Esempio 5.3: Collegamento di un evento utilizzando il metodo $.fn.b ind con informazione associata
01
02
03
04
05
06
07
08
09
10
11
12
$('input').bind(
'click change',
//
//
{ foo : 'bar' }, //
//
è possibile collegare più eventi
all'elemento
deve essere passato come argomento
le informazioni associatea
function(eventObject) {
console.log(eventObject.type, eventObject.data);
// registra il tipo di evento e l'informazione
// associata { foo : 'bar' }
}
);
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 fare
eseguire uno diverso. A tal fine, jQuery fornisce il metodo $.fn.one.
Esempio 5.4: Camb iare controller usando il metodo $.fn.one method
1
2
3
4
$('p').one('click', function() {
console.log('fatto click la prima volta!');
$(this).click(function() { console.log('fatto click di nuovo!'); });
});
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
1
$('p').unbind('click');
Esempio 5.6: Scollegare un controllore di evento particolare click
1
2
3
4
5
var foo = function() { console.log('foo'); };
var bar = function() { console.log('bar'); };
$('p').bind('click', foo).bind('click', bar);
$('p').unbind('click', bar); // foo è lagato all'evento 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 si
scolleghino eventi quando no lo si desidera.
Esempio 5.7: Spazio di Nomi per gli Eventi
1
2
3
4
5
$('p').bind('click.myNamespace', function() { /* ... */ });
$('p').unbind('click.myNamespace');
$('p').unbind('.myNamespace');
// scollega tutti gli eventi con
// lo spazio dei nomi myNamespace
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
2
3
4
5
6
7
8
$('p').bind({
'click': function() {
console.log('fatto click!');
},
'mouseover': function() {
console.log('il mouse è sopra!');
}
});
24/08/2012 19:45
Fondamentali di jQuery
28 di 57
http://rhadrix.net/guest/book/index.html
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 viene
comunemente utilizzato per prevenire l'azione predefinita del evento attraverso il metodo preventDefault. T uttavia, 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:
1
var $this = $(this);
Esempio 5.9: Annullare che facendo click su un link, questo si esegua
1
2
3
4
5
6
7
$('a').click(function(e) {
var $this = $(this);
if ($this.attr('href').match('evil')) {
e.preventDefault();
$this.addClass('evil');
}
});
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 dovrebbe
salvare 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
01
02
03
04
05
06
07
08
09
10
11
12
var foo = function(e) {
if (e) {
console.log(e);
} else {
console.log('questa azione non proviene da un evento!');
}
};
$('p').click(foo);
foo(); // invece di eseguire $('p').trigger('click')
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, è possibile
associare 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 a
centinaia 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.
24/08/2012 19:45
Fondamentali di jQuery
29 di 57
http://rhadrix.net/guest/book/index.html
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
1
2
3
4
$('#myUnorderedList').delegate('li', 'click', function(e) {
var $myListItem = $(this);
// ...
});
Esempio 5.12: Delegare un evento con $.fn.live
1
2
3
4
$('#myUnorderedList li').live('click', function(e) {
var $myListItem = $(this);
// ...
});
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
1
2
$('#myUnorderedList').undelegate('li', 'click');
$('#myUnorderedList li').die('click');
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
1
2
3
$('#menu li').hover(function() {
$(this).toggleClass('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
1
2
3
4
5
6
7
8
$('p.expander').toggle(
function() {
$(this).prev().addClass('open');
},
function() {
$(this).prev().removeClass('open');
}
);
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:
1. Impostare il valore dell'elemento input uguale al valore dell'elemento label;
24/08/2012 19:45
Fondamentali di jQuery
30 di 57
http://rhadrix.net/guest/book/index.html
2. Aggiungere la classe "hint" all'elemento input;
3. Remuover l'elemento label;
4. Collegare un evento focus nell'elemento input per rimuovere il testo di suggerimento e la classe "hint";
5. 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.
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:
1. Nascondere titti gli elementi div.module;
2. Creare una lista non ordinata prima del primo div.module per utilizzarla come schede;
3. 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.
4. 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;
5. Infine, mostrare la prima scheda.
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' anche
possibile 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 b ase di un effetto incorporato
1
$('h1').show();
24/08/2012 19:45
Fondamentali di jQuery
31 di 57
http://rhadrix.net/guest/book/index.html
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
1
2
$('h1').fadeIn(300);
$('h1').fadeOut('slow');
// dissolvenza in 300ms
// utilizzo di una definizione di velocità interna
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".
1
2
3
4
5
6
speeds: {
slow: 600,
fast: 200,
// Velocità predefinita
_default: 400
}
Pertanto, è possibile sovrascrivere o aggiungere nuovi valori all'oggetto. Per Esempio, quando si vuole cambiare l'effetto predefinito o aggiungere una v elocità
personalizzata.
Esempio 6.3: Aumentare la velocità con jQuery.fx.speeds
1
2
jQuery.fx.speeds.blazing = 100;
jQuery.fx.speeds.turtle = 2000;
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 eseguire
codice 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, la
parola 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
1
$('div.old').fadeOut(300, function() { $(this).remove(); });
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 selezione
restituisce 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
01
02
03
04
05
06
07
08
09
10
11
var $thing = $('#nonexistent');
var cb = function() {
console.log('realizzato!');
};
if ($thing.length) {
$thing.fadeIn(300, cb);
} else {
cb();
}
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
1
2
3
4
5
6
7
8
$('div.funtimes').animate(
{
left : "+=50",
opacity : 0.25
},
300, // durata
function() { console.log('done!'); // retrochiamata
});
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
24/08/2012 19:45
Fondamentali di jQuery
32 di 57
http://rhadrix.net/guest/book/index.html
[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 due
metodi 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: Transizione easing per ogni proprietà
1
2
3
4
5
6
7
$('div.funtimes').animate(
{
left : [ "+=50", "swing" ],
opacity : [ 0.25, "linear" ]
},
300
);
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.
1
$('h1').show(300).delay(1000).hide(300);
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ò essere
particolarmente 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 corrispondente
anche 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.
1. Spostare l'elemento #slideshow alla parte superiore della pagina;
2. Scrivere un codice per la visualizzazione degli items in maniera ciclica, mostrando un item per alcuni secondi, poi nasconderlo con un effetto fade out e
mostrare il seguente item con l'effetto di dissolvenza fade in;
3. Una volta raggiunto l'ultimo elemento della lista, ricominciare con il primo;
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
24/08/2012 19:45
Fondamentali di jQuery
33 di 57
http://rhadrix.net/guest/book/index.html
Ajax
Introduzione
Il metodo XMLHttpRequest (XHR) consente ai browser di comunicare con il server senza ricaricare la pagina. Questo metodo, noto anche come Ajax (Asincrono
JavaScript 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 eseguita
il 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 a
funzionare, 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 testo
formato HTML o informazioni in JSON (JavaScript Object Notation).
In generale, l'Ajax non funziona in domini diversi. T uttavia, 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 HT T P 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ò generare
comportamenti 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 un
utente 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 dal
nome 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 HT ML 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 i
dettagli 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 non
dovrebbe funzionare:
1
2
3
var response;
$.get('foo.php', function(r) { response = r; });
console.log(response); // undefined - indefinito!
24/08/2012 19:45
Fondamentali di jQuery
34 di 57
http://rhadrix.net/guest/book/index.html
Invece, è necessario specificare una funzione di ritorno, questa funzione verrà eseguita quando la richiesta si sia conclusa correttamente in quanto è allora che la
risposta del server è pronta.
1
$.get('foo.php', function(response) { console.log(response); });
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 agli
script 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 con
uno 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 scheda
console 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 fine
quando 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. T uttavia, 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 le
proprietà separatamente, rendendo più facile il riutilizzo del codice. È possibile visitare http://api.jquery.com/jQuery.ajax/ per consultare la documentazione sulle
opzioni disponibili nel metodo.
Esempio 7.1: Utilizzare il metodo $.ajax
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$.ajax({
// l'URL per la richiesta
url : 'post.php',
// invio di informazioni
// (è anche possibile utilizzare una stringa di dati)
data : { id : 123 },
// specificare se si tratta di una richiesta POST o GET
type : 'GET',
// il tipo di informazioni
// che ci si attende come risposta
dataType : 'json',
// codice da eseguire se la richiesta viene accettata;
// la risposta è passata come argomento alla funzione
success : function(json) {
$('<h1/>').text(json.title).appendTo('body');
$('<div class="content"/>')
.html(json.html).appendTo('body');
},
// codice da eseguire se la richiesta fallisce;
// sono passati come argomenti alla funzione
// l'oggetto della petizione in codice grezzo
// e lo stato della richiesta
error : function(xhr, status) {
alert('Spiacente, c\'è stato un problema!');
},
// codice da eseguire indipendentemente dal
// fatto se la richiesta riesca.
complete : function(xhr, status) {
alert('Richiesta fatta!');
}
});
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 HT T P non mostrerà alcun errore. Quando si lavora con le richieste Ajax, assicurarsi che il server invii il tipo di informazioni
che 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-type
dovrebbe 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 opzioni
disponibili, consultare http://api.jquery.com/jQuery.ajax/; le seguenti sono le più comuni:
24/08/2012 19:45
Fondamentali di jQuery
35 di 57
http://rhadrix.net/guest/book/index.html
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 argomenti
l'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 il
tipo 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 grezza
e 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 un
oggetto 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 visitate
http://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), ma
possono 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
24/08/2012 19:45
Fondamentali di jQuery
36 di 57
http://rhadrix.net/guest/book/index.html
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 e
l'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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
// ottiene il testo piano o html
$.get('/users.php', { userId : 1234 }, function(resp) {
console.log(resp);
});
// aggiunge uno script alla pagina e quindi
// esegue la funzione specificata
$.getScript('/static/js/myScript.js', function() {
functionFromMyScript();
});
// ottiene i dati in formato JSON dal server
$.getJSON('/details.php', function(resp) {
$.each(resp, function(k, v) {
console.log(k + ' : ' + v);
});
});
$.fn.load
Il metodo $.fn.load è l'unico che può essere chiamato da una selezione. Questo metodo ottiene il codice HT ML 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
1
$('#newContent').load('/foo.html');
Esempio 7.4: Utilizzare il metodo $.fn.load per riempire un elemento b asato su una selezione.
1
2
3
$('#newContent').load('/foo.html #myDiv h1:first', function(html) {
alert('Contenuto aggiornato!');
});
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 per
aggiungere 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
1
$('#myForm').serialize();
Esempio 7.6: Creare un array di oggetti che contengono informazioni da un form
1
2
3
4
5
6
7
$('#myForm').serializeArray();
// crea una struttura come questa:
[
{ name : 'field1', value : 123 },
{ name : 'field2', value : 'hello world' }
]
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 di
informazione, cui si accede attraverso un'API (Application programming interface in inglese) predefinita. Un particolare servizio che fornisce informazioni in formato
24/08/2012 19:45
Fondamentali di jQuery
37 di 57
http://rhadrix.net/guest/book/index.html
JSONP è Yahoo! Query Language, che lo utilizza per ottenere, per esempio, notizie sui gatti:
Esempio 7.7: Usare YQL e JSONP
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$.ajax({
url : 'http://query.yahooapis.com/v1/public/yql',
// viene aggiunto come parametro il nome della funzione
// di ritorno, come specificato nel servizio di YQL
jsonp : 'callback',
// si indica jQuery che è atteso informazioni
// in formato JSONP
dataType : 'jsonp',
// si indica al servizio di YQL quale è l'informazione
// che si desidera e che la si vuole in formato JSON
data : {
q : 'select title,abstract,url from search.news where query="cat"',
format : 'json'
},
// si esegue una funzione se
// la richiesta è andata a buon fine
success : function(response) {
console.log(response);
}
});
jQuery si occupa di risolvere tutti gli aspetti complessi della richiesta JSONP. T utto 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 queste
funzioni 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
1
2
3
$('#loading_indicator')
.ajaxStart(function() { $(this).show(); })
.ajaxStop(function() { $(this).hide(); });
Esercizi
Caricare contenuto esterno
Open the file /exercises/index.html in your browser. Use the file /exercises/js/load.js. Y our task is to load the content of a blog item when a user clicks on the
title of the item.
1. 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.
2. 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.
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 di
blog.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:
1
2
3
var href = 'blog.html#post1';
var tempArray = href.split('#');
var id = '#' + tempArray[1];
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.
1. Aggiungere un elemento div dopo il form all'interno dell'elemento #specials; sarà lì il luogo dove si metteranno le informazioni da ottenere.
2. Vincolare l'evento change sull'elemento select; quando si apporta una modifica nella selezione, inviare una richiesta Ajax a /exercises
/data/specials.json.
3. Quando la richiesta restituisce una risposta, utilizzare il valore selezionato nella select (suggerimento: $.fn.val) per trovare le informazioni appropriate nella
risposta JSON.
4. Aggiungere un po' di HT ML con le informazioni ottenute nel div creato in precedenza.
5. Infine rimuovere il pulsante di invio (submit) del form.
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 salv are le
informazioni per trarre vantaggio quando si torna a modificare la selezione?
24/08/2012 19:45
Fondamentali di jQuery
38 di 57
http://rhadrix.net/guest/book/index.html
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, tutti
gli 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:
1
2
3
4
5
6
7
(function($){
$.fn.myNewPlugin = function() {
return this.each(function(){
// fare qualcosa
});
};
}(jQuery));
L'estensione del prototipo dell'oggetto jQuery si verifica nella seguente riga:
1
$.fn.myNewPlugin = function() { //...
Il quale è racchiusa in una funzione auto-eseguibile
1
2
3
(function($){
//...
}(jQuery));
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 è:
1
2
3
4
5
$.fn.myNewPlugin = function() {
return this.each(function(){
// fare qualcosa
});
};
In esso, la parola chiave this si riferisce all'oggetto jQuery in cui è chiamata l'estensione.
1
2
3
4
5
6
7
8
var somejQueryObject = $('#something');
$.fn.myNewPlugin = function() {
alert(this === somejQueryObject);
};
somejQueryObject.myNewPlugin();
// mostra un avviso con 'true'
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():
1
2
3
4
5
$.fn.myNewPlugin = function() {
return this.each(function(){
});
};
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:
01
02
03
04
05
06
07
08
09
10
11
12
(function($){
$.fn.showLinkLocation = function() {
return this.filter('a').each(function(){
$(this).append(
' (' + $(this).attr('href') + ')'
);
});
};
}(jQuery));
// Esempio di utilizzo:
$('a').showLinkLocation();
L'estensione modificherà tutti i link all'interno della collezione di oggetti e aggiungerà il valore attributo del suo attributo href tra parentesi.
1
2
3
<!-- Prima che l'estensione sia chiamata: -->
<a href="page.html">Foo</a>
24/08/2012 19:45
Fondamentali di jQuery
39 di 57
4
5
http://rhadrix.net/guest/book/index.html
<!-- Dopo che l'estensione sia chiamata: -->
<a href="page.html">Foo (page.html)</a>
È anche possibile ottimizzare l'estensione:
1
2
3
4
5
6
7
(function($){
$.fn.showLinkLocation = function() {
return this.filter('a').append(function(){
return ' (' + this.href + ')';
});
};
}(jQuery));
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 un
altro metodo di jQuery:
01
02
03
04
05
06
07
08
09
10
(function($){
$.fn.fadeInAndAddClass = function(duration, className) {
return this.fadeIn(duration, function(){
$(this).addClass(className);
});
};
}(jQuery));
// Esempio di utilizzo:
$('a').fadeInAndAddClass(400, 'finishedFading');
Individuare e valutare estensioni
Uno degli aspetti più popolari di jQuery è la diversità di estensioni che esistono.
T uttavia, 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, senza
seguire 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 trovata
l'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 possono
arrivare a sovraccaricare la pagina. Per ulteriori suggerimenti su come individuare un'estensione mediocre, è possibile leggere l'articolo (in inglese) I segni di un plugin
per 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 cartella
dell'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 di
operazioni.
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
01
02
03
04
05
06
07
08
09
10
11
// definizione dell'estensione
(function($){
$.fn.hoverClass = function(c) {
return this.hover(
function() { $(this).toggleClass(c); }
);
};
})(jQuery);
// utilizzare l'estensione
$('li').hoverClass('hover');
Per ulteriori informazioni sullo sviluppo di estensioni, vedere l'articolo (in inglese) A Plugin Development Pattern di Mike Alsup. In questo articolo, si sviluppa
un'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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
//
// creare una chiusura
//
(function($) {
//
// definizione dell'estensione
//
$.fn.hilight = function(options) {
debug(this);
// generazione delle opzioni principali
// prima di interagire
var opts = $.extend({}, $.fn.hilight.defaults, options);
// ittera e riformatta ogni elemento
return this.each(function() {
$this = $(this);
24/08/2012 19:45
Fondamentali di jQuery
40 di 57
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
http://rhadrix.net/guest/book/index.html
// generazione delle opzioni specifiche
// per ogni elemento
var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
// aggiornamento degli stili per ogni elemento
$this.css({
backgroundColor: o.background,
color: o.foreground
});
var markup = $this.html();
// si chiama la funzione per la formattazione
markup = $.fn.hilight.format(markup);
$this.html(markup);
});
};
//
// funzione privata per la depurazione
//
function debug($obj) {
if (window.console && window.console.log)
window.console.log('hilight selection count: ' + $obj.size());
};
//
// definire ed esporre la funzione di formattazione
//
$.fn.hilight.format = function(txt) {
return '<strong>' + txt + '</strong>';
};
//
// opzioni predefinite
//
$.fn.hilight.defaults = {
foreground: 'red',
background: 'yellow'
};
//
// fine della chiusura
//
})(jQuery);
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 solo
elemento, 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 e
ammette più funzioni da essere esposte in una singola estensione. Questo sistema è chiamato widget factory e fa parte della versione 1.8 di jQuery UI attraverso
jQuery.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 le
funzioni 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, il
contesto è sempre un unico oggetto, mai una collezione.
Esempio 8.3: Una semplice estensione con mantenimento dello stato utilizzando widget factory di jQuery UI
1
2
3
4
5
6
7
8
$.widget("nmk.progressbar", {
_create: function() {
var progress = this.options.value + "%";
this.element
.addClass("progressbar")
.text(progress);
}
});
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 di
una collezione più ampia. D'altra parte, lo spazio dei nomi ui è riservato per le estensioni ufficiali di jQuery UI.
24/08/2012 19:45
Fondamentali di jQuery
41 di 57
http://rhadrix.net/guest/book/index.html
Esempio 8.4: Passare opzioni al widget
1
2
3
$("<div></div>")
.appendTo( "body" )
.progressbar({ value: 20 });
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
01
02
03
04
05
06
07
08
09
10
11
12
13
$.widget("nmk.progressbar", {
// opzioni predefinite
options: {
value: 0
},
_create: function() {
var progress = this.options.value + "%";
this.element
.addClass( "progressbar" )
.text( progress );
}
});
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 metodo
nell'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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$.widget("nmk.progressbar", {
options: {
value: 0
},
_create: function() {
var progress = this.options.value + "%";
this.element
.addClass("progressbar")
.text(progress);
},
// crea un metodo pubblico
value: function(value) {
// non si passa alcun valore,
// agisce quindi come metodo ottenitore (getter)
if (value === undefined) {
return this.options.value;
// passando un valore, agisce quindi
// come metodo impostatore (setter)
} else {
this.options.value = this._constrain(value);
var progress = this.options.value + "%";
this.element.text(progress);
}
},
// crea un metodo privato
_constrain: function(value) {
if (value > 100) {
value = 100;
}
if (value < 0) {
value = 0;
}
return value;
}
});
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 questi
devono essere passati subito dopo il nome del metodo.
Esempio 8.7: Chiamare i metodi in un'istanza dell'estensione
01
02
03
04
05
06
07
08
09
10
11
12
var bar = $("<div></div>")
.appendTo("body")
.progressbar({ value: 20 });
// ottiene il valore corrente
alert(bar.progressbar("value"));
// aggiorna il valore
bar.progressbar("value", 50);
// ottiene di nuovo il valore
alert(bar.progressbar("value"));
24/08/2012 19:45
Fondamentali di jQuery
42 di 57
http://rhadrix.net/guest/book/index.html
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 di
coppie di nomi e valori il metodo funziona come setter. Se utilizzato come metodo getter, l'estensione restituirà il valore corrente dell'opzione corrispondente al nome
passato 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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
$.widget("nmk.progressbar", {
options: {
value: 0
},
_create: function() {
this.element.addClass("progressbar");
this._update();
},
_setOption: function(key, value) {
this.options[key] = value;
this._update();
},
_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
}
});
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'estensione
cambia. 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 implementare
funzionalità personalizzate.
Esempio 8.9: Fornire funzioni di (callb ack) retrochiamata
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$.widget("nmk.progressbar", {
options: {
value: 0
},
_create: function() {
this.element.addClass("progressbar");
this._update();
},
_setOption: function(key, value) {
this.options[key] = value;
this._update();
},
_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
if (this.options.value == 100) {
this._trigger("complete", null, { value: 100 });
}
}
});
Le funzioni di callback sono essenzialmente solo opzioni aggiuntive e possono essere impostate come qualsiasi altra opzione. Ogni volta che una funzione di callback
viene 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 di
callback. 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
02
03
04
05
06
07
var bar = $("<div></div>")
.appendTo("body")
.progressbar({
complete: function(event, data) {
alert( "Funzione di callback" );
}
})
24/08/2012 19:45
Fondamentali di jQuery
43 di 57
08
09
10
11
12
13
http://rhadrix.net/guest/book/index.html
.bind("progressbarcomplete", function(event, data) {
alert("Eventi bolla e molti gestori di supporto per una flessibilità estrema.");
alert("Il valore della barra di avanzamento è " + data.value);
});
bar.progressbar("option", "value", 100);
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. T utte le caratteristiche che automaticamente si aggiungono all'estensione provvengono dal prototipo base del widget, il quale è definito come
jQuery.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 i
metodi direttamente nell'istanza dell'estensione invece di passare il nome del metodo come una stringa, dando la possibilità di accedere alle proprietà dell'estensione.
01
02
03
04
05
06
07
08
09
10
11
12
var bar = $("<div></div>")
.appendTo("body")
.progressbar()
.data("progressbar" );
// chiamare un metodo direttamente
// nell'istanza dell'estensione
bar.option("value", 50);
// accedere alle proprietà
// nell'istanza dell'estensione
alert(bar.options.value);
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 nel
prototipo dell'estensione permette di modificarli anche in tutte le istanze dell'estensione. Per esempio, se vogliamo aggiungere un metodo all'estensione della barra di
avanzamento per permettere di resettare il progresso a 0%, è possibile farlo aggiungendo questo metodo al prototipo e sarà automaticamente disponibile per essere
chiamato da qualsiasi istanza dell'estensione.
1
2
3
$.nmk.progressbar.prototype.reset = function() {
this._setOption("value", 0);
};
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 rimosso
dal 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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$.widget( "nmk.progressbar", {
options: {
value: 0
},
_create: function() {
this.element.addClass("progressbar");
this._update();
},
_setOption: function(key, value) {
this.options[key] = value;
this._update();
},
_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
if (this.options.value == 100 ) {
this._trigger("complete", null, { value: 100 });
}
},
destroy: function() {
this.element
.removeClass("progressbar")
.text("");
// chiama alla funzione base destroy
$.Widget.prototype.destroy.call(this);
}
});
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 i
suoi 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.
24/08/2012 19:45
Fondamentali di jQuery
44 di 57
http://rhadrix.net/guest/book/index.html
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.
1
$('#myTable').stripe('#cccccc');
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 jQuery
Anti-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.
1
2
3
4
5
var myLength = myArray.length;
for (var i = 0; i < myLength; i++) {
// fare delle cose
}
Aggiungere nuovi contenuti fuori da un ciclo
Se si sta inserendo molti elementi nel DOM, fatelo tutti in una volta, non uno per volta.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
// male
$.each(myArray, function(i, item) {
var newListItem = '<li>' + item + '</li>';
$('#ballers').append(newListItem);
});
// meglio: fare questo
var frag = document.createDocumentFragment();
$.each(myArray, function(i, item) {
var newListItem = '<li>' + item + '</li>';
frag.appendChild(newListItem);
});
$('#ballers')[0].appendChild(frag);
// o questo
var myHtml = '';
$.each(myArray, function(i, item) {
html += '<li>' + item + '</li>';
});
$('#ballers').html(myHtml);
Non Ripetersi
Nessuna ricorrenza; fare le cose una volta e solo una, altrimenti è sbagliato.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
// MALE
if ($eventfade.data('currently') != 'showing') {
$eventfade.stop();
}
if ($eventhover.data('currently') != 'showing') {
$eventhover.stop();
}
if ($spans.data('currently') != 'showing') {
$spans.stop();
}
// BENE
var $elems = [$eventfade, $eventhover, $spans];
$.each($elems, function(i,elem) {
if (elem.data('currently') != 'showing') {
elem.stop();
}
});
24/08/2012 19:45
Fondamentali di jQuery
45 di 57
http://rhadrix.net/guest/book/index.html
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).
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// MALE
$(document).ready(function() {
$('#magic').click(function(e) {
$('#yayeffects').slideUp(function() {
// ...
});
});
$('#happiness').load(url + ' #unicorns', function() {
// ...
});
});
// MEGLIO
var PI = {
onReady : function() {
$('#magic').click(PI.candyMtn);
$('#happiness').load(PI.url + ' #unicorns', PI.unicornCb);
},
candyMtn : function(e) {
$('#yayeffects').slideUp(PI.slideCb);
},
slideCb : function() { ... },
unicornCb : function() { ... }
};
$(document).ready(PI.onReady);
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. T uttavia, ci sono alcuni consigli da tenere a mente.
Selettori basati sugli ID
È sempre meglio iniziare le selezioni con un ID.
1
2
3
4
5
// veloce
$('#container div.robotarm');
// super-veloce
$('#container').find('div.robotarm');
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.
1
2
3
4
5
// non ottimizzato
$('div.data .gonzalez');
// ottimizzato
$('.data td.gonzalez');
Utilizzare il più possibile tag.classe del lato destro della selezione, e solo tag o .classe a sinistra.
Evitare specificità eccessiva
1
2
3
4
$('.data table.attendees td.gonzalez');
// molto meglio: eliminare il mezzo, se possibile,
$('.data td.gonzalez');
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.
1
2
3
4
5
6
$('.buttons > *'); // molto lento
$('.buttons').children(); // molto meglio
$('.gender :radio'); // selezione universale implicita
$('.gender *:radio'); // stesa cosa, ma in modo esplicito
$('.gender input:radio'); // molto meglio
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 (per
esempio, gli elementi in una lista). jQuery rende rende questo lavoro facile attraverso $.fn.live e $.fn.delegate. Se possibile, si raccomanda utilizzare
24/08/2012 19:45
Fondamentali di jQuery
46 di 57
http://rhadrix.net/guest/book/index.html
$.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.
1
2
3
4
5
6
7
8
9
// sbagliato (se ci sono molti elementi nella lista)
$('li.trigger').click(handlerFn);
// meglio: delegazione di eventi con $ fn.live.
$('li.trigger').live('click', handlerFn);
// molto meglio:. delegazione di evento con $ fn.delegate
// permette specificare un contesto in modo facile
$('#myList').delegate('li.trigger', 'click', handlerFn);
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.
1
2
3
4
5
6
var $table = $('#myTable');
var $parent = $table.parent();
$table.detach();
// ... si aggiungono molte celle alla tabella
$parent.append($table);
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%.
1
2
3
4
// corretto fino a 20 elementi, lento dopo i 20 elementi
$('a.swedberg').css('color', '#asd123');
$('<style type="text/css">a.swedberg { color : #asd123 }</style>')
.appendTo('head');
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.
1
2
3
4
5
// regolare
$(elem).data(key,value);
// 10 volte più veloce
$.data(elem,key,value);
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 contiene
elementi.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
// SBAGLIATO: il codice esegue tre funzioni
// senza verificare se ci sono
// nella selezione
$('#nosuchthing').slideUp();
// MEGLIO
var $mySelection = $('#nosuchthing');
if ($mySelection.length) { $mySelection.slideUp(); }
// MOLTO MEGLIO: aggiunge una estensione doOnce
jQuery.fn.doOnce = function(func){
this.length && func.apply(this);
return this;
}
$('li.cartitems').doOnce(function(){
// fare qualcosa
});
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.
1
2
3
4
5
6
7
8
9
// antico
var test = 1;
var test2 = function() { ... };
var test3 = test2(test);
// migliore modo
var test = 1,
test2 = function() { ... },
test3 = test2(test);
Nelle funzioni di autoeseguibili, le definizioni di variabili possono essere passate tutte insieme.
24/08/2012 19:45
Fondamentali di jQuery
47 di 57
1
http://rhadrix.net/guest/book/index.html
(function(foo, bar) { ... })(1, 2);
Condizionali
1
2
3
4
5
6
7
8
// antico
if (type == 'foo' || type == 'bar') { ... }
// migliore
if (/^(foo|bar)$/.test(type)) { ... }
// ricerca in oggetto letterale
if (({ foo : 1, bar : 1 })[type]) { ... }
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 ad
analizzare 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 un
rappresentanzio 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 la
comunicazione con altre unità dovrebbe avvenire attraverso un sistema di messaggi come eventi personalizzati o pub/sub. E per quanto possibile, tenere
lontana 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 applicazioni
complesse, 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 per
eliminare le funzioni anonime, centralizzare le opzioni di configurazione, e facilitare la via per il riutilizzo e il rifattorizzazione.
Esempio 10.1: Un oggetto letterale
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
var myFeature = {
myProperty : 'ciao',
myMethod : function() {
console.log(myFeature.myProperty);
},
init : function(settings) {
myFeature.settings = settings;
},
readSettings : function() {
console.log(myFeature.settings);
}
};
myFeature.myProperty; // 'ciao'
myFeature.myMethod(); // registra 'ciao'
myFeature.init({ foo : 'bar' });
myFeature.readSettings(); // registra { foo : 'bar' }
24/08/2012 19:45
Fondamentali di jQuery
48 di 57
http://rhadrix.net/guest/book/index.html
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:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
// Facendo clic su un item della lista
// si carica un certo contenuto.
// Utilizzando l'ID dell'item e a sua
// volta nasconde gli altri item fratelli.
$(document).ready(function() {
$('#myFeature li')
.append('<div/>')
.click(function() {
var $this = $(this);
var $div = $this.find('div');
$div.load('foo.php?item=' +
$this.attr('id'),
function() {
$div.show();
$this.siblings()
.find('div').hide();
}
);
});
});
Se l'esempio illustrato rappresenta il 100% della richiesta, si consiglia di lasciare così com'è. T uttavia, se il pezzo è solo una parte di una applicazione più grande, sarebbe
bene 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'area
di 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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var myFeature = {
init : function(settings) {
myFeature.config = {
$items : $('#myFeature li'),
$container : $('<div class="container"></div>'),
urlBase : '/foo.php?item='
};
// permete di sovrascrivere
// la configurazione predefinita
$.extend(myFeature.config, settings);
myFeature.setup();
},
setup : function() {
myFeature.config.$items
.each(myFeature.createContainer)
.click(myFeature.showItem);
},
createContainer : function() {
var $i = $(this),
$c = myFeature.config.$container.clone()
.appendTo($i);
$i.data('container', $c);
},
buildUrl : function() {
return myFeature.config.urlBase +
myFeature.$currentItem.attr('id');
},
showItem : function() {
var myFeature.$currentItem = $(this);
myFeature.getContent(myFeature.showContent);
},
getContent : function(callback) {
var url = myFeature.buildUrl();
myFeature.$currentItem
.data('container').load(url, callback);
},
showContent : function() {
myFeature.$currentItem
.data('container').show();
myFeature.hideContent();
},
hideContent : function() {
myFeature.$currentItem.siblings()
.each(function() {
$(this).data('container').hide();
});
}
};
$(document).ready(myFeature.init);
La prima caratteristica da notare è che il codice è più lungo da quello originale - come affermato in precedenza, se questo è il campo dell'applicazione, utilizzare un
oggetto 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
24/08/2012 19:45
Fondamentali di jQuery
49 di 57
http://rhadrix.net/guest/book/index.html
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().
T uttavia, 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 si
desidera.
Esempio 10.3: Il modello modulare
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var feature =(function() {
// variabili e funzioni private
var privateThing = 'segreto',
publicThing = 'non segreto',
changePrivateThing = function() {
privateThing = 'super segreto';
},
sayPrivateThing = function() {
console.log(privateThing);
changePrivateThing();
};
// API pubblica
return {
publicThing : publicThing,
sayPrivateThing : sayPrivateThing
}
})();
feature.publicThing; // registra 'non segreto'
feature.sayPrivateThing();
// registra 'segreto' e cambia il valore
// di privateThing a 'super segreto'
Nell'esempio, si autoesegue un funzione anonima che restituisce un oggetto. All'interno della funzione, si definiscono alcune variabili. Visto che sono definite all'interno
della 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 della
funzione ha accesso alla variabile privateThing o alla funzione sayPrivateThing. T uttavia, 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 v isto 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
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$(document).ready(function() {
var feature = (function() {
var $items = $('#myFeature li'),
$container = $('<div class="container"></div>'),
$currentItem,
urlBase = '/foo.php?item=',
createContainer = function() {
var $i = $(this),
$c = $container.clone().appendTo($i);
$i.data('container', $c);
},
buildUrl = function() {
return urlBase + $currentItem.attr('id');
},
showItem = function() {
var $currentItem = $(this);
getContent(showContent);
},
showItemByIndex = function(idx) {
$.proxy(showItem, $items.get(idx));
},
getContent = function(callback) {
$currentItem.data('container').load(buildUrl(), callback);
},
showContent = function() {
$currentItem.data('container').show();
hideContent();
},
24/08/2012 19:45
Fondamentali di jQuery
50 di 57
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
http://rhadrix.net/guest/book/index.html
hideContent = function() {
$currentItem.siblings()
.each(function() {
$(this).data('container').hide();
});
};
$items
.each(createContainer)
.click(showItem);
return { showItemByIndex : showItemByIndex };
})();
feature.showItemByIndex(0);
});
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 in
modo 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 il
caricamento 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 tempo
di 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 codice
incapsulato, 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 esclude
porzioni 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. Di
seguito, l'esempio presuppone che sia jQuery come gli altri files siano all'interno della cartella scripts/.
Esempio 10.5: Usare RequireJS: un semplice esempio
01
02
03
04
05
06
07
08
09
10
11
<!DOCTYPE html>
<html>
<head>
<title>jQuery+RequireJS pagina di esempio</title>
<script src="scripts/require-jquery.js"></script>
<script>require(["app"]);</script>
</head>
<body>
<h1>jQuery+RequireJS pagina di esempio</h1>
</body>
</html>
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:
1
<script>require(["scripts/app.js"]);</script>
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
1
2
3
4
5
6
7
require(["jquery.alpha", "jquery.beta"], function() {
// le estensioni jquery.alpha.js y jquery.beta.js
// sono state caricate.
$(function() {
$('body').alpha().beta();
});
});
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:
24/08/2012 19:45
Fondamentali di jQuery
51 di 57
http://rhadrix.net/guest/book/index.html
Esempio 10.7: Definizione di un modulo RequireJS che non ha dipendenze
1
2
3
4
5
6
require.def("my/simpleshirt",
{
color: "black",
size: "unisize"
}
);
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 (nello
stesso 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
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
require.def("my/shirt",
["my/cart", "my/inventory"],
function(cart, inventory) {
// restituisce un oggetto che definisce
// il modulo "my/shirt".
return {
color: "blue",
size: "large"
addToCart: function() {
inventory.decrement(this);
cart.add(this);
}
}
}
);
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:
1
2
3
my/cart.js
my/inventory.js
my/shirt.js
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
01
02
03
04
05
06
07
08
09
10
11
require.def("my/title",
["my/dependency1", "my/dependency2"],
function(dep1, dep2) {
// restituisce una funzione per definire "my/title".
// Questo restituisce o imposta
// il titolo della finestra
return function(title) {
return title ? (window.title = title) : window.title;
}
}
);
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 di
fuori 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 HT ML e
tutti i file JavaScript dell'applicazione). La struttura della cartella è la seguente:
1
2
3
4
5
6
requirejs/ (utilizzayo per eseguire gli strumenti)
webapp/app.html
webapp/scripts/app.js
webapp/scripts/require-jquery.js
webapp/scripts/jquery.alpha.js
webapp/scripts/jquery.beta.js
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
01
02
03
04
05
06
07
08
{
appDir: "../",
baseUrl: "scripts/",
dir: "../../webapp-build",
// Commentare la riga seguente se volete
// minimizzare il codice dal compilatore
// in modalità "semplice"
optimize: "none",
24/08/2012 19:45
Fondamentali di jQuery
52 di 57
09
10
11
12
13
14
15
http://rhadrix.net/guest/book/index.html
modules: [
{
name: "app"
}
]
}
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:
1
2
3
4
5
# per sistemi non-Windows
../../requirejs/build/build.sh app.build.js
# per sistemi Windows
..\..\requirejs\build\build.bat app.build.js
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:
1
2
3
4
5
6
7
var myPortlet = Portlet({
title : 'Curry',
source : 'data/html/curry.html',
initialState : 'open' // or 'closed'
});
myPortlet.$element.appendTo('body');
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:
1
2
3
4
5
6
7
8
myPortlet.open();
myPortlet.close();
myPortlet.toggle();
// forza per aprire
// forza per chiudere
// alterna gli stati
// tra aperto e chiuso
myPortlet.refresh(); // aggiorna il contenuto
myPortlet.destroy(); // rimuove il porlet dalla pagina
myPortlet.setSource('data/html/onions.html');
// cambia il codice
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 capitolo
useremo 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 le
esigenze. Tuttavia, gli eventi personalizzati offrono un modo nuovo di pensare la programmazione in JavaScript. Invece di concentrarsi sull'elemento che esegue
un'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):
1
2
3
4
5
6
<div class="room" id="kitchen">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>
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, vogliono
solo cambiare il loro stato.
Senza l'utilizzo di eventi personalizzati, è possibile scrivere la routine come segue:
24/08/2012 19:45
Fondamentali di jQuery
53 di 57
1
2
3
4
5
6
7
8
http://rhadrix.net/guest/book/index.html
$('.switch, .clapper').click(function() {
var $light = $(this).parent().find('.lightbulb');
if ($light.hasClass('on')) {
$light.removeClass('on').addClass('off');
} else {
$light.removeClass('off').addClass('on');
}
});
D'altra parte, con gli eventi personalizzati, il codice appare così:
01
02
03
04
05
06
07
08
09
10
11
12
$('.lightbulb').bind('changeState', function(e) {
var $light = $(this);
if ($light.hasClass('on')) {
$light.removeClass('on').addClass('off');
} else {
$light.removeClass('off').addClass('on');
}
});
$('.switch, .clapper').click(function() {
$(this).parent().find('.lightbulb').trigger('changeState');
});
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:
01
02
03
04
05
06
07
08
09
10
11
12
13
<div class="room" id="kitchen">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>
<div class="room" id="bedroom">
<div class="lightbulb on"></div>
<div class="switch"></div>
<div class="switch"></div>
<div class="clapper"></div>
</div>
<div id="master_switch"></div>
Se c'è una lampada accesa in casa, è possibile spegnerla tramite l'interruttore generale, nello stesso modo quando ci sono luci spente, è possibile accenderle con questo
interruttore. 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:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$('.lightbulb')
.bind('changeState', function(e) {
var $light = $(this);
if ($light.hasClass('on')) {
$light.trigger('turnOff');
} else {
$light.trigger('turnOn');
}
})
.bind('turnOn', function(e) {
$(this).removeClass('off').addClass('on');
})
.bind('turnOff', function(e) {
$(this).removeClass('off').addClass('on');
});
$('.switch, .clapper').click(function() {
$(this).parent().find('.lightbulb').trigger('changeState');
});
$('#master_switch').click(function() {
if ($('.lightbulb.on').length) {
$('.lightbulb').trigger('turnOff');
} else {
$('.lightbulb').trigger('turnOn');
}
});
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 che
appartiene 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 associate
all'evento come secondo argomento, spostando come terzo argomento la funzione gestore degli eventi. Qualunque informazione passata sarà disponibile alla
funzione attraverso della proprietà data dell'oggetto dell'evento. A sua volta, la funzione del gestore degli eventi riceve l'oggetto dell'evento come primo
argomento.
Il metodo $.fn.trigger prende come argomenti il tipo di evento e facoltativamente può prendere un array di valori. Questi valori saranno passati alla
24/08/2012 19:45
Fondamentali di jQuery
54 di 57
http://rhadrix.net/guest/book/index.html
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:
1
2
3
4
5
6
7
$(document).bind('myCustomEvent', { foo : 'bar' }, function(e, arg1, arg2) {
console.log(e.data.foo); // 'bar'
console.log(arg1); // 'bim'
console.log(arg2); // 'baz'
});
$(document).trigger('myCustomEvent', [ 'bim', 'baz' ]);
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 una
ricerca 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:
24/08/2012 19:45
Fondamentali di jQuery
55 di 57
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
http://rhadrix.net/guest/book/index.html
<h1>Twitter Search</h1>
<input type="button" id="get_trends"
value="Load Trending Terms" />
<form>
<input type="text" class="input_text"
id="search_term" />
<input type="submit" class="input_submit"
value="Add Search Term" />
</form>
<div id="twitter">
<div class="template results">
<h2>Search Results for
<span class="search_term"></span></h2>
</div>
</div>
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 eseguiranno
azioni. 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. T ale 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.
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
$.fn.twitterResult = function(settings) {
return this.each(function() {
var $results = $(this),
$actions = $.fn.twitterResult.actions =
$.fn.twitterResult.actions ||
$.fn.twitterResult.createActions(),
$a = $actions.clone().prependTo($results),
term = settings.term;
$results.find('span.search_term').text(term);
$.each(
['refresh', 'populate', 'remove', 'collapse', 'expand'],
function(i, ev) {
$results.bind(
ev,
{ term : term },
$.fn.twitterResult.events[ev]
);
}
);
// utilizza la classe di ogni azione per
// determinare quale evento si svolgerà
// nel riquadro dei risultati
$a.find('li').click(function() {
// passa l'elemento <li> cliccato
// sulla funzione in modo da poterlo
// manipolare, se necessario
$results.trigger($(this).attr('class'), [ $(this) ]);
});
});
};
$.fn.twitterResult.createActions = function() {
return $('<ul class="actions" />').append(
'<li class="refresh">Refresh</li>' +
'<li class="remove">Remove</li>' +
'<li class="collapse">Collapse</li>'
);
};
$.fn.twitterResult.events = {
refresh : function(e) {
// indica che i risultati sono
// in fase di aggiornamento
var $this = $(this).addClass('refreshing');
$this.find('p.tweet').remove();
$results.append('<p class="loading">Loading ...</p>');
24/08/2012 19:45
Fondamentali di jQuery
56 di 57
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
http://rhadrix.net/guest/book/index.html
// ottiene le informazioni da Twitter
// in formato jsonp
$.getJSON(
'http://search.twitter.com/search.json?q=' +
escape(e.data.term) + '&rpp=5&callback=?',
function(json) {
$this.trigger('populate', [ json ]);
}
);
},
populate : function(e, json) {
var results = json.results;
var $this = $(this);
$this.find('p.loading').remove();
$.each(results, function(i,result) {
var tweet = '<p class="tweet">' +
'<a href="http://twitter.com/' +
result.from_user +
'">' +
result.from_user +
'</a>: ' +
result.text +
' <span class="date">' +
result.created_at +
'</span>' +
'</p>';
$this.append(tweet);
});
// indica che i risultati
// sono già stati aggiornati
$this.removeClass('refreshing');
},
remove : function(e, force) {
if (
!force &&
!confirm('Rimuovere pannello per il termine ' + e.data.term + '?')
) {
return;
}
$(this).remove();
// indica che si non avrà
// un pannello per il termine
search_terms[e.data.term] = 0;
},
collapse : function(e) {
$(this).find('li.collapse').removeClass('collapse')
.addClass('expand').text('Expand');
$(this).addClass('collapsed');
},
expand : function(e) {
$(this).find('li.expand').removeClass('expand')
.addClass('collapse').text('Collapse');
$(this).removeClass('collapsed');
}
};
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 T witter:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
$('#twitter')
.bind('getResults', function(e, term) {
// si verifica che non ci sia
// un contenitore per il termine
if (!search_terms[term]) {
var $this = $(this);
var $template = $this.find('div.template');
// fa una copia del modello div e la inserisce
// come il primo contenitore di risultati
$results = $template.clone().
removeClass('template').
insertBefore($this.find('div:first')).
twitterResult({
'term' : term
});
// carica il contenuto utilizzando
// l'evento personalizzato "refresh"
24/08/2012 19:45
Fondamentali di jQuery
57 di 57
20
21
22
23
24
25
26
27
28
29
30
31
32
33
http://rhadrix.net/guest/book/index.html
// vincolato al contenitore dei risultati
$results.trigger('refresh');
search_terms[term] = 1;
}
})
.bind('getTrends', function(e) {
var $this = $(this);
$.getJSON('http://search.twitter.com/trends.json?callback=?', function(json) {
var trends = json.trends;
$.each(trends, function(i, trend) {
$this.trigger('getResults', [ trend.name ]);
});
});
});
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 è creato
una 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 esegue
getResults. D'altra parte, cliccando sul pulsante per caricare i "temi caldi", si esegue l'evento getTrends:
1
2
3
4
5
6
7
8
9
$('form').submit(function(e) {
e.preventDefault();
var term = $('#search_term').val();
$('#twitter').trigger('getResults', [ term ]);
});
$('#get_trends').click(function() {
$('#twitter').trigger('getTrends');
});
Aggiugendo pulsanti con un ID apropriato, è possibile rimuovere, collassare, espandere e aggiornare tutti i contenitori di risultati, allo stesso tempo. Per il pulsante che
rimuove 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.
1
2
3
4
5
6
7
8
9
$.each(['refresh', 'expand', 'collapse'], function(i, ev) {
$('#' + ev).click(function(e) { $('#twitter div.results').trigger(ev); });
});
$('#remove').click(function(e) {
if (confirm('Remove all results?')) {
$('#twitter div.results').trigger('remove', [ true ]);
}
});
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 si
prende il tempo dall'inizio per spiegare le parti della vostra applicazione, così come i comportamenti che queste parti hanno bisogno di esibire, gli eventi personalizzati
forniscono 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 di
interfaccia. 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 suo
comportamento.
È 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.
24/08/2012 19:45