La classe DataGrid, che abbiamo definito nella lezione precedente, è definita da una semplice funzione e dalla modifica dell'oggetto prototype associato ad essa. Ovviamente per poter utilizzare questo approccio è necessario prima di tutto definire il costruttore e successivamente i metodi, in quanto l'oggetto DataGrid.prototype
esiste solo successivamente alla definizione della funzione DataGrid
.
Il costruttore non fa altro che impostare alcune proprietà private della classe in base ai parametri passati e a istanziare il vettore _selectedIndex
che conterrà gli indici delle righe selezionate.
Il metodo più complesso è render il quale costruisce gli oggetti DOM che rappresentano la struttura della tabella ed appende questi oggetti all'elemento DOM ricevuto come parametro.
Il punto critico di questo metodo è l'assegnazione a ciascuna riga della tabella (tr
) di tre callback per altrettanti eventi (onmouseover
, onmouseout
, onclick
). A queste funzioni callback viene forzato lo scope tramite la funzione setScope
, alla quale vengono passati alcuni parametri aggiuntivi: nel nostro caso un riferimento all'oggetto tr
stesso e l'indice della riga selezionata.
Successivamente vengono definite queste funzioni callback, che modificarno l'aspetto grafico della tabella e, nel caso di _onclick
, demandano le funzionalità a _onselect
o a _ondeselect
in base al fatto che la riga sulla quale l'utente ha cliccato sia già stata selezionata o meno (lo capiamo controllando che l'indice i sia presente o meno all'interno dell'oggetto _selectedIndex
).Queste due funzioni a loro volta salvano o eliminano appunto da questa cache locale la riga selezionata.
Gli ultimi due metodi sono quelli pubblici (non presentano l'underscore iniziale), che forniscono all'utilizzatore di questa classe un'interfaccia comoda per interagire e ottenere informazioni riguardo la griglia.
Oltre a questa classe implementiamo altri metodi di utilità per gli oggetti Function
e Array
:
<script type="text/javascript">
Function.prototype.setScope = function(obj) {
var method = this;
var arg = [];
for(var i = 1; i < arguments.length; i++) arg.push(arguments[i]);
temp = function() {
return method.apply(obj, arg);
};
return temp;
}
Array.prototype.exists = function(value) {
for(var i = 0; i<this.length; i++) if(this[i] == value) return true;
return false;
}
Array.prototype.remove = function(value) {
for(var i = 0; i<this.length; i++) if(this[i] == value) this.splice(i,1);
}
</script>
Il metodo setScope
è la versione leggermente modificata della funzione vista in precedenza: questa richiama la funzione passando anche un numero non definito di argomenti passati alla funzione setScope
. Il ciclo for iniza da 1 e non da 0 proprio per "scartare" il primo argomento che rappresenta lo scope e non un parametro aggiuntivo.
Sono stati aggiunti anche due metodi di utilità all'oggetto implicito Array
per ricercare se un elemento è già presente al suo interno e per eliminarlo.
Il funzionamento della griglia è semplicissimo:
<script type="text/javascript">
var grid;
window.onload = function() {
grid = new DataGrid(["FirstName", "LastName", "Age"],
[
["Luca","Luchi",32],
["Marco","Marchi",42],
["Bruno","Bruni",23]
]);
grid.render(document.getElementsByTagName("div")[0]);
}
</script>
<div></div>
<button onclick="alert(grid.getSelectedData())">GetSelecteData</button>
<button onclick="alert(grid.getSelectedIndex())">GetSelecteIndex</button>
Oltre alla semplice creazione della griglia e il suo render all'interno del <div>
, sono stati predisposti due bottoni per verificare l'effettivo funzionamento delle API della classe DataGrid.
L'esempio, come al solito, è perfettibile, sia sotto il profilo della funzionalità, sia nell'aspetto, ma dovrebbe essere sufficiente a mostrare la potenza dell'uso dei prototipi.