- Introduzione al framework MooTools: supporto, selettori e array -
 
COSA SERVE PER QUESTO TUTORIAL
Chiedi sul FORUM | Glossario una conoscenza basica di JavaScript
MooTools: capire i concetti fondamentali

I FRAMEWORK JAVASCRIPT E MOOTOOLS
A cosa servono i framework JavaScript e quali sono i loro limiti.

Chiunque abbia avuto a che fare con JavaScript ha certamente inizialmente riscontrato delle difficoltà, non tanto dovute al linguaggio in sé, estremamente semplice, intuitivo e versatile, quanto per via del DOM (Document Object Model), ovvero tutti i vari oggetti di uso comune come document, window e così via. Le problematiche sono principalmente dovute alle differenti implementazioni dei vari browser, che supportano o meno una funzionalità, oppure semplicemente richiedono una procedura differente per ottenere il medesimo risultato. Ebbene, per colmare queste differenze sono nati vari framework per JavaScript, ovvero dei semplici script che offrono una serie di classi e funzioni che permettono di svolgere un determinato compito senza doversi preoccupare di quale sia il browser in uso.
In questo caso ci occuperemo di MooTools, un ottimo framework che, prima cosa da prendere in considerazione nella scelta, ha un ottimo supporto per i browser, arrivando a coprire la quasi totalità degli utenti attualmente circolanti sul web. MooTools supporta i seguenti browser:

  • Internet Explorer (versione 6 e successive);
  • Firefox (versione 2 e successive);
  • Opera (versione 9 e successive);
  • Safari (versioni 2 e successive);

Ovviamente questi dati non indicano il supporto della sola applicazione ma del motore di rendering che vi sta alla base, ciò significa che tutti i browser che si basano su Gecko (come Camino), su WebKit (Google Chrome e Konqueror) o quello di IE (Avant Browser e altri) sono supportati pienamente, a parità di versioni.
I framework non si limitano però solamente a rendere più facili operazioni comuni a più browser, ma permettono anche di ottenere risultati grafici di elevatissimo livello con uno sforzo davvero minimo. Inoltre MooTools potenzia il linguaggio stesso simulando costrutti non presenti in JavaScript come i for-each (un for che cicla ogni oggetto appartenente ad un array), le classi e altri strumenti che si riveleranno sicuramente utili.
L'ultimo aspetto importante da tener presente prima di passare al codice è quello del peso: MooTools si definisce un framework ultra-leggero, soprattutto grazie alla possibilità di creare uno script contenente esclusivamente le funzionalità desiderate del framework direttamente dal sito, il che evita di portarsi dietro inutili dipendenze. Inoltre grazie ad avanzati tool di "compressione" degli script è possibile ridurre drasticamente il peso del file JS eliminando commenti, spazi inutili e accorciando i nomi delle variabili, ovvero sacrificando la leggibilità in favore dell'efficienza (in ogni caso per la fase di testing offline ci si può tranquillamente servire dello script originale). Alla versione 1.2 il peso minimo che il MooTools riesce ad ottenere sono 65 Kb, un risultato più che soddisfacente per lo stato della rete attuale.

IL SELETTORE $
Il primo script MooTools e il selettore per ID.

La prima volta che si entra a contatto con la sintassi di MooTools in genere si rimane piuttosto spiazzati, poiché risulta molto diverso dal codice JavaScript che si è abituati a vedere. Uno dei fattori principali che crea questa confusione è il simbolo del dollaro ($) che ricorre di frequente. $ in realtà non è altro che il nome di una funzione che restituisce l'elemento con l'ID specificato vediamo un esempio:


<html>
    <head>
        <script type="text/javascript" language="javascript" 
            src="http://mootools.net/download/get/mootools-1.2.2-core-yc.js"></script>
    </head>
    <body>
        <div id="mioDiv" lang="it">Testo</div>
        <div id="altroDiv">Altro Testo</div>
        <script type="text/javascript" language="javascript">
            alert($("mioDiv").lang);
        </script>
    </body>
</html>


Per prima cosa vediamo all'interno dell'elemento HEAD un riferimento allo script contenente l'intero core (ovvero i componenti principali) di MooTools, in questo caso la versione 1.2.2 compressa tramite il compressore YUI (di Yahoo). Come già detto è meglio non servirsi dello script offerto da mootools.net, si consiglia di crearne uno personalizzato, più leggero possibile da ospitare sul proprio sito.
Nel corpo abbiamo un semplice DIV dotato di un ID e un attributo LANG. Subito dopo abbiamo un semplice script che non fa altro che mostrare una alert con la lingua dell'elemento con ID mioDiv. Fin da ora è bene capire che quando un framework offre delle alternative alla maniera tradizionale di fare una cosa c'è una ragione e questo caso non fa eccezione: utilizzare document.getElementById() non sarebbe stato errato ma avrebbe impedito a MooTools di estendere l'elemento in questione, ovvero di aggiungere una serie di metodi previsti per un elemento. Tra questi vi è ad esempio destroy(), che come si può intuire serve per eliminare l'elemento in questione. Avremmo dunque potuto scrivere al posto della alert:

$("mioDiv").destroy();

Ma non:

document.getElementById("mioDiv").destroy();

In quanto MooTools non avrebbe potuto agire sull'oggetto in questione aggiungendo i metodi necessari, tra cui destroy(). Quindi per prima cosa è importante imparare che bisogna usare tutti gli strumenti che il framework offre per poterne sfruttare appieno le potenzialità.
La funzione $() (spesso chiamata anche selettore) può ricevere come parametro, in alternativa alla stringa contenente l'ID di un elemento, un elemento vero e proprio, quindi anche document, document.body e così via, permettendo in questo modo di usufruire dei metodi avanzati anche su essi, senza passare per forza dall'ID.

I SELETTORI AVANZATI
Selezionare più elementi e applicare filtri avanzati.

MooTools come selettori offre però molto di più della semplice funzione $(): esistono infatti i metodi getElement, getElements e la funzione $$. getElement e getElements si applicano ad un elemento già a disposizione e sono pressoché identici se non per il fatto che getElement restituisce il primo elemento che corrisponde ai criteri, mentre getElements restituisce un array contenente tutti gli elementi corrispondenti. Ad esempio

$(document.body).getElement("div").destroy();

distruggerà il primo DIV contenuto nel BODY, mentre:


var divs = $(document.body).getElements("div");
for (i=0;i < divs.length;i++)
    divs[i].destroy();

distruggerà tutti i DIV contenuti nel BODY. Se si desidera prendere tutti gli elementi che corrispondono ad un certo criterio nel documento, invece che servirsi ogni volta di $(document).getElements() ci si può servire dell'apposita funzione $$.
Finora abbiamo parlato di criteri, ma cosa è possibile specificare? I criteri sono i selettori CSS (ma più potenti rispetto a quelli comunemente supportati dai browser),  vediamo alcuni esempi:

  • $$("*") seleziona tutti gli elementi;
  • $$("div") seleziona tutti i DIV;
  • $$(".nomeClasse") seleziona tutti gli elementi dotati della classe nomeClasse;
  • $$("#identificativo") seleziona tutti gli elementi con ID identificativo (in realtà uno solamente);

Sono supportate anche diverse pseudo-classi:

  • $$(".casa:enabled") seleziona tutti gli elementi con classe casa e che siano abilitati;
  • $$("p:empty") seleziona tutti i P che siano vuoti;
  • $$("div:contains(\"AAC\")") seleziona tutti i DIV contenenti il testo "AAC";
  • $$("#footer:nth-child(2n)") seleziona tutti i figli pari dell'elemento con ID footer;
  • $$("#footer:nth-child(2n+1)") seleziona tutti i figli dispari dell'elemento con ID footer;
  • $$("#footer:nth-child(3n)") seleziona tutti i figli multipli di 3 dell'elemento con ID footer;
  • $$("#footer:even") seleziona tutti i figli pari dell'elemento con ID footer;
  • $$("#footer:odd") seleziona tutti i figli dispari dell'elemento con ID footer;
  • $$("#footer:first-child") seleziona il primo figlio dell'elemento con ID footer;
  • $$("#footer:last-child") seleziona l'ultimo figlio dell'elemento con ID footer;
  • $$("#footer:only-child") seleziona l'unico figlio dell'elemento con ID footer;

Sono infine supportate le condizioni sugli attributi:

  • $$("input:[type=button]") seleziona tutte i pulsanti;
  • $$("p[lang!=it]") seleziona tutti i P dove la lingua non è l'italiano;
  • $$("img[alt*=AAC]") seleziona tutte le immagini che nel testo alternativo contengono "AAC";
  • $$("a[href^=https]") seleziona i link che puntano ad URL che iniziano per "https";
  • $$("a[href$=mpg]") seleziona i link che puntano ad URL che finiscono in "mpg";
  • $$("a[href$=mpg]") seleziona i link che puntano ad URL che finiscono in "mpg";
  • $$("*[class~=secondario]") seleziona tutti gli elementi che hanno la classe secondario (~= indica "contiene la stringa in una lista separata da spazi");
  • $$("*[title|=12]") seleziona tutti gli elementi che contengono nell'attributo title il numero 12 (|= indica "contiene la stringa in una lista separata da trattini");
I CICLI EACH
Come funzionano each() e $each().

Vediamo infine il costrutto $each() e la funzione each() di un array di MooTools: essi permettono di agire con semplicità su un array senza dover dichiarare un contatore e servirsi di un classico ciclo for. Questo è utile anche per mettere a fuoco il secondo fattore che genera confusione in chi si avvicina per la prima volta a MooTools, ovvero l'uso massiccio di funzioni anonime. Vediamo come potremmo riscrivere il codice precedente che distruggeva tutti i DIV contenuti nel BODY:


$$("body div").each(function(divCurrent) {
        divCurrent.destroy();
    }
);

La funzione $$() abbiamo detto che restituisce un array di elementi, su questo array abbiamo chiamato il metodo each() che prende come parametro una funzione (che abbiamo deciso di specificare inline) la quale sarà eseguita per ogni elemento dell'array passandogli l'elemento in questione. La funzione non farà altro che invocare il metodo destroy() sull'elemento avuto come parametro. Se non dovesse essere chiaro il concetto di funzione anonima vediamo un suo equivalente con una funzione tradizionale:


function distruggiDiv(divCurrent) {
    divCurrent.destroy();
}

$$("body div").each(distruggiDiv);

In questo caso abbiamo creato una funzione con tanto di nome (distruggiDiv) e poi abbiamo invocato each() passandogli un riferimento alla funzione. Si noti il fatto che non vi sono le parentesi dopo distruggiDiv nel passare la funzione come parametro, se ci fossero la funzione verrebbe eseguita invece che essere passata come riferimento.
Vediamo ora potremmo scrivere lo stesso codice usando $each():


$each(function(divCurrent) {
        divCurrent.destroy();
    }, $$("body div")
);

La sintassi è quasi identica se non per il fatto che invece che richiamare il metodo each() dell'array restituito da $$() in questo caso usiamo la funzione $each(), passandogli come primo parametro la funzione da eseguire, e come secondo l'array degli elementi da distruggere.
Sia il metodo each() degli array che $each() possono ricevere un altro parametro, il cui valore sarà impostato come oggetto this nella funzione che deve essere eseguita, ma non approfondiremo ora questa funzionalità. Vediamo invece un'altra possibilità offerta da each() e $each(), ovvero quella di passare alla funzione da eseguire anche l'array su cui si sta ciclando e l'indice corrente:


$$("body div").each(function(divCurrent, intDivIndex, arrDivs) {
        arrDivs[intDivIndex].destroy();
        // divCurrent.destroy();
    }
);

Come si può notare abbiamo aggiunto due parametri alla funzione anonima, l'indice dell'elemento corrente (indDivIndex) e l'array su cui si sta lavorando (arrDivs). Il codice lascia intuire facilmente che invocare destroy() su arrDivs[intDivIndex] o sul parametro divCurrent è del tutto equivalente.

 

<< INDIETRO by VeNoM00