11 agosto 2009

jQuery: bollino sconti per siti e-commerce

In questi giorni ho lavorato sodo alla nuova versione del negozio I Tesori del Drago, che vende principalmente prodotti naturali per la salute ed il benessere, oltre ad altri articoli interessanti.
Questo negozio era stato lanciato a Novembre 2008, e mi ero occupato praticamente di tutto l'aspetto creativo e tecnico. Si è deciso di cambiare l'impostazione grafica da "dark" a "light", e ne ho approfittato per aggiungere alcune migliorie.

Tra le varie cosette carine implementate, oggi voglio parlare del bollino che ho creato per i prodotti in offerta (un bollino che indica lo sconto percentuale applicato sull'articolo), perché rende bene l'idea del potenziale di jQuery anche a livelli di web design quasi puro.

L'idea era quella di avere, nella homepage e nella pagina dedicata all'articolo in offerta, una funzionalità completamente automatica che generasse una grafica mostrante lo sconto percentuale, da abbinare alla foto del prodotto.


Ho usato esclusivamente jQuery per realizzare questa piccola miglioria di design.
In pratica, si calcola lo sconto percentuale tramite i tag che contengono il valore del prezzo di listino e di quello di vendita, e poi si immette quel valore percentuale in un elemento blocco opportunamente stilato con del CSS (anch'esso generato con jQuery). L'unica cosa esterna al file .html di cui si ha bisogno è un PNG24 con il bollino, da usare come sfondo del blocco creato.
La grafica deve essere in formato .png a 24bit perché abbiamo bisogno di una trasparenza perfetta, ovviamente, visto che andremo a sovrapporre il bollino sugli sfondi più svariati.

L'HTML della sezione che ci interessa ha una struttura di questo tipo:

<div class="offerte">
<h1>nome articolo</h1>
<p>descrizione articolo</p>
<img alt="foto articolo" />
<span class="list_price">14.00€</span>
<span class="sell_price">12.60€</span>
</div>


Ecco il codice jQuery per calcolare la percentuale di sconto applicata:

$('.offerte').each(function (i) {
var lp=$(this).children('.list_price').text();
lp=lp.substr(0, lp.length - 1);
var sp=$(this).children('.sell_price').text();
sp=sp.substr(0, sp.length - 1);
var sconto=Math.round((100-((sp/lp)*100)));
});


Il metodo each( callback ) serve per iterare su tutti gli elementi aventi la classe "offerte" presenti nella pagina, in quanto non è detto che lo sconto percentuale applicato sia lo stesso su tutti gli articoli.
Prima di tutto si memorizzano il prezzo vecchio e quello scontato ciascuno in una propria variabile con il metodo text().
Poi con l'espressione che segue si tronca l'ultimo carattere della stringa memorizzata in ciascuna variabile. Questo per eliminare il simbolo finale dell'euro, che ci renderebbe il dato inutilizzabile in operazioni matematiche.
Occhio che il simbolo separatore dei decimali sia un punto (.) e non una virgola (,), perché jQuery nel secondo caso non riconoscerebbe come numeri i valori memorizzati.

Nella variabile sconto si calcola lo sconto percentuale: il metodo round(x) dell'oggetto Math arrotonda il valore dello sconto all'intero più vicino.
Questo è molto utile dal punto di vista grafico, visto che una o più cifre decimali "strizzerebbero" troppo il testo nel nostro bollino.

A questo punto, si costruisce un elemento blocco <div> nel quale immettere come testo il valore della variabile sconto, per poterlo visualizzare formattato a piacere:

$('.offerte').each(function (i) {
var lp=$(this).children('.list_price').text();
lp=lp.substr(0, lp.length - 1);
var sp=$(this).children('.sell_price').text();
sp=sp.substr(0, sp.length - 1);
var sconto=Math.round((100-((sp/lp)*100)));
$(this).append("<div class='bollino'></div>");
$(this).children('.bollino').css(bollino).html(sconto).prepend('-').append('%');
});


In sostanza, si appende un div al blocco "offerte" e gli si attribuisce dello stile precedentemente creato, tramite una variabile (usando css(properties), che vedremo tra poco), gli si inserisce come contenuto HTML la variabile sconto (html(val)) e si guarnisce con i necessari simboli "-" (visto che è uno sconto) e "%", rispettivamente prima e dopo il testo inserito.

Per l'immagine del bollino ho semplicemente usato una delle shapes predefinite di Photoshop:


A questo punto dobbiamo solo creare il CSS necessario a formattare e posizionare il nostro bollino.
Anche in questo caso si usa jQuery, creando una variabile da passare comodamente al proprio blocco col metodo css(properties).

var bollino = {
'background' : 'transparent url(images/bollino.png) top center no-repeat',
'width' : '50px',
'height' : '50px',
'z-index' : '100',
'text-align' : 'center',
'padding-top' : '1em',
'font' : 'italic bold 1em "century gothic", century, sans-serif',
'color' : '#fede60',
'position' : 'absolute',
'top' : '70px',
'left' : '125px'
}


Il position: absolute serve per poter piazzare il bollino parzialmente sovrapposto alla foto del prodotto.
L'unica cosa da notare in questo caso è che per consentire un posizionamento assoluto del bollino all'interno del blocco "offerte", è necessario che quest'ultimo abbia la proprietà CSS position: relative. Se così non fosse, il posizionamento sarà rispetto al primo blocco antenato posizionato relativamente, e quasi sicuramente ciò farà sì che tutti i bollini si sovrappongano.
E questo non è ciò che vogliamo, giusto?

Alla fine, quello che si ottiene sarà qualcosa di questo tipo:


Ecco lo script completo autosufficiente:
$(document).ready(function(){

var bollino = {
'background' : 'transparent url(images/bollino.png) top center no-repeat',
'width' : '50px',
'height' : '50px',
'z-index' : '100',
'text-align' : 'center',
'padding-top' : '1em',
'font' : 'italic bold 1em "century gothic", century, sans-serif',
'color' : '#fede60',
'position' : 'absolute',
'top' : '70px',
'left' : '125px'
}

$('.offerte').each(function (i) {
var lp=$(this).children('.list_price').text();
lp=lp.substr(0, lp.length - 1);
var sp=$(this).children('.sell_price').text();
sp=sp.substr(0, sp.length - 1);
var sconto=Math.round((100-((sp/lp)*100)));
$(this).append("<div class='bollino'></div>");
$(this).children('.bollino').css(bollino).html(sconto).prepend('-').append('%');
});

});

[Aggiunta: sul Problema della Trasparenza in IE6]
La questione è fin troppo vecchia per doverne sempre stare a discutere: IE6 non supporta la trasparenza alpha dei PNG24, e il nostro bollino su tale browser degrada ad un ingombro grafico sgradevole.
Nessuno oggigiorno dovrebbe mai navigare in internet con un simile programma! Ma per coloro che sono obbligati, c'è sempre una qualche scappatoia parziale.

Un metodo è usare lo script PNG Fix di Andreas Eberhard, che fa generalmente un ottimo lavoro nel ripristinare la corretta trasparenza dei PNG della pagina web su cui è invocato.

L'altra soluzione è il vecchio metodo delle immagini GIF di sostituzione a quelle PNG, visto che almeno la trasparenza GIF ad un solo bit è supportata da questo browser.
In questo caso, se usate un bollino "a tinta unita" (solid color) come il mio sopra, conviene creare una GIF a soli due colori: uno per il colore del bollino, l'altro per la trasparenza, e senza alcun dithering. In questo modo, quando il bollino si sovrappone ad altri elementi, i risultati sono decisamente più accettabili.

Una maniera di implementare questo ultimo sistema nel nostro script senza stravolgere alcunché è sfruttare jQuery per riconoscere il modello e la versione del browser che interpreta la pagina web, e agire di conseguenza.

Ad esempio aggiungendo in fondo allo script, semplicemente:
if($.browser.msie && $.browser.version<="6.0"){
$('.bollino').css('background', 'transparent url(images/bollino.gif) top center no-repeat');
}
In realtà l'uso del metodo $.browser.version è deprecata perché l'utilizzo di jQuery concerne più le caratteristiche di un browser, che la sua versione, come si spiega nella pagina della documentazione dedicata al metodo jQuery.support.