Uno degli effetti più utili e gradevoli da implementare su un sito sono i menu a cascata (drop-down menu in inglese). Siamo abituati a vedere menu a cascata ovunque, e la maggior parte dei linguaggi di programmazione permette di crearli e gestirli con poche istruzioni. Per quanto possa sembrare strano, questo non vale per l'HTML: sebbene ogni sito che si rispetti utilizzi qualche effetto grafico a cascata (o a scomparsa), dietro le quinte c'è spesso qualcuno che si è ingegnato per realizzarlo.

Oggi vedremo come implementare un menu a cascata con poche righe, utilizzando jQuery.

Teoria

La prima caratteristica di un menu a cascata è il timing, ovvero la necessità di rallentare l'apparizione del menu, per creare un piacevole effetto di comparsa e scomparsa (fadein e fadeout). Abbiamo già visto che gestire il delay in JavaScript non è affatto intuivo. Siccome jQuery è una libreria JavaScript, valgono esattamente le stesse limitazioni: non possiamo sfruttare un ciclo per eseguire le istruzione una di seguito all'altra, con tempi diversi, perché il browser le eseguirebbe sempre e comunque tutte assieme, alla fine del ciclo.

Un modo di aggirare il problema è usare la concatenazione di metodi diversi con la dot notation, ovvero

fai_questo(100).fai_quello() ;

Se il metodo fai_questo() prevede un certo ritardo nell'esecuzione, supponiamo di 100 ms (come scritto qui sopra), allora saremo sicuri che il metodo fai_quello() verrà eseguito in ritardo rispetto al primo (in questo caso dopo circa 100 ms). La tecnica si potrebbe applicare per creare effetti di scomparsa mediante le funzioni fadeOut() e fadeIn() di jQuery, ad esempio

$('#mio_menu').fadeOut(500).fadeIn(500) ;

la riga qui sopra non serve a nulla ma "funziona", perché fa scomparire l'elemento  mio_menu in mezzo secondo, e dopo un altro mezzo secondo lo fa riapparire. Far scomparire e apparire subito dopo un elemento è abbastanza inutile, però dimostra che la tecnica funziona, perché ci permette di eseguire le funzioni con il timing previsto. A questo punto potremo illuderci di scrivere un codice del genere

$('#menu_1').fadeOut(500).$('#menu_2').fadeOut(500) ;

ma questo non gira nemmeno! La dot notation permette di eseguire metodi solo sullo stesso oggetto, o per la precisione: sull'oggetto ritornato dal metodo precedente. Quindi non ha alcun senso applicare il metodo

$('#menu_2')

sull'oggetto

$('#menu_1').fadeOut(500)

La morale è che jQuery non permette di gestire il delay in modo diverso da JavaScript, ed è giusto che sia così: JavaScript sta “sotto” a jQuery, i limiti strutturali della libreria dipendono dalle fondamenta su cui è edificata, e non viceversa!

La soluzione corretta è quella di sfruttare quando già imparato nella gestione del delay in JavaScript e applicarlo alla funzioni di jQuery, ottenendo un gradevole effetto a scomparsa con poche righe. Passiamo quindi alla pratica.

Pratica

Consideriamo per semplicità un menu HTML realizzato con una tabella

<table>

<tr><td><a href="#" onclick="collapse(11,13);">Home</a></td></tr>

<tr id="row_11"><td><a href="#">Software</a></td></tr>

<tr id="row_12"><td><a href="#">Formazione</a></td></tr>

<tr id="row_13"><td><a href="#">Links</a></td></tr>

</table>

Immaginando di avere altre righe più sotto, del tipo row_21, row_22, row_23 ecc...

Useremo poi la funzione JavaScript

function collapse(n, tot) {

var t = 100 ;

menu_div = $('#' + 'row_' + n) ;

if (menu_div.is(":visible") ) {

for (i = n ; i <= tot ; i++)

$('#row_' + i).fadeOut ( t*(i-n) ) ;

} else {

for (i = n ; i <= tot ; i++)

$('#row_' + i).fadeIn ( 3*t*(i-n) ) ;

}

};

Ecco finalmente un menu a cascata funzionante! Abbiamo aggirato il problema del delay assegnando tempi diversi alle diverse righe della tabella. Durante il fadeOut() la prima riga avrà delay = 0, la seconda delay = 100, la terza delay = 200. Vale lo stesso discorso per il fadeIn(), a parte il fattore 3 che abbiamo aggiunto per rallentare la comparsa del menu: spesso è più piacevole vedere scomparire quasi subito ciò che non serve, e veder apparire un po' più lentamente (ma non troppo) ciò che si serve.