====== jQuery.callback ======
JQuery.callback è un plugin per il framework jQuery che permette la modifica del comportamento delle funzioni assegnate come callback per eventi relativi alla GUI o alle richieste AJAX. Il progetto è hostato su [[http://code.google.com/p/jquerycallback/|google code]]. \\
\\
Il suo utilizzo non è banale e scontato per cui cerchiamo di capire a cosa può servire questo plugin:\\
\\
JQuery è una libreria event-oriented ovvero che permette di controllare i comportamenti degli utenti tramite appositi listeners, ovvero funzioni che vengono invocate automaticamente allo scatenarsi di un qualsiasi evento (sia dal punto di vista dell'interfaccia utente, sia dal punto di vista delle richiesta AJAX asincrone). Questi listeners vengono invocati con dei parametri particolari che rappresentano nello specifico l'evento o i dati ricevuti. \\
Iniziando a utilizzare questo approccio ad eventi però, ci si accorge di due particolari mancanze. Innanzitutto è impossibile passare altri parametri oltre a quelli di default decisi dal framework. \\
Immaginiamo questo contesto:
function init() {
var nome = "pippo"; //variabile importante richiesta nella callback
$.get(url, myCallback);
}
function myCallback(data) {
alert(nome); //non ho modo di recuperarlo - stamperà undefined
}
Le soluzioni a questo problema sono principalmente tre ma non sono propriamente eleganti nè "pulite":
/* soluzione 1 -> callback inline */
function init() {
var nome = "pippo";
$.get(url, function() {
alert(nome); //grazie alla scope-chain la variabile è disponibile anche nella callback
});
}
/* soluzione 2 -> approccio globale */
var nome;
function init() {
nome = "pippo";
$.get(url, myCallback);
}
function myCallback(data) {
alert(nome); //essendo globale, posso accedervi da ovunque
}
/* soluzione 3 -> binding forzato */
function init() {
var nome = "pippo";
$.get(url, (function(nome) { //piccolo trucco per creare una scope-chain
return function(data) {
alert(nome);
})(nome)
);
}
La soluzione che preferisco è la terza, ma ammetto che la miglior cosa sarebbe quella di avere un costrutto per rendere più facile la creazione di queste funzioni "dinamiche". \\
Ovviamente in JQuery questo manca; cosa che invece non manca in altri framework (prototypeJS presenta il metodo [[http://www.prototypejs.org/api/function/bind|bind]], ExtJS il metodo [[http://extjs.com/deploy/dev/docs/?class=Function&member=createCallback|createCallback]], MooTools il metodo [[http://mootools.net/docs/Native/Function#Function:pass|pass]]).\\
L'altra mancanza invece riguarda lo scope di invocazione dei listeners e la possibilità di impostare non funzioni globali ma metodi di oggetti che fanno riferimento all'istanza corrente tramite il costrutto this. \\
Contestualizziamo il problema:
var oggetto = {
nome: 'pippo',
stampaNome: function() {
alert(this.nome);
}
}
function init() {
$.get(url, oggetto.stampaNome); //stamperà undefined
}
Anche in questo caso la soluzione è quella di creare una nuova funzione modificandone la scope-chain:
var oggetto = {
nome: 'pippo',
stampaNome: function() {
alert(this.nome);
},
getStampaNome: function(scope) {
return function() {
scope.stampaNome.call(scope, scope.nome);
}
}
}
function init() {
$.get(url, oggetto.getStampaNome(oggetto));
}
Anche in questo caso, nonostante l'efficacia della soluzione, essa è davvero scomoda e poco manutenibile, soprattutto perchè il numero delle funzioni necessarie aumenta notevolmente. \\
Come per il problema precedente, anche questo viene risolto in maniera elegante da altri framework Javascript per esempio ExtJS con il metodo [[http://extjs.com/deploy/dev/docs/?class=Function&member=createDelegate|createDelegate]] o MooTools con il metodo [[http://mootools.net/docs/Native/Function#Function:create|create]].\\
\\
Grazie invece al plugin jQuery.callback è possibile sia assegnare parametri particolari alle funzioni di callback (oltre a quelli di default del framework) sia di modificarne lo scope di esecuzione.\\
\\
Maggiori informazioni sull'utilizzo in concreto del plugin sono disponibili, insieme ovviamente ai sorgenti, sulla piattaforma [[http://code.google.com/p/jquerycallback/wiki/Usage|google code]]