Usando jQuery ci troviamo spesso di fronte allo stesso dilemma: dobbiamo usare un plugin per un progetto specifico? Dipende spesso dai requisiti del progetto. In altre parole: quanto codice e quanto tempo sono necessari per ottenere un determinato risultato? Si tratta di una questione di tempo. Dal momento che spesso non abbiamo il tempo necessario a causa della scadenza dei tempi di consegna, a volte è necessario usare un plugin. Altre volte invece, specie quando il progetto ha delle specifiche che non si trovano facilmente implementate in un plugin, possiamo sviluppare una nostra implementazione. Vediamo il secondo caso.
Requisiti del progetto
Un cliente vuole che le immagini ridimensionate inserite nelle pagine siano trasformate in una galleria con effetto lightbox. La galleria dovrà essere qualcosa di molto semplice: una finestra modale con un sistema di navigazione e paginazione delle immagini e un elemento di overlay sottostante semitrasparente.
Quando si clicca su un'immagine, la galleria deve comparire mostrando l'immagine corrente come prima immagine e le altre immagini nascoste. Usando la navigazione si mostrano le altre immagini con un effetto di assolvenza.
La marcatura
Il codice HTML è il seguente:
<a href="percorso/immagine-full.jpg" class="gallery">
<img src="percorso/immagine-resized.jpg" alt="Testo" />
</a>
Con jQuery dobbiamo creare la seguente struttura da inserire alla fine dell'elemento body
:
<div id="overlay"></div>
<div id="gallery">
<div id="gallery-wrapper">
<img id="first-image" />
</div>
<div id="gallery-nav"></div>
</div>
Il codice CSS
Useremo il posizionamento assoluto per visualizzare la galleria e l'elemento di overlay. Quest'ultimo elemento avrà un'altezza assegnata dinamicamente da jQuery:
#overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
background: rgba(0, 0, 0, 0.7);
display: none;
}
#gallery {
width: 500px;
height: 400px;
border: 5px solid #eee;
position: absolute;
top: 50%;
left: 50%;
margin: -210px 0 0 -260px;
background: #fff;
display: none;
}
#gallery-wrapper {
width: 400px;
height: 300px;
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -200px;
}
#gallery-nav {
height: 2em;
width: 100%;
position: absolute;
bottom: 0;
left: 0;
background: #f6f6f6;
border-top: 1px solid #eee;
text-align: center;
}
#gallery-nav a {
display: inline-block;
height: 1.6em;
width: 1.6em;
line-height: 1.6;
margin: 0.2em 0.5em 0.2em 0;
text-align: center;
text-decoration: none;
color: #333;
background: #ddd;
}
#gallery-wrapper img {
max-width: 100%;
display: none;
}
#gallery-wrapper > img:first-child {
display: block;
}
Il codice jQuery
Useremo un oggetto Gallery
con vari metodi. Essi dovranno:
- ottenere il percorso e l'attributo
alt
dell'immagine corrente - inserire le altre immagini nella gallery quando l'utente attiva la lightbox
- generare la struttura HTML della gallery (vista sopra)
- aggiungere i link alla navigazione in modo tale che ciascun link abbia un attributo
data-
che punti all'indice dell'immagine corrispondente - popolare e mostrare la galleria
- gestire la navigazione
- nascondere la galleria e resettarne la struttura DOM.
Ecco il nostro oggetto:
var Gallery = {
utils: {
getCurrentImage: function(element) {
var $img = $('img', element),
src = $img.attr('src'),
alt = $img.attr('alt');
return {
src: src,
alt: alt
}
},
insertOtherImages: function(element) {
var parent = element.parents('#content');
var links = parent.find('a.gallery').not(element);
links.each(function() {
var $link = $(this);
var image = Gallery.utils.getCurrentImage($link);
$('<img/>').attr({
src: image.src,
alt: image.alt
}).appendTo('#gallery-wrapper');
});
}
},
fn: {
createGallery: function() {
$('<div id="overlay"/>').
css('height', $(document).height()).
appendTo('body');
$('<div id="gallery"/>').insertAfter('#overlay');
$('#gallery').html('<div id="gallery-wrapper"></div><div id="gallery-nav"></div>');
$('<img id="first-image"/>').appendTo('#gallery-wrapper');
},
populateGallery: function() {
$('a.gallery').each(function(i) {
$('<a/>').attr({
href: '#',
'data-image': i
}).text(i + 1).appendTo('#gallery-nav');
});
},
showGallery: function() {
$('a.gallery').on('click', function(e) {
e.preventDefault();
var $a = $(this);
var image = Gallery.utils.getCurrentImage($a);
$('#first-image').attr({
src: image.src,
alt: image.alt
});
Gallery.utils.insertOtherImages($a);
$('#overlay').fadeIn(400, function() {
$('#gallery').fadeIn(400);
});
});
},
navigate: function() {
$('a', '#gallery-nav').live('click', function(e) {
e.preventDefault();
var index = $(this).data('image');
$('img', '#gallery-wrapper').eq(index).fadeIn(600).siblings('img').hide();
});
},
closeGallery: function() {
$('#overlay').on('click', function() {
var overlay = $(this);
$('#gallery').fadeOut(400, function() {
overlay.fadeOut(400);
$('#first-image').show().attr({
src: '',
alt: ''
}).siblings('img').remove();
});
});
}
},
init: function() {
this.fn.createGallery();
this.fn.populateGallery();
this.fn.showGallery();
this.fn.navigate();
this.fn.closeGallery();
}
};
L'oggetto può essere inizializzato come segue:
$(function() {
Gallery.init();
});
Analisi del codice
L'oggetto Gallery
è composto da tre membri:
utils
– Oggetto che contiene due metodi di utility:getCurrentImage(element)
– Questo metodo accetta come argomento l'elementoa
che contiene l'immagine nel documento. Restituisce un oggetto che memorizza il percorso dell'immagine ed il suo attributoalt
.insertOtherImages(element)
– Questo metodo accetta come argomento l'elementoa
corrente (che viene cliccato). Esegue un loop sugli altri elementia
(ovviamente ad eccezione di se stesso) e genera le altre immagini da inserire nella gallery dopo quella corrente.
fn
– Il core del nostro oggetto principale. Ha cinque metodi:createGallery()
– Genera la struttura HTML della gallery e imposta l'altezza dell'overlay sull'altezza dell'intero documento.populateGallery()
– Genera i link per la navigazione delle immagini con un loop attraverso i link presenti nel documento. Ciascun link avrà un attributodata-image
che contiene l'indice dell'immagine corrispondente.showGallery()
– Questo metodo associa un eventoclick
ai link presenti nel documento. Per prima cosa inserisce l'immagine corrente, quindi inserisce le altre immagini. A quel punto mostra l'elemento di overlay e la gallery con un effetto di assolvenza.navigate()
– Questo metodo reperisce l'indice delle immagini memorizzato nell'attributodata-
e lo usa per visualizzare l'immagine corrente nella galleria, nascondendo al contempo tutte le altre.closeGallery()
– Questo metodo fa sparire l'overlay e la gallery resettandone la struttura DOM.
init()
– Metodo di inizializzazione dell'oggettoGallery
.