Una delle caratteristiche più interessanti di jQuery è la sua estensibilità mediante plugin. Gli ideatori di jQuery hanno giustamente pensato che è praticamente impossibile creare una libreria che soddisfi tutte le esigenze degli sviluppatori. Quindi hanno lasciato aperta una porta per estendere le funzionalità di base della libreria. Questa porta è l'alias fn
che non è altro che una scorciatoia per accedere alla proprietà prototype
di ciascun oggetto del set di jQuery.
In jQuery, tutti i componenti di una catena di selettori (per esempio elementi HTML) sono oggetti. In JavaScript quando si crea un oggetto si crea anche una proprietà prototype
che serve sia per aggiungere membri all'oggetto sia per gestirne l'ereditarietà . Ogni volta che jQuery definisce un metodo per un elemento del suo set, usa l'alias fn
. Questo vale sia per i metodi già presenti nella libreria, sia per quelli che verranno definiti in un plugin.
La sintassi è la seguente:
(function($) { $.fn.plugin = function() { // qui il codice del plugin }; })(jQuery);
Come si può notare, si tratta in sostanza di una funzione self-executing (auto-eseguente) che vive all'interno del namespace globale di jQuery. Al suo interno troviamo l'accesso all'alias fn
seguito dal nome del plugin, che è in sostanza una funzione a sua volta. Una volta definito il plugin in questo modo, possiamo richiamarlo su qualsiasi elemento del set di jQuery, così:
$('#test').plugin();
Noterete che non c'è più alcuna differenza con l'invocazione di un normale metodo della libreria. Facciamo un esempio: si supponga di voler creare un metodo che testi se un elemento è vuoto, ossia se non contenga né spazi né nodi. Ecco come fare:
(function($) { $.fn.isEmpty = function() { if(this[0].firstChild == null) { return true; } else { return false; } }; })(jQuery);
La parola chiave this
in un plugin si riferisce sempre all'oggetto su cui il plugin andrà ad essere applicato. Nel nostro caso specifico tramite la notazione a parentesi quadre abbiamo semplicemente avuto accesso alla proprietà firstChild
di un nodo, cosa impossibile all'interno di un normale set di jQuery.
Il nostro esempio è semplicissimo: una funzione senza argomenti. E se volessimo aggiungere argomenti, o, per meglio dire, opzioni da passare al nostro plugin? All'inizio pensavo che la cosa più semplice da fare fosse quella di passare alla funzione degli argomenti all'interno della definizione della funzione. In realtà questo metodo è sconsigliato quando un plugin ha svariate opzioni, data la natura molto "permissiva" di JavaScript nel trattare l'ordine degli argomenti (o parametri).
Si consiglia invece di usare un oggetto le cui proprietà saranno le opzioni del nostro plugin. Per esempio, decidiamo di creare un plugin per gestire i link AJAX, ossia quelle call-to-action che lanciano una richiesta AJAX. Ecco un'ipotesi:
(function($) { $.fn.ajaxLink = function(options) { options.method = options.method || 'GET'; options.url = options.url || this.attr('href'); options.type = options.type || 'text'; options.data = options.data || null; options.callback = options.callback || function() {}; this.click(function(e) { $.ajax({ type: options.method, url: options.url, dataType: options.type, data: options.data, success: options.callback }); e.preventDefault(); }); }; })(jQuery);
Ed ecco un esempio pratico:
$('#call a:first-child').ajaxLink({ url: 'ajax.php', type: 'html', callback: function(html) { alert(html); } });
Come si può notare, se non si specificano tutte le opzioni, allora verranno utilizzati i valori di default specificati nel nostro oggetto. Questo si rivela molto comodo e garantisce una notevole flessibilità .