Colui che dice "io posso"
e colui che dice "io non posso"
hanno entrambi ugualmente ragione.

In questo tutoriale faremo un semplice menu verticale con jQuery ma che cattura l’attenzione del navigatore con l’aiuto di CSS e del plugin Easing per l’effetto a fisarmonica.
Come potete vedere in seguito dalla demo, il menu è diviso in quattro voci, ciascuna definita da un elemento LI posizionati all’interno dell’elenco principale UL:
<li class="menu"> <!-- costituisce ogni sezione del menu principale -->
<ul>
<!-- titolo della sezione che fa aprire il sotto menu -->
<li class="title"><a href="#">Categoria Firefox</a></li>
<li class="sub-menu">
<ul>
<li><a href="http://www.mainickweb.com/hack-css-per-firefox-opera-safari-e-internet-explorer/">Articolo 1</a></li>
<li><a href="http://www.mainickweb.com/firefox-3-le-caratteristiche/">Articolo 2</a></li>
</ul>
</li>
</ul>
</li>
Ogni voce del menu contiene un altro elenco UL, formato dalla voce del menu principale (li.title) e da un altro elenco UL che rappresenta il sotto menu (li.sub-menu).
All’interno dell’elemento li.title abbiamo un ancora a cui poi associamo un gestore di eventi jQuery che fa aprire il sotto menu corrispondente: il menu a discesa è nascosto di default tramite la proprietà css display: none.
Con uno stile accattivante, anche la più semplice idea può fare una grande differenza nell’attenzione del visitatore.
E’ importante fare particolare attenzione che il codice CSS sia valido e che funzioni bene in tutti i browser:
li.menu {
/* Voci dell'elenco principale */
width: 100%;
padding: 5px 0;
}
li.title a {
/* Voce del menu principale */
display: block;
position: relative;
width: 200px;
height: 34px;
padding: 10px 20px 0;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
background-color: #cc0000;
color: #ffffff;
font-family: BPreplay,Arial,Helvetica,sans-serif;
font-size: 21px;
overflow: hidden;
}
li.title a:hover {
background-color: #f40000;
text-decoration: none;
}
li.title a span {
/* Questo span agisce come parte finale della sezione title */
display: block;
position: absolute;
top: 0;
right: 0;
width: 4px;
height: 44px;
}
.sub-menu {
/* Sotto menu */
display: none;
width: 100%;
padding-top: 5px;
}
.sub-menu li {
/* Voci del sotto menu */
margin: 5px 0;
padding: 4px 18px;
border: 1px solid #40392c;
background-color: #2F2F2F;
color: #cccccc;
}
In primo luogo abbiamo bisogno di includere alcuni script nel documento HTML (questo codice va messo all’interno della sezione HEAD):
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript" src="jquery.easing.1.3.js"></script> <script type="text/javascript" src="script.js"></script>
Per prima cosa bisogna includere la libreria jQuery (in questo caso dai server di Google), poi il plugin Easing e infine il nostro file di script.
Come potete notare dalla demo, l’effetto che si ha nell’aprire un sotto menu è simile ad un rimbalzo. Questo risultato è ottenuto con l’aiuto del plugin Easing per jQuery: esso prevede una serie di effetti interessanti.
Ecco il codice del nostro file di script:
$(document).ready(function(){
/* Cambiare l'effetto da utilizzare */
$.easing.def = "easeOutBounce";
/* Associare una funzione all'evento click sul link */
$('li.title a').click(function(e){
/* Finding the drop down list that corresponds to the current section: */
var subMenu = $(this).parent().next();
/* Trovare il sotto menu che corrisponde alla voce cliccata */
$('.sub-menu').not(subMenu).slideUp('slow');
subMenu.stop(false,true).slideToggle('slow');
/* Prevenire l'evento predefinito (che sarebbe di seguire il collegamento) */
e.preventDefault();
})
});
Per prima cosa bisogna impostare l’effetto da utilizzare (easeOutBounce), e quindi associare una funzione da compiere per l’evento click sul link in li.title: si ottiene il corrispondente sotto menu (linea ) e lo si mostra (linea ), nascondendo tutti gli altri (linea ).
Il metodo slideToggle di jQuery controlla se l’elemento è già visibile sulla pagina, e decide se mostrarlo o nasconderlo: in questo modo, quando si fa click su una sezione del menu già aperta, essa viene semplicemente chiusa.
Dopo questo, usiamo e.preventDefault() per impedire al browser di seguire il collegamento (il comportamento normale per avere cliccato su un link).
Nel corso degli anni ho acquisito una vasta esperienza nella progettazione e realizzazione in ambito siti e applicazioni web, ma continuo ad approfondire le mie conoscenze e a sperimentare, per migliorarmi e seguire l'evoluzione di Internet.
Mi occupo delle nuove tecnologie di sviluppo sul Web/Internet, con particolare attenzione ad Ajax, Web2.0, jQuery, PHP.
Ulteriori conoscenze da esperienze lavorative:
DVD
luglio 9th, 2010 alle 23:21
Ottimo! solo una cosa.. se volessi implementare a:active
per il submenu?
$(document).ready(function() {
$(“.sub-menu a”).click(function() {
$(“.sub-menu a”).removeClass(“selected”);
$(this).addClass(“selected”);
});
});
Grazie!
MaiNick
luglio 12th, 2010 alle 12:41
@ DVD:
scusami ma con
$(this)ti stai riferendo alla voce cliccata, dunque quello che fa ciò che hai scritto è rimuovere la classeselectede poi ri-aggiungerla.Non ho capito cosa cercavi di fare
DVD
luglio 15th, 2010 alle 15:19
@ MaiNick:
Praticamente voglio assegnare una classe dei css diversa alla voce del menu selezionata. Per esempio se clicco su Articolo 1, si deve attivare per la voce selezionata una classe specifica che ho definito che lo evidenzia fino a che non seleziono un altra voce.
Grazie!
MaiNick
luglio 15th, 2010 alle 23:47
@ DVD:
forse ho capito. Inserisci nel file di script, dopo la dichiarazione dell’evento click sui link principali:
$('li.sub-menu a').click(function(){// rimuovo la classe css su ogni possibile link voce sotto-menu
$('li.sub-menu a').each(function(){
$(this).removeClass("selected");
});
// aggiungo la classe css al link cliccato
$(this).addClass("selected");
// se non deve continuare nella funzione default del link
return false;
});
spero di aver capito e risolto il tuo problema.
DVD
luglio 16th, 2010 alle 12:53
6 un grande! Grazie mille!!
Dino
luglio 22nd, 2010 alle 21:23
Ciao! Sarebbe grandioso se esistesse anche una versione “orizzontale” di questo fantastico menù. Mi spiego…
invece di avere la progressione così
—-
|
—-
|
—-
e via dicendo, sarebbe possibile averla così:
|—-|–|—–|
o è troppo complicato?
Grazie!
Pino
luglio 24th, 2010 alle 15:56
Ciao e complimenti! Senti, come posso fare per mantenere il sotto menu aperto una volta cliccata una voce.
mi spiego meglio:
clicco una una delle voci principali -> si apre la tendina -> clicco su una voce di sotto menu -> vengo indirizzato alla pagina. Ecco, vorrei che nella nuova pagina il sotto menu selezionato in precedenza rimanesse aperto.
grazie
MaiNick
luglio 25th, 2010 alle 15:40
Ciao e grazie! Puoi inviarti un valore tramite l’array globale
$_GET, oppure tramite uno script in JavaScript controllare l’indirizzo della pagina corrente. Tutti e due i casi imposti una classe CSS, ad esempio open, che ti rimane aperto il sotto-menu desiderato.pino
luglio 26th, 2010 alle 18:55
Ciao e grazie per la solerte risposta. Il problema è che il menu si genera dinamicamente attraverso un ciclo while, se invio tramite get un valore x tutti i link del menu avranno quel valore e quindi tutte le tendine si aprirebbero.
Spero di essermi spiegato!
Hai qualche idea?
grazie
@ MaiNick:
MaiNick
luglio 28th, 2010 alle 09:56
@ pino: meglio così, io per valore intendevo la voce del menù che devi visualizzare: quando generi il menu con il
whilefai un controllo se la voce da visualizzare è uguale a quella inviata allora stampa la classeopenpino
luglio 28th, 2010 alle 14:23
Hai ragione MaiN, mi ero scioccamente impuntato sulle sottocategorie. Ora funziona, ti ringrazio.
pino
luglio 30th, 2010 alle 16:03
MaiN, come ti dicevo, funziona. C’è solo un piccolo problema:
una volta giunto sulla pagina di destinazione, il sottomenu rimane aperto, appunto. Ma se seleziono un’altra voce di menu, chiaramente il sottomenu precedente continua a rimanere aperto a causa della classe open cui ora è soggetta.
È possibile ri-associare la classe originaria a quel sottomenu quando si fa clic su una nuova voce di menu?
MaiNick
luglio 30th, 2010 alle 22:43
Se ho capito bene dici che se clikki una voce del menu principale, il sotto-menu che prima era aperto tramite la classe
opennon si chiude automaticamente.Allora puoi risolvere il problema inserendo nel codice del file dello script, prima della riga di codice
$('.sub-menu').not(subMenu).slideUp('slow');, la seguente istruzione:$('.sub-menu').not(subMenu).removeClass('open');.Spero di aver capito il tuo problema e di averlo risolto.
pino
agosto 2nd, 2010 alle 10:08
Ciao MaiN. Esatto, il problema è proprio questo.
La classe “open” rimane associata a quel che si porta dietro il nome della categoria principale.
Il mio problema è quello di rimuovere la classe “open” e riattivare la classe d’origine “sub-menu”.
Ho provato a inserire l’istruzione che dicevi ma, ahimè, non produce alcun effetto.
MaiNick
agosto 2nd, 2010 alle 13:12
Scusami ma la classe
openè sullo stesso elemento a cui è associata la classesub-menu?pino
agosto 2nd, 2010 alle 14:02
ho fatto un controllo di questo tipo:
<?php
if($open==$nome_cat) {
$class = "open";
echo "”;
} else {
echo “”;
}
?>
MaiNick
agosto 2nd, 2010 alle 18:04
Se scrivi il sotto-menu nel modo seguente, il codice JavaScript che ti ho scritto nei commenti precedenti, dovrebbe funzionare:
<li class="sub-menu <?php echo ($open==$nome_cat) ? 'open' : ''"?>">
<ul>
<li><a href="#">Articolo 1</a></li>
<li><a href="#">Articolo 2</a></li>
</ul>
</li>
pino
agosto 2nd, 2010 alle 19:13
scusa, il codice di prima non ha incluso le due opzioni .
Ci riprovo:
<?php
if($open==$nome_cat) {
$class = "open";
echo "”;
} else {
echo “”;
}
?>
pino
agosto 2nd, 2010 alle 19:16
di nuovo, provo così:
nel primo echo ci sta
e nel secondo
else
pino
agosto 3rd, 2010 alle 11:05
Non funziona. Facendo come dici l’output html mi restituisce questo:
li class=”sub-menu open”
MaiNick
agosto 3rd, 2010 alle 22:29
Scusa ma tu prima dove la mettevi la classe
open?pino
agosto 4th, 2010 alle 10:25
con un controllo if else, se variabile open corrisponde a variabile nome_cat allora stampo un “li” con class “open”, altrimenti stampo “li” con class “sub-menu”@ MaiNick:
MaiNick
agosto 4th, 2010 alle 18:30
Quindi se ho capito bene metti la classe
opensuli, dove ci sono i link alle pagine, all’interno della lista con la classesub-menu.Se si al posto del codice javascript che ti ho scritto alcuni commenti prima
$('.sub-menu').not(subMenu).removeClass('open');sostituiscila con la seguente riga$('.sub-menu li').removeClass('open');che non fa altro che togliere la classeopenda tutte le vociliinterne al lista con classesub-menu.Se non funziona inviami un’e-mail risponde a quella che ti ho inviato in questo momento.
paolo
agosto 5th, 2010 alle 18:18
MaiNick ha scritto:
so qual è la pagina.. ok! e come dico con i CSS che resti aperto??
MaiNick
agosto 9th, 2010 alle 08:53
Puoi fare come ho scritto in un commento precedente: scrivi il sotto-menu nel modo seguente
<li class="sub-menu <?php echo ($_GET['open']==$nome_cat) ? ‘open’ : ” ?>">
<ul>
<li><a href="#">Articolo 1</a></li>
<li><a href="#">Articolo 2lt;/a></li>
</ul>
&/li>
dove
$nome_catè il nome della categoria o voce lista con il quale fare il confronto con il valore inviato tramite$_GET['open'].Iron
agosto 24th, 2010 alle 15:52
Una domanda! (sono un neofita, quindi non lapidatemi
).
Voglio che se JavaScript venga disattivato il menù possa apparire per intero, quindi aperto.
Altrimenti, con JS attivato, chiuso.
Grazie
MaiNick
agosto 24th, 2010 alle 21:37
@ Iron: benvenuto iron.
Allora innanzitutto devi togliere la proprietà
display:nonedi.sub-menudal foglio di stile CSS, poi inserisci la seguente riga di codice javascript nel codice del file di script:$('.sub-menu').css("display","none");subito dopo
$(document).ready(function(){Fabio
agosto 25th, 2010 alle 12:06
Ciao, complimenti per il blog.
Io, purtroppo ho un problema non posso usare il codice php “> che tu hai indicato.
Mi sarebbe utile capire come indicare tramite il CSS e il Javascript di lasciare aperto il sotto menu.
Grazie per l’attenzione.
MaiNick
agosto 25th, 2010 alle 12:22
@ Fabio: ciao Fabio e grazie dei complimenti.
Se vedi il commento sopra il tuo ho risolto il tuo problema solo con codice JavaScript e CSS.
Iron
agosto 25th, 2010 alle 12:48
Grazie MaiNick per la risposta
Un ultimo quesito.
Voglio dare un’effetto diverso dal Bounce.
All’apertura del sub-menu infatti, vorrei dare un effetto di Fade al sub-menu stesso.
Come posso fare?
Grazie ancora
Fabio
agosto 25th, 2010 alle 13:25
@MaiNick: Grazie sei stato velocissimo. Ma credo di essermi spiegato male: io ho lo stesso problema che aveva Pino, ma posso trovare una soluzione esclusivamente tramite Javascript e CSS.
La tua soluzione può essere un punto di partenza ma devo trovare un modo per lasciare esploso solo il sottomenu inerente al link visitato.
Grazie ancora
MaiNick
agosto 25th, 2010 alle 14:26
@ Iron: dirti la verità non mi piace molto, anche perché non si vedrebbe l’effetto, comunque se vuoi puoi sostituire nel file di script la seguente voce:
subMenu.stop(false,true).slideToggle('slow');con la seguente
subMenu.stop(false,true).fadeIn('slow');Iron
agosto 25th, 2010 alle 14:43
Era proprio l’effetto che volevo dare, grazie.
Però una volta aperto un sub-menu, se ri-clicco sulla voce principale il sub-menu stesso non si richiude..
Come potrei risolvere?
Grazie
Fabio
agosto 25th, 2010 alle 14:44
@MaiNick: secondo me ti sei pentito di questo post
Ti stiamo rompendo proprio l’anima !!!
MaiNick
agosto 25th, 2010 alle 14:48
@ Fabio: come per Pino ti invii un valore tramite url
http://www.esempio.it/articolo.html?catopen=jqueryche poi prelevi tramite JavaScript in questo modo:var categoriaOpen = unescape(self.location.search.substr(1)).split("=");otterrai nella variabile
categoriaOpenun array composto da due elementicategoriaOpen[0]il valorecatopenecategoriaOpen[1]il valore del menu da lasciare apertojquery.Puoi inserire questo codice JavaScript nel file di script dell’esempio e poi continuare con uno
switcho unifper determinare il menu che dovrà avere la classeopenspiegata nei commenti in risposta a Pino.MaiNick
agosto 25th, 2010 alle 14:59
@ Iron: si infatti, perché prima c’era l’effetto
slideToggleche provvedeva ad aprire o chiudere con effetto a tendina a seconda che si trovava nello stato inverso, mentre non esiste un effetto fade che provveda ad eseguire l’effetto inverso allo stato in cui si trova (aperto o chiuso) e deve provvedere tu tramitefadeInefadeOut, ma come è sviluppato il menu è un passaggio piuttosto difficile.Mi dispiace non averti dato una risposta migliore
Iron
agosto 25th, 2010 alle 15:00
Iron ha scritto:
PS: dimenticavo! Con un fade anche in chiusura
Iron
agosto 25th, 2010 alle 15:01
Ah, letto ora
grazie 1000 delle risposte.
Ciao!
Fabio
agosto 25th, 2010 alle 16:54
@MaiNick: Grazie 1000. Sei stato davvero gentilissimo!!!
aleandro
agosto 28th, 2010 alle 15:53
Ciao MainNick, sono un niubbio con javascript e jquery, e sono di fronte ad un prob, che è l’attivazione del controllo activeX di IE (ho la versione 8)..
ho visto che molti esempi e animazioni di Jquery funzionano senza questo prob, ma quando provo a creare una funzione,
e lo testo su IE, mi parte il controllo activeX..
mi è anche venuto un dubbio non è (come in Flash) che il controllo parte quando il file viene testato in locale??
e se è cosi come si fà a vedere effettivamente se usando altre tecnologie javascript e ajax non parta quel controllo quando il sito è online?
grazie..
MaiNick
agosto 28th, 2010 alle 17:30
@ aleandro: ciao e benvenuto. Si il problema che si attivi il controllo ActiveX su IE risulta solo in locale (verifica di sicurezza), mentre on-line non si verificherà.
aleandro
agosto 30th, 2010 alle 09:26
@ MaiNick:
grazie, mi ci sono sbattuto per diversi giorni..
Riccardo
settembre 2nd, 2010 alle 07:15
Ciao. E’ possibile che una voce non apra altre voci ma che sia un link diretto? Come si fa?
MaiNick
settembre 2nd, 2010 alle 16:52
@ Riccardo: ciao e benvenuto. Allora puoi ricreare una voce del menu principale senza il sotto-menu
.sub-menue cambiare la classe.titlein.title-link. Poi dai le stesse regole CSS che ha la classe.titleanche alla nuova classe.title-linke ovviamente metti il link che deve seguire nell’attributohrefdella nuova voce di menu principale.Spero di essere stato chiaro, se hai problemi fammi sapere.
Riccardo
settembre 2nd, 2010 alle 20:31
Grazie mille, ce l’ho fatta.
Pino
settembre 3rd, 2010 alle 11:58
ciao Main, eccomi di nuovo
Ho notato che il menu funziona bene su tutte le versioni di browser recenti: FF, safari, opera ecc. Mentre per l’amico IE funziona bene solo con la versione 8. Con IE6 e IE7 il menu funziona a scatti. Il movimento di chiusura e apertura della tendina non è fluido.
È possibile fare qualcosa?
grazie
MaiNick
settembre 3rd, 2010 alle 17:38
Mi dispiace ma l’effetto dipende dalla libreria jQuery con plugin Easing. Prova ad aumentare la velocità dell’effetto e vedi se cambia qualcosa; al posto di
slowutilizza il parametrofast.