Il 14 gennaio scorso, giorno del quarto compleanno della più popolare libreria JavaScript, è stata rilasciata l'ultima versione di jQuery: la 1.4.
Come tutte le precedenti versioni rilasciate, gli aggiornamenti apportati sono molti e in questo articolo li analizzeremo brevemente soffermandoci sulle principali novità in termini di API e affrontando anche lo scomodo problema della retrocompatibilità con script e plugin realizzati con versioni precedenti della libreria.
Cosa c'è di nuovo?
Performance
Uno dei temi preferiti da Resig, padre del framework, rimane quello relativo alle performance e all'utilizzo sapiente delle risorse dei computer, tematica direi fondamentale per quanto riguarda un linguaggio interpretato (e non sempre ottimamente dai browser) come è JavaScript.
La nuova versione di jQuery porta con sé notevoli miglioramenti da questo punto di vista, soprattutto nelle funzionalità relative alla ricerca e manipolazione del DOM, da sempre aspetto critico.
Ecco alcune immagini riassuntive dei benefici ottenuti nei principali metodi della libreria:
![screenshot](http://farm3.static.flickr.com/2781/4271691293_324e506c7b.jpg)
![screenshot](http://farm5.static.flickr.com/4029/4271691471_1240afd5af.jpg)
![screenshot](http://farm5.static.flickr.com/4026/4271691147_fd72853fa4.jpg)
![screenshot](http://farm5.static.flickr.com/4037/4271691747_0cce01a33d.jpg)
Manipolazione del DOM
Nuovo parametro
Oltre ad un miglioramento delle performance, i metodi per la manipolazione del DOM presentano una nuova funzionalità. Fino alla versione precedente, questa tipologia di funzioni (tra le quali ricordiamo attr()
, css()
, val()
, html()
, text()
, append()
, wrap()
, addClass()
, removeClass()
) accettavano un valore sotto forma di stringa (o per alcuni di essi come oggetto JSON). Con la versione 1.4 sarà possibile passare al metodo anche una particolare funzione che verrà eseguita dal motore di jQuery e il cui risultato verrà utilizzato come valore per modificare il DOM.
Per intenderci meglio:
var getHTML = function() {
return “Questo è̀ un frammento di HTML”;
}
$(“#test_div”).html(getHTML);
L'aspetto interessante di questa novità riguarda la possibilità̀, all'interno della funzione, di utilizzare alcuni parametri passati in fase di invocazione come per esempio l'elemento corrente e il valore della vecchia proprietà da modificare. Per esempio:
var updater = function(item, oldValue) {
return “E' ora di cambiare “ + oldValue + “ con qualcosa di nuovo”;
}
$(“a”).attr(“title”, updater);
$(“div”).html(updater);
Eliminiamo i container
Grazie al nuovo metodo unwrap()
è possibile eliminare dalla pagina il container parent
dell'elemento selezionato senza però rimuovere il suo contenuto. Quindi partendo da un HTML di questo tipo:
<div id="out"> <div id="in">
</div>
</div>
<span>Testo</span>
e invocando lo script:
$(“span”).unwrap();
si otterrà il seguente risultato:
<div id="out"> <span>Testo</span>
</div>
Remove e detach
Il metodo detach()
, a differenza del già presente remove()
, permette di rimuovere dal DOM un particolare elemento senza però rimuoverne le meta informazioni (impostate tramite data()
) ed eventuali callback associate a degli eventi esposti.
Questo comportamento è utile quando si pensa che l'elemento appena separato dalla pagina debba servire successivamente e quando non si vogliono perdere informazioni e comportamenti già definiti in precedenza.
Ajax
Come tutti gli altri aspetti, anche il componente Ajax presenta delle novità.
La versione 1.4 permette di serializzare i parametri da inviare al server sotto forma di vettore utilizzando la sintassi utilizzata da PHP e da Ruby on Rails (pagina.php?ids[]=1&ids[]=2
). Questo comportamento è ovviamente disattivabile agendo sulla variabile jQuery.ajaxSettings.traditional
.
Oltre a questo, ora il client è in grado di identificare la response sulla base del content-type e agire di conseguenza: creare un JSON nel caso di application/json
o eseguire lo script nel caso di application/x javascript
o text/javascript
. Anche questo comportamento può essere limitato utilizzando la proprietà dataType
.
In caso di parsing di JSON la nuova versione utilizza, se disponibili, la funzione nativa JSON.parse
presente nei browser più recenti. Nei browser che implementano già l'HTML 5, inoltre, è già inclusa la serializzazione delle nuove tipologie di campi <input>
.
La novità secondo me più rilevante, però, riguarda la possibilità di personalizzare lo scope di esecuzione delle funzioni di callback utilizzando la proprietà context
. Ecco un breve esempio di quest'ultima funzionalità:
var o = {
name: “Alberto”
}
$.ajax({
[...],
context: o,
success: function() {
alert(this.name);
}
}
Altre funzionalità di interesse inferiore sono state inserite sempre nella componente Ajax della libreria; per chi volesse informarsi maggiormente suggerisco, come al solito, di collegarsi al sito ufficiale di jQuery.
Core e traversing
Costruire codice con jQuery
Novità anche dal fronte core nella gestione globale degli oggetti jQuery.
Per costruire un nuovo frammento DOM, oltre alla struttura classica che accetta una stringa HTML, con la nuova versione possiamo utilizzare un JSON per definire le varie proprietà del nuovo oggetto. I due frammenti di codice seguenti sono equivalenti:
jQuery(“<div/>", {
id:"testDiv",
css: {
height: “50px",
width: “50px",
backgroundColor: “red"
},
click: function() {
$(this).css(“backgroundColor", “blue");
}
}).appendTo(“body");
jQuery(“<div id='testDiv' style='height:50px;width:50px;background-color:red'></div>")
.click(function() { $(this).css(“backgroundColor", “blue"); })
.appendTo(“body");
In questa nuova versione sono stati aggiunti anche due nuovi metodi first()
e last()
che ritornano rispettivamente il primo e l'ultimo elemento incapsulato in un oggetto jQuery. Oltre a questi sono stati modificati i metodi eq
e get
che ora accettano indici negativi per selezionare gli elementi partendo dalla fine del vettore.
Altre novità
Il nuovo metodo has()
permette di sapere se un determinato oggetto jQuery incapsula al suo interno un particolare elemento. Questo metodo è il corrispettivo del selettore has()
utilizzato proprio per ottenere elementi della pagina sulla base del contenuto HTML degli stessi.
Come per la componente Ajax, anche il Core presenta aggiornamenti di lieve importanza che non verranno trattati in questo articolo. Per i più curiosi suggerisco sempre la lettura della documentazione ufficiale.
Eventi jQuery.proxy per controllare gli scope
Tra tutte le modifiche della nuova versione credo che questa sia la più attesa soprattutto perché colma una delle principali lacune che le versioni precedenti di jQuery avevano, ovvero un controllo migliore dello scope delle funzioni callback.
Nella nuova versione è stato introdotto un nuovo metodo per l'oggetto core che permette di personalizzare l'ambiente di esecuzione di una funzione. Il metodo riceve due parametri: un oggetto e il nome di un metodo dello stesso e ritorna una funzione che permette di eseguire il metodo definito senza preoccuparsi del valore della variabile this
. L'esempio riportato da Resig è molto chiaro:
var obj = {
name: "John",
test: function() {
alert( this.name );
$("#test").unbind("click", obj.test);
}
};
$("#test").click( jQuery.proxy( obj, "test" ) );
Cliccando sull'elemento #test
verrà invocato il metodo test
il quale potrà accedere, visto che è stato forzato lo scope grazie a jQuery.proxy
, al proprio membro name
direttamente.
Altre novità per gli eventi
Oltre alla possibilità di controllare lo scope, la release 1.4 di jQuery presenta altre novità riguardanti la gestione degli eventi.
Utilizzando il metodo bind
sarà possibile assegnare più callback per lo stesso elemento:
$(“#div”).bind({
click: function() {
alert(“clicked”);
}, mouseover: function() {
alert(“mouseover”);
}
});
Dal punto di vista dei live events, inoltre, sono stati armonizzati tutti i metodi (eccetto ready
e i deprecati focus
e blur
– utilizzabili con focusin
e focusout
) permettendone l'utilizzo tramite la funzione live()
e non solo come binding statico. Ulteriori novità riguardanti gli eventi sono presenti nella documentazione ufficiale.
Animazioni
Grande novità anche dal fronte animazioni. Nelle versioni precedenti a quella attuale, il metodo animate
accettava una lista di proprietà e del relativo valore finale da animare. Il tutto funzionava senza problemi; l'unica mancanza era data dal fatto che non era possibile personalizzare ciascuna delle precedenti proprietà con un tipo di animazione differente dalle altre.
Con la release 1.4 questo diventa possibile: al posto del semplice valore finale è possibile passare (all'interno di un vettore) la stringa identificatrice della tipologia di effetto da applicare alla proprietà.
Come al solito ecco l'esempio chiarificatore che genera un “palleggio” di un div:
$(“#div”).animate({
left: 600,
top: [500, 'easeOutBounce']
})
Un'ulteriore novità in questo componente riguarda il metodo delay()
che permette di fermare l'esecuzione di una coda di chiamate. Il metodo in realtà non riguarda propriamente solo le animazioni, ma viene inserito in questo punto perché gli unici metodi che potrebbero richiedere un intervento bloccante di questo tipo sono le animazioni. Grazie a questo metodo non è necessario utilizzare il confusionario setTimeout()
:
$(“#div”).slideDown().delay(500).slideUp();
Aggiornamenti secondari
Sono stati aggiunti ulteriori metodi nel componente traversing (nextUntil()
, prevUntil()
, parentsUntil()
) per ottenere liste di elementi precedenti o successivi ad un determinato nodo ed è stato riscritto il metodo index()
per migliorarne la comprensione e l'utilizzo (nelle versioni precedenti era effettivamente poco intuitivo).
Nuovi metodi di introspezione sono stati implementati nell'oggetto jQuery come ad esempio isEmptyObject()
(per sapere se l'oggetto non ha proprietà associate) e isPlainObject()
(per sapere se l'oggetto è un semplice literal o qualcosa di più complesso). jQuery.noop()
invece è un riferimento ad una funzione vuota che può essere utilizzata quando è necessario disporre di callback che non eseguono praticamente codice.
Retrocompatibilità: nuove possibilità e problemi
Qualsiasi rilascio di librerie software può presentare problemi di retrocompatibilità con le versioni precedenti della medesima.
Per utilizzare gli script realizzati con la versione precedente di jQuery sono necessarie alcune
accortezze e modifiche per integrare al meglio il vecchio codice con la 1.4. Le modifiche principali riguardano la modifica del comportamento di alcuni metodi e del loro valore ritornato.
Un ottimo elenco dal quale reperire le informazioni necessarie e per sapere se e quali modifiche sono necessarie ai propri script o plugin è presente a questo indirizzo: http://jquery14.com/day-01#backwards. Il team di sviluppo ha tra l'altro rilasciato un apposito plugin per risolvere al meglio questi problemi. Si può scaricare dalla sezione del sito che abbiamo linkato.