Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

MooTools: usare Events e Options

Impariamo ad usare e gestire due fondamentali oggetti del noto framework Javascript
Impariamo ad usare e gestire due fondamentali oggetti del noto framework Javascript
Link copiato negli appunti

Come ho già detto nei precedenti articoli, Introduzione a MooTools e Le basi di MooTools, MooTools è un framework completamente orientato agli oggetti che permette di creare meccanismi di ereditarietà complessi sfruttando i potenti metodi nativi del costruttore Class. In questo articolo vedremo come creare un meccanismo di ereditarietà utilizzando due dei tre oggetti extra disponibili per Class: l'oggetto Options e l'oggetto Events.

OOP: superclassi e sottoclassi

Un'applicazione orientata agli oggetti definisce due grandi tipologie di costruttori: le superclassi e le sottoclassi.

Le prime sono gli oggetti "genitori" delle seconde, sono generalmente il più astratte possibile e contengono metodi "core" che potranno essere utilizzati dalle relative sottoclassi. Le sottoclassi ereditano tutti i metodi della classe "genitore" e in più possono ridefinirli con nuove funzionalità.

Vediamo brevemente un esempio di superclasse e sottoclasse in MooTools:

var SuperClass = new Class({
initialize: function() {
// inizializzazione
}
});

var SubClass = SuperClass.extend({
// metodi di SubClass
});

Grazie al metodo EXTEND tutti i metodi della classe SuperClass vengono ereditati dalla classe SubClass (per una trattazione completa dell'oggetto Class e dei suoi metodi rimando all'articolo Le basi di MooTools).

Con MooTools è possibile fare molto di più rispetto ad un classico meccanismo di ereditarietà. Ad esempio, è possibile estendere le caratteristiche degli oggetti Class con funzionalità extra tramite gli oggetti Options, Events e Chain (Class.Extras.js).

Questi possono essere implementati in qualsiasi oggetto di tipo Class con l'ausilio del metodo IMPLEMENT:

myClass.implement(new Chain, new Events, new Options);

Gli stessi sviluppatori di MooTools implementano questi oggetti extra in diversi altri oggetti importanti del framework, come Fx, XHR e Ajax.

L'oggetto Options

Con l'oggetto Options implementato possiamo decentralizzare i dati di un oggetto Class nelle opzioni del costruttore, o meglio, nella sua proprietà this.options. Vediamo subito un esempio. Assumiamo di avere un oggetto di tipo Class chiamato Car che rappresenta una macchina. Prima dell'inizializzazione dichiariamo una proprietà chiamata options e impostiamo a tutte le proprietà i nostri valori di default:

var Car = new Class({

options: {
numeroPorte: 4,
alimentazione: 'diesel'
},

initialize: function(name, options) {
this.name = name;
this.setOptions(options);
}
});

I nostri oggetti di tipo Car avranno due opzioni di default: il numero delle porte della macchina (di default 4) e il tipo di alimentazione (di default 'diesel'). Ricordo che il precedente esempio non funzionerà se non scriviamo la seguente riga di codice:

Car.implement(new Options);

Nell'initialize facciamo uso del metodo setOptions ereditato dall'oggetto Options, con il quale è possibile settare la proprietà this.options di Car, le cui proprietà passate al costruttore sovrascriveranno quelle di default:

var myCar = new Car('myCar', {alimentazione: 'benzina', numeroPorte:3});

// 'benzina'
alert(myCar.options.alimentazione);

Questa tecnica di decentralizzazione apporta notevoli vantaggi:

  • la possibilità di definire parametri di default modificabili dall'utente all'inizializzazione del costruttore, in modo da personalizzare istanze aventi lo stesso costruttore;
  • una sintassi molto più elegante e flessibile. Pensate se Car avesse dieci opzioni e, invece di dichiararle nella proprietà options, ovvero:

var myCar = new Car('myCar', {
opt1 = 'opt1',
opt2 = 'opt2',
opt3 = 'opt3',
opt4 = 'opt4',
});

avessimo dovuto scrivere:

var myCar = new Car('myCar', 'opt1', 'opt2', 'opt3', 'opt4', ...);

Sarebbe un totale fallimento se l'utente saltasse la dichiarazione di un parametro.

Il mio consiglio è di includere nelle opzioni tutte le proprietà 'secondarie' che personalizzano il nostro costruttore e di lasciare come normali parametri dati principali come l'id di un elemento e cosi via.

Come vedremo, oltre alle proprietà, è possibile includere nelle opzioni anche i metodi, che rappresentano gli eventi da richiamare in determinati momenti all'interno del costruttore.

L'oggetto Events

Se un oggetto Class implementa l'oggetto Events, assume la capacità di settare, azionare e rimuovere eventi.

Un evento viene inizializzato passando alla proprietà options vista in precedenza un metodo che inizia con 'on' seguito da una lettera maiuscola:

options: {
numeroPorte: 4,
alimentazione: 'diesel',
onStart: function() {
alert('Macchina accesa');
},
onFinish: function() {
alert('Macchina spenta');
}
}

In questo caso abbiamo impostato due eventi, onStart e onFinish, le cui funzioni di default sono quelle di avvisare che la macchina viene rispettivamente accesa o spenta. Vediamo ora come azionarli:

Car.implement({
avvio: function() {
this.fireEvent('onStart');
},

spegnimento: function() {
this.fireEvent('onFinish');
}
});

Se richiamiamo il metodo avvio su di un oggetto di tipo Class, l'evento onStart verrà azionato e verrà visualizzato il messaggio:

// alert 'Macchina accesa'
myCar.avvio();

Possiamo personalizzare l'azione dell'evento onStart passando alla proprietà options un nuovo metodo onStart che sovrascriverà le funzionalità di quello di default:

options: {
onStart: function() {
$('myBox').setHTML('Avvio');
}
}

Ora, se richiamiamo myCar.avvio, verrà inserito il testo 'Avvio' nell'elemento con id 'myBox'.

L'oggetto Events aggiunge al nostro costruttore anche il metodo removeEvent, che funziona come fireEvent ma rimuove l'evento invece che azionarlo, ed il metodo addEvent che aggiunge un evento allo stack degli eventi dell'istanza in considerazione.

Un'altra funzionalità aggiuntiva dell'oggetto Events molto importante è che è possibile passare ai metodi che rappresentano gli eventi uno o più parametri. Nel secondo caso è necessario passare un array di argomenti:

onStart(property) {
alert(property);
}

// azioniamolo...
this.fireEvent('onStart', this.genericproperty);

Meccanismo di ereditarietà

Ora che abbiamo visto come funziona il meccanismo di creazione e di gestione degli oggetti di tipo Class, vediamo come estendere l'oggetto precedentemente creato, Car, con funzionalità nuove rappresentate da un nuovo oggetto chiamato SuperCar:

var Car = new Class({

options: {
numeroPorte: 4,
alimentazione: 'diesel',
onStart: function() {
alert('Macchina accesa');
},
onFinish: function() {
alert('Macchina spenta');
}
},

initialize: function(name, options) {
this.name = name;
this.setOptions(options);
},

avvio: function() {
this.fireEvent('onStart');
},

spegnimento: function() {
this.fireEvent('onFinish');
}
});

Car.implement(new Events, new Options);

var SuperCar = Car.extend({

options: {
numeroMarce: 6,
velMax: 320,
onChange: function(num) {
alert('Marcia aumentata: sei in ' + num);
},
onError: function(num) {
alert('Non puoi inserire più di ' + num + ' marce');
}
},

initialize: function(name, options) {
this.parent(name, options);
this.marcia = 0;
},

aumenta: function() {
if(this.marcia < this.options.numeroMarce) {
this.marcia ++;
this.fireEvent('onChange', this.marcia);
}
else this.fireEvent('onError', this.options.numeroMarce);

}

});

L'oggetto SuperCar eredita tutti i metodi e le opzioni dell'oggetto Car, in più, definisce tre nuove opzioni:

  • l'evento onChange che scatta quando aumentiamo la marcia;
  • l'evento onError che dice che non è possibile inserire un numero di marce superiore a quelle dichiarate nell'opzione numeroMarce;
  • la velocità massima.

Ho creato questo esempio per mostrare tutta la potenza e la flessibilità degli oggetti Class. Ovviamente questo non è tutto quello che è possibile fare, basta dare un'occhiata ai meccanismi degli effetti Fx per comprenderne le infinite potenzialità.


Ti consigliamo anche