Guida Jquery Base: #5 Esempi pratici di jQuery in pagine Web con un Tab Layout

By Andrea Marchetti - 2 Mar , 2016

Guida Jquery Base: #5 Esempi pratici di jQuery in pagine Web con un Tab Layout

In questo articolo andiamo a combinare le nozioni jQuery che abbiamo imparato nei precedenti articoli creando un Layout a Tab. Come prima cosa definiamo l’html necessario:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<style>	
body{font-family: arial;padding:40px; margin:0; background: #19a2c9; color:#fff; }
a{color:#fff210; text-decoration: none; display: inline-block; width:33%;text-align: center}
hr{ border: 0; height: 1px; background: #ccc; margin-bottom: 40px; }
ul{padding: 0;margin:0;}
li{display: inline-block;padding: 5px}
.panel{display: none; padding:0; margin: 0;}
.panel.active{display: block}
li.active{background: #333}
</style>
</head>
<body>
<h1>JQuery</h1>
<h2>Introduzione a jquery</h2>
<div class="tab-container">
<ul class="tab-menu">
<li class="active">Titolo 1</li>
<li>Titolo 2</li>
<li>Titolo 3</li>
</ul>	
<div class="panel active" id="panel1">	
<h3>Pannello 1</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div class="panel" id="panel2">	
<h3>Pannello 2</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
<div class="panel" id="panel3">	
<h3>Pannello 3</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>	
$(document).ready(function(){
// codice jquery
});
</script>
</body>
</html>

La struttura è semplice, ci sono tre elementi li e tre div con classe panel. Di default tutti i div con classe panel sono nascosti tramite css con display:none. Grazie alla classe active con css display:block scelgo il pannello da visualizzare.

Con jQuery dobbiamo far si che quando clicco sul un elemento li venga applicata la classe active al pannello corrispondente.

1) L’attributo data

Per legare la voce li al pannello utilizziamo l’attributo data-NOMEATTRIBUTO, definiamo il nostro attributo con data-panel.

Con data-panel possiamo stabilire l’id del pannello che vogliamo aprire, ora il nostro menu sarà:

<ul class="tab-menu">
<li class="active" data-panel="panel1">Titolo 1</li>
<li data-panel="panel2">Titolo 2</li>
<li data-panel="panel3">Titolo 3</li>
</ul>

Fatta questa modifica nell’html andiamo a scrivere il codice jQuery necessario, come prima cosa dobbiamo recuperare l’attributo data-panel quando si clicca su un li.

<script>	
$(document).ready(function(){
$(".tab-menu li").on('click', function(){
var panel = $(this).attr("data-panel");
alert(panel);
})
});
</script>

Con questo codice testiamo l’on-click. Quando cicchiamo su un elemento li viene aperto un alert con l’id del pannello da mostrare.

jquery19

2) Funzione showPanel

Ora creiamo una funzione showPanel che mostrerà il pannello selezionato utilizzando l’id recuperato dall’attributo data-panel.

<script>	
$(document).ready(function(){
$(".tab-menu li").on('click', function(){
var panel = $(this).attr("data-panel");
$(".panel.active").slideUp(600, showPanel);
// function pass as a callback
function showPanel(){
$("#"+panel ).slideDown(600);
}
})
});
</script>

Da notare che la funzione showPanel è eseguita dopo lo slideUp di .panel.active. Prima scompare il pannello corrente poi viene mostrato quello sul quale l’utente ha cliccato.

Ora il sistema funziona ma è incompleto. Non ho aggiunto la classe active quando mostro il pannello, quindi jQuery non sa che pannello nascondere dopo il primo click.

jquery-20

Per ovviare a questo problema modifichiamo la funzione showPanel(). Come prima cosa rimuovo la classe active del pannello che sto nascondendo (tramite slideUp).

$(".panel.active").slideUp(600, showPanel);
function showPanel(){
$(this).removeClass('active');
$("#"+panelToShow ).slideDown(600);
}

Successivamente aggiungo la classe active al pannello mostrato (tramite slideDown).

$(".panel.active").slideUp(600, showPanel);
function showPanel(){
$(this).removeClass('active');
$("#"+panelToShow ).slideDown(600, function (){
$(this).addClass('active');
});
}

Questa volta la funzione con cui aggiungiamo la classe active è definita all’interno al metodo slideDown non viene richiamata dall’esterno come showPanel.

3) Valore di this

Qui potrebbero nascere dei dubbi sul valore di this. Il context di this cambia in base al proprietario che esegue la funzione.

Prendiamo il nostro codice e commentiamolo:

<script>	
$(document).ready(function(){
$(".tab-menu li").on('click', function(){
// 1) this si riferisce a .tab-menu li 
var panelToShow  = $(this).attr("data-panel");
$(".panel.active").slideUp(600, showPanel);
// funzione che viene passato dopo lo slideUp callback
function showPanel(){
// 2) this si riferisce a .panel.active 
$(this).removeClass('active');
$("#"+panelToShow ).slideDown(600, function (){
// 3) this si riferisce al panelToShow
$(this).addClass('active');
});
}
});
});
</script>

Il primo this si riferisce al elemento del menu cliccato .tab-menu li, questo perché this è contenuto dalla funzione function() lanciata dal metodo on(‘click’).

Il secondo this si riferisce al pannello attivo .panel.active, questo perché this è contenuto dalla funzione showPanel eseguita alla fine dello slideUp applicato su .panel.active.

Il terzo this si riferisce al pannello da mostrare (”#”+panelToShow), questo perché this è contenuto dalla funzione
function() eseguita alla fine dello slideDown applicato su ”#”+panelToShow.

Questi sono i tre Context di this nel nostro script, se hai dubbi ti rimando alla guida base javascript dove viene spiegato il concetto di context/this:

Vai alla guida

Detto questo applichiamo la classe active nel menu:

<script>	
$(document).ready(function(){
$(".tab-menu li").on('click', function(){
$(".tab-menu li.active").removeClass("active");
$(this).addClass("active");
// 1) this si riferisce a .tab-menu li 
var panelToShow  = $(this).attr("data-panel");
$(".panel.active").slideUp(600, showPanel);
// funzione che viene passato dopo lo slideUp callback
function showPanel(){
// 2) this si riferisce a .panel.active 
$(this).removeClass('active');
$("#"+panelToShow ).slideDown(600, function (){
// 3) this si riferisce al panelToShow
$(this).addClass('active');
});
}
});
});
</script>

Prima rimuovo la classe active e poi la aggiungo al corrente li.

jquery-21

4) Ottimizzazioni

Ora il nostro layout a tab funziona, non è però perfetto ci sono aspetti che possono essere migliorati.

Vengono più volte utilizzati selettori simili $(“.tab-menu li.active”) e $(“.panel.active”) all’interno dell’evento on click.

Ogni volta che un elemento li viene cliccato jQuery deve cercare in tutta la pagina html l’elemento che abbiamo definito nel selettore. Se la nostra applicazione è molto piccola non ci sono problemi. Se incominciamo a sviluppare qualcosa di più complesso questo può causare problemi (rallentamenti e potenzialmente conflitti con altre strutture html con stesse classi).

Per ottimizzare quindi la nostra struttura crediamo una nuova variabile currentContainer dove salviamo il selettore che identifica il div contenitore del nostro tab layout.

<script>	
$(document).ready(function(){
$(".tab-menu li").on('click', function(){
var currentContainer = $(this).closest(".tab-container");
$(".tab-menu li.active").removeClass("active");
$(this).addClass("active");
// 1) this si riferisce a .tab-menu li 
var panelToShow  = $(this).attr("data-panel");
$(".panel.active").slideUp(600, showPanel);
// funzione che viene passato dopo lo slideUp callback
function showPanel(){
// 2) this si riferisce a .panel.active 
$(this).removeClass('active');
$("#"+panelToShow ).slideDown(600, function (){
// 3) this si riferisce al panelToShow
$(this).addClass('active');
});
}
});
});
</script>

Successivamente utilizziamo la variabile creata e il metodo find per cercare gli elementi solo nel div contenitore e non in tutta la pagina html. Questo evita conflitti ed è più performante.

<script>	
$(document).ready(function(){
$(".tab-menu li").on('click', function(){
//stabilisco qual'è il container
var currentContainer = $(this).closest(".tab-container");
//trovo l'elemento nel menù e rimuovo la classe active
currentContainer.find(".tab-menu li.active").removeClass("active");
$(this).addClass("active");
// 1) this si riferisce a .tab-menu li 
var panelToShow  = $(this).attr("data-panel");
//trovo il pannello attivo lo nascondo e mostro quello nuovo
currentContainer.find(".panel.active").slideUp(600, showPanel);
// funzione che viene passato dopo lo slideUp "callback"
function showPanel(){
// 2) this si riferisce a .panel.active 
$(this).removeClass('active');
$("#"+panelToShow ).slideDown(600, function (){
// 3) this si riferisce al panelToShow
$(this).addClass('active');
});
}
});
});
</script>

Fatto questo come ultima cosa quando aggiungiamo il segno dollaro $ davanti alla variabile $currentContainer.

<script>	
$(document).ready(function(){
// evento che ascolta ogni click su gli elementi li
$(".tab-menu li").on('click', function(){
//stabilisco qual'è il container
var $currentContainer = $(this).closest(".tab-container");
//trovo l'elemento corrente nel menù e rimuovo la classe active
$currentContainer.find(".tab-menu li.active").removeClass("active");
//aggiungo la classe al nuovo elemento corrente
$(this).addClass("active");
//stabilisco qual'è il pannello da mostrare
// 1) this si riferisce a .tab-menu li 
var panelToShow  = $(this).attr("data-panel");
//trovo il pannello attivo lo nascondo e mostro quello nuovo
$currentContainer.find(".panel.active").slideUp(600, showPanel);
//funzione che viene passato dopo lo slideUp come "callback"
function showPanel(){
// 2) this si riferisce a .panel.active 
$(this).removeClass('active');
//creo il selettore per mostrare il nuovo pannello corrente
$("#"+panelToShow ).slideDown(600, function (){
// 3) this si riferisce al panelToShow
$(this).addClass('active');
});
}
});
});
</script>

Questo è una “best practice” jQuery che ci indica che la variabile che stiamo utilizzando è riferita a un selettore jQuery. Il codice è ampiamente commentato se avete dubbi scrivetemi nei commenti.

Stay Tuned!

Prossima lezione:

Tutte le lezioni della Guida jQuery Base:

demo

Se ti và ringraziami con un Like a MarchettiDesign.net.

Oppure offrimi un caffè :-)
download

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *