Abbiamo visto timer JavaScript di tutti i tipi e di tutte le salse e siamo consapevoli che grazie a questi elementi possiamo aumentare la scarsità nella mente dei nostri potenziali clienti, ma è possibile inserirne uno all’interno delle nostre pagine senza dover appesantire il nostro sito?
Parlo di appesantire perché fin troppo spesso troviamo script JavaScript che sono scritti per rispondere a moltissime necessità e includono decine di effetti e librerie che facilitano la configurazione di questi elementi a discapito della semplicità. Però recentemente mi sono trovato a chiedermi se fosse veramente così difficile dover creare un timer con questo linguaggio, ed ecco che una volta trovata la risposta ho deciso di scrivere questo articolo.
Tutta la mia ricerca e riflessione è nata dalla necessità che avevo per un lavoro che abbiamo curato all’interno della nostra azienda. Il progetto utilizzava WordPress, quindi avrei potuto rivolgermi al suo repository di plugin e scegliere tra le centinaia di soluzioni disponibili. Avrei potuto, ma non lo ho fatto. Perché?
Il progetto che avevamo tra le mani puntava molto all’ottimizzazione del codice e al mantenimento di prestazioni elevate. Come puoi immaginare non volevo assolutamente utilizzare delle soluzioni che non conoscevo e che avrebbero richiamato file JavaScript e CSS incrementando il numero delle chiamate HTTP e il peso del sito web.
Assolutamente non era una strada che volevo percorrere!
Come realizzare un timer in JavaScript
Sappiamo tutti che JavaScript è un linguaggio di programmazione, giusto?
Ebbene, partendo da questa certezza possiamo anche immaginarci che grazie a questo linguaggio è possibile svolgere facilmente dei calcoli matematici che ci aiutino a svolgere il grosso del lavoro.
Precedentemente ti ho spiegato le opinioni che mi hanno spinto a scartare la possibilità di gestire il tutto con un plugin WordPress, però la mia scelta è stata ulteriormente più selettiva. Ho scelto di non usare neanche uno script JavaScript realizzato da terze parti, ecco alcune motivazioni:
- ho evitato le problematiche che avrei potuto incontrare dovute dalla dipendenza con altre librerie
- dato che non devo fare affidamento a librerie esterne, ho l’opportunità che il mio sito abbia prestazioni migliori
- ho il pieno controllo su come il timer si visualizzerà e sono in grado di personalizzarlo come meglio credo
- non ho neanche dovuto richiamare uno script esterno perché nella homepage, unica pagina dove mi interessava richiamare il timer, ho potuto aggiungere il mio codice all’interno del file
home.js
che veniva già collegato alla pagina.
Inoltre, come dicevo, questa soluzione è scritta interamente in JavaScript e dato che ho utilizzato la sintassi ES2015 e che non si tratta di un elemento essenziale al funzionamento della pagina, se il browser che carica la pagina non è in grado di comprendere questa sintassi posso tranquillamente evitare di inserirlo.
La prima cosa che bisogna fare in questo contesto è definire una scadenza appropriata. Si parla sempre di un timer in fin dei conti e per funzionare ha bisogno di una scadenza.
let scadenza = '2/17/2017';
Come puoi immaginare dalla struttura della stringa di testo inserita nella variabile scadenza
, ho scelto di utilizzare la sintassi mm/dd/yyyy (ovvero mese/giorno/anno) per rispettare il più classico dei modi in cui vengono definite le date nei linguaggi di programmazione. Avrei anche potuto optare per qualcosa di diverso come Feb 17, 2017 che è altrettanto compatibile, ma dato che non volevo rischiare di fare qualche errore ho favorito questo tipo di struttura.
Adesso però viene il bello, ora che abbiamo una data di scadenza è giusto sfruttare a pieno la potenza di calcolo del computer o smartphone utilizzato e calcolare il tempo rimasto. Per svolgere questi calcoli ho creato la seguente funzione JavaScript.
function tempoRimasto(tempo){ let t = Date.parse(tempo) - Date.parse(new Date()); let sec = Math.floor( (t/1000) % 60 ); let min = Math.floor( (t/1000/60) % 60 ); let ore = Math.floor( (t/(1000*60*60)) % 24 ); let giorni = Math.floor( t/(1000*60*60*24) ); return { 'totale': t, 'giorni': giorni, 'ore': ore, 'minuti': min, 'secondi': sec }; }
Ogni volta che la funzione tempoRimasto()
viene richiamata si crea una variabile t
all’interno della quale viene salvato il risultato della sottrazione tra un tempo futuro (la nostra scadenza) e il nostro presente.
Grazie al metodo Date.parse()
posso passare una stringa, meglio se formattata come la data specificata nella variabile scadenza
, farla tradurre nel numero di millisecondi che sono passati dal 1 gennaio 1970.
Giusto per correttezza sento il dovere di dire che se passiamo a questo metodo una stringa che non riesce a riconoscere, verrà restituito il valore NaN.
Tornando a noi, forse la creazione della variabile t
è la cosa più noiosa che avviene all’interno della funzione. In fin dei conti non facciamo altro che calcolare il numero di millisecondi che separano il nostro presente dalla scadenza
.
Non credi che sia più interessante scoprire come abbiamo fatto a calcolare la quantità di secondi, minuti, ore e giorni?
Qua entriamo nella vera matematica, abbiamo un valore numerico dichiarato in millisecondi e dobbiamo trasformarlo in un numero che sia comprensibile per il sistema sessagesimale che definisce la relazione tra secondi, minuti e ore.
Dato che la formula più semplice è quella che riguarda i secondi andrò a descrivere quest’ultima nel tentativo di farti comprendere anche le altre. Se hai qualche problema non esitare a scriverlo nei commenti e farò del mio meglio per aiutarti a comprendere anche le parti di codice che non ho spiegato.
let sec = Math.floor( (t/1000) % 60 );
Una singola riga di codice JavaScript può essere così tradotta:
- divido i millisecondi per 1000 in modo da ottenere il loro valore in secondi
- grazie all’operatore modulo (
%
) divido la cifra ottenuta per 60 e conservo soltanto il valore in eccesso che delinea i secondi rimasti - arrotondo la cifra ottenuta dall’operazione precedente con il metodo
Math.floor()
, perché quello che mi interessa è avere un numero pieno che identifica i secondi.
Ripetendo questo calcolo per gli altri valori si può calcolare facilmente anche i minuti, le ore e i giorni. Attento a questi ultimi due valori perché al posto di seguire il sistema sessagesimale dobbiamo tenere di conto che ci sono soltanto 24 ore in ogni giorno 😉
A questo punto il nostro timer è funzionante, anche se non vediamo assolutamente niente nel nostro file HTML ti basterà sostituire il return
della funzione con un classico console.log()
per scoprire che il conteggio funziona correttamente.
Se ti senti perso e non capisci parte del codice che stiamo discutendo, sappi che in SkillsAndMore è presente un corso completo che ti permetterà di scoprire come iniziare a programmare con il linguaggio JavaScript.
Adesso che abbiamo sfruttato la matematica per dare valore a una serie numerica, è giunto il momento di sfruttare le potenzialità del linguaggio JavaScript per mostrare un timer nelle nostre pagine HTML.
Come mostrare il timer nelle nostre pagine HTML
Come ti ho anticipato nella frase precedente, tutto quello che resta da fare al momento è capire come inserire nella pagina HTML il nostro timer. Se hai prestato attenzione alla sintassi della funzione hai sicuramente notato che stiamo restituendo un oggetto JSON all’interno del quale ogni proprietà contiene il valore dei secondi, minuti, ore e giorni che ci separano dalla scadenza.
return { 'totale': t, 'giorni': giorni, 'ore': ore, 'minuti': min, 'secondi': sec };
Grazie a questo oggetto restituito dalla nostra funzione possiamo inserire i valori calcolati all’interno della nostra pagina richiamandoli dalla funzione stessa. Ecco come è possibile, per esempio, richiamare i secondi:
tempoRimasto(scadenza).secondi
Per costruire il timer completo tutto quello che dobbiamo fare è mostrare tutti i valori che sono stati calcolati in modo che siano comprensibili per un essere umano. Dato che stiamo calcolando tutti questi valori in JavaScript, quello che ci resta da fare è creare un elemento HTML all’interno del quale inserire il nostro codice.
<div id="timer"></div>
Ora che abbiamo il nostro elemento HTML, non resta altro che creare una funzione incaricata di popolarlo:
function inizializzoTimer(id, scadenza){ let timer = document.getElementById( id ); let intervalloTempo = setInterval(function(){ var t = tempoRimasto(scadenza); timer.innerHTML = 'giorni: ' + t.giorni + '<br>' + 'ore: '+ t.ore + '<br>' + 'minuti: ' + t.minuti + '<br>' + 'secondi: ' + t.secondi; if(t.total<=0){ clearInterval(intervalloTempo); } },1000); }
Questa funzione è stata creata per accettare due parametri: l’id dell’elemento che vogliamo selezionare e che conterrà il timer (che con molta fantasia ho chiamato appunto timer
) e il valore per il quale stiamo calcolando il tempo restante.
All’interno di questa funzione andiamo inoltre a creare la variabile timer
e la utilizziamo per mantenere in memoria un riferimento all’elemento incaricato di contenerlo, in questo modo non andremo a interrogare continuamente il DOM e salveremo preziose risorse al computer del nostro visitatore.
Una volta che abbiamo ”preparato il campo” è giunto il momento di dare vita al nostro timer e fare in modo che si aggiorni automaticamente ogni secondo. Per raggiungere questo effetto non facciamo altro che utilizzare la funzione setInterval()
in modo da eseguire il codice che contiene al suo interno attraverso le seguenti operazioni:
- calcolare il tempo rimasto con la funzione
tempoRimasto()
- mostrare il tempo rimasto nella pagina grazie alla proprietà
innerHTML
dell’elemento contenitore - e nel caso in cui il tempo rimasto sia uguale o minore a zero, fermare il timer.
Ecco fatto, adesso sta alle tue competenze di HTML e CSS andare a personalizzare ulteriormente lo stile di questo elemento per ottenere il risultato che desideri.
Potrei anche fermarmi qua, però…
Sul fatto che il timer sia stato realizzato credo proprio che non ci sia alcun dubbio, anzi se proprio non mi credi eccoti un CodePen che dovrebbe soddisfare la tua curiosità.
Però per quanto funzionante questo script ha qualche piccolo problema di fondo ed essere in grado di sistemarlo ci consentirà di imparare qualcosa in più su JavaScript.
Dato che questa è un’ottima opportunità per apprendere qualcosa di nuovo realizzando qualcosa di utile, procederò in questo articolo andando ad analizzare le soluzioni implementate.
Prima di tutto dobbiamo capire quali sono i problemi che si trovano in questo script:
- non so se lo hai notato, ma c’è un leggero ritardo tra il caricamento della pagina e la presenza del timer. La prima cosa che faremo sarà fare in modo che il timer venga visualizzato immediatamente.
- aggiungiamo la possibilità di inserire uno 0 iniziale in base alle nostre necessità
- con uno script scritto in questo modo tutti gli elementi del timer vengono costruiti dinamicamente. Per quanto essenziale per rimuoverli se il JavaScript non è attivato, prima di concludere ti mostrerò anche come sia possibile realizzare una soluzione ibrida per aggiornare soltanto i valori numerici.
Adesso che abbiamo definito quali sono le aree che possiamo migliorare all’interno del nostro script non ci resta altro che andare a sistemare uno per uno i precedenti aspetti.
Rimuoviamo il ritardo nella creazione del timer
Abbiamo utilizzato la funzione setInterval()
per aggiornare il nostro timer, anche se la maggior parte delle volte questa è una soluzione che può andar bene, bisogna ammettere che in questo contesto causa un secondo di ritardo nella creazione dello stesso elemento.
Per rimuovere questo strano effetto dobbiamo modificare il nostro script in modo che aggiorni i valori contenuti nel timer prima ancora di eseguire questa funzione.
Per fare questo dobbiamo spostare la funzione anonima alla quale passiamo il risultato di setInterval()
in una funzione separata, che potremmo chiamare aggiornaTimer()
. In questo modo chiameremo questa stessa funzione la prima volta fuori dal nostro intervallo e la richiameremo nuovamente una volta che le operazioni necessarie all’intervallo saranno avviate.
Praticamente dovrai sostituire il seguente blocco di codice:
let intervalloTempo = setInterval(function(){ ... },1000);
Con questo:
function aggiornaTimer(){ let t = tempoRimasto(scadenza); timer.innerHTML = 'giorni: ' + t.giorni + '<br>' + 'ore: '+ t.ore + '<br>' + 'minuti: ' + t.minuti + '<br>' + 'secondi: ' + t.secondi; if(t.total<=0){ clearInterval(intervalloTempo); } } aggiornaTimer(); let intervalloTempo = setInterval(aggiornaTimer,1000);
Come dicevo, quello che abbiamo realizzato è stato delegare tutto il calcolo alla funzione aggiornaTimer()
in modo da poterla richiamare immediatamente e poi delegare il vero aggiornamento del timer alla funzione setInterval()
.
Se provi ad aggiornare la pagina noterai che tutto funziona correttamente e che il timer viene visualizzato nel momento stesso in cui la pagina viene caricata.
Gestiamo gli zeri e creiamo un timer più ordinato
Diciamoci la verità, avere un timer più uniforme è una cosa molto più gradevole dal punto di vista dello stile delle nostre pagine, non è vero?
Per uniforme intendo dire che tutte le cifre come ore, minuti e secondi al posto di mostrarsi in questo modo 1:23:4 (ovvero mancano 1 ora, 23 minuti e 4 secondi alla scadenza), verranno trasformate in 01:23:04. Questo ci consente di mantenere la dimensione del nostro timer ed evitare spiacevoli spostamenti nelle nostre pagine.
Come successo anche precedentemente, ti mostro come sia possibile applicare questo effetto soltanto su un unico valore e poi tu potrai decidere a quali applicarlo liberamente nel tuo codice.
'secondi: ' + ( '0' + t.secondi).slice(-2);
Se conosci la sintassi JavaScript, quello che stiamo facendo è relativamente semplice. Prima di inserire il nostro codice HTML aggiungiamo uno 0 in fronte alla stringa numerica e ci assicuriamo di ottenere da questa soltanto le ultime due cifre. Se è già un numero composto da due cifre, come nel caso di 23, non facciamo altro che prendere questo numero e inserirlo nel timer, mentre se il numero è composto da una singola cifra manteniamo lo 0 che abbiamo appena aggiunto.
Ora il nostro timer è più bilanciato e non ci resta altro che migliorare il codice HTML e renderlo più semplice da personalizzare. Nella prossima sezione ti mostro quale sia stata la mia scelta di personalizzazione, ma una volta che avrai appreso come sia facile da realizzare sarai in grado di trasformarlo come meglio credi.
Aggiungiamo un po’ di stile personalizzando il codice HTML
A questo punto voglio andare ad alleggerire il carico JavaScript e fare in modo che questo linguaggio vada soltanto ad aggiungere le cifre che identificheranno il tempo che ci separa dalla scadenza.
Tenendo a mente che questo potrebbe comportare alcuni problemi per i browser che non comprendono la sintassi ES2015 o che hanno JavaScript disattivato, ho comunque creato la seguente struttura:
<div id="timer"> <div class="giorni"> <span></span> <p>Giorni</p> </div> <div class="ore"> <span></span> <p>Ore</p> </div> <div class="minuti"> <span></span> <p>Minuti</p> </div> <div class="secondi"> <span></span> <p>Secondi</p> </div> </div>
So benissimo che per i puristi in ascolto l’uso di elementi span
vuoti non rappresenta la scelta migliore, ma come vedrai a breve, ho utilizzato questa tecnica perché in questo modo posso selezionare il nodo specifico nel DOM e utilizzarlo con la proprietà innerHTML
. Ecco come ho selezionato i miei elementi posizionandomi immediatamente sotto alla dichiarazione della variabile t
.
let giorni = timer.querySelector( '.giorni span' ); let ore = timer.querySelector( '.ore span' ); let minuti = timer.querySelector( '.minuti span' ); let secondi = timer.querySelector( '.secondi span' );
Con un semplice querySelector()
ho fatto selezionare a JavaScript i singoli elementi span
contenuti negli specifici dei contenitori. Adesso quello che manca è soltanto il codice che ci permetterà di aggiornare il loro contenuto.
Spostiamoci quindi all’interno della funzione aggiornaTimer()
e sostituiamo la porzione di codice timer.innerHTML
come segue:
giorni.innerHTML = ('0' + t.giorni).slice(-2); ore.innerHTML = ('0' + t.ore).slice(-2); minuti.innerHTML = ('0' + t.minuti).slice(-2); secondi.innerHTML = ('0' + t.secondi).slice(-2);
Ecco fatto, adesso hai un timer leggero e veloce che puoi personalizzare come meglio credi grazie ai tuoi CSS. Sei rimasto deluso perché alla fine ti ho fatto sporcare il tuo codice HTML con elementi ‘inutili’? Continua a leggere le conclusioni di questo articolo e scopri come sia possibile reimpostare il tutto per sfruttare JavaScript e far scomparire completamente il timer nel caso in cui questo linguaggio non venga interpretato!
Conclusioni
Siamo giunti al termine di un articolo che ritengo veramente interessante, in fin dei conti non abbiamo fatto altro che creare un timer in puro JavaScript. Ah già, quasi dimenticavo, al momento il nostro timer non è in puro JavaScript perché facciamo riferimento ad alcuni elementi che abbiamo inserito nel nostro HTML.
Però come ti avevo descritto qualche articolo fa, grazie alla sintassi ES2015 abbiamo diversi trucchi nelle nostre maniche e penso che sia proprio giunto il momento di mostrarti l’utilità di uno di questi:
timer.innerHTML = `<div class="giorni"> <span>${t.giorni}</span> <p>Giorni</p> </div> <div class="ore"> <span>${t.ore}</span> <p>Ore</p> </div> <div class="minuti"> <span>${t.minuti}</span> <p>Minuti</p> </div> <div class="secondi"> <span>${t.secondi}</span> <p>Secondi</p> </div>`;
Praticamente, grazie alla funzionalità dedicata delle template string e al carattere speciale backtick non facciamo altro che dire a JavaScript che deve rispettare la struttura del codice che abbiamo inserito al suo interno, in questo modo non dobbiamo fare altro che utilizzare i nostri elementi HTML e il simbolo ${}
per includere direttamente il valore delle variabili che specifichiamo all’interno delle parentesi graffe.
Eccoti un esempio di come potrebbe risultare il tuo timer con un po’ di stile CSS 😉
Ci sarebbe veramente molto altro di cui parlare, come per esempio personalizzare questo timer per fare in modo che salvi un cookie nel browser del nostro visitatore e che lo utilizzi per definire la scadenza in modo da realizzare timer personalizzati per ciascun visitatore. Oppure potremmo fare in modo di preparare in anticipo delle scadenze e lasciare che il timer si mostri e si nasconda automaticamente all’interno delle nostre pagine senza richiedere modifiche al codice.
Potremmo addirittura andare a costruire assieme un plugin WordPress che svolga queste stesse funzioni!
Insomma, come avrai capito tu stesso le possibilità sono veramente tante ed estendere questo argomento e affrontarlo sotto diversi aspetti. Purtroppo, o per fortuna, non voglio proseguire oltre perché ritengo che questo articolo sia già abbastanza completo.
Però se sei curioso e vuoi scoprire ancora di più, non esitare a farmelo sapere all’interno dei commenti che trovi qua sotto. Sarò più che lieto a preparare un nuovo articolo e approfondire ulteriormente questi aspetti!
Mickyhood dice
Ciao, ottimo articolo. Ma mi chiedevo: come fai a darglielo “in pasto” a WordPress una cosa così? Cioè immagino tu debba creare un file .js per andargli poi a dare la risorsa direttamente dalla pagina di WP. O sbaglio?
Andrea Barghigiani dice
Ciao Micky,
grazie mille per i complimenti! Ci fa un incredibile piacere sapere che i nostri articoli sono stati utili e apprezzati.
Venendo invece alla tua richiesta poter inserire un timer all’interno di una pagina WordPress può essere svolto in diversi modi e dipende molto dalle funzionalità che vuoi inserire.
Le prime soluzioni che mi vengono a mente sono l’inserimento tramite shortcode o widget cosa che ti permetterebbe anche di richiamare dei parametri che ti permetteranno di personalizzare l’output definendo la scadenza del timer stesso.
Altri metodi potrebbero essere quelli di iniettare direttamente il codice all’interno di una pagina del tuo tema ma questo comporterebbe la necessità di aprire il file ogni volta che si desidera fare una modifica al timer e inoltre non ti permetterebbe di averne più di uno all’interno dell’installazione (a meno che tu non desideri creare tanti blocchi di codice quanti timer hai bisogno di usare).
In effetti questa tua richiesta mi ha fatto pensare che potremmo creare un nuovo articolo dove mostriamo come creare un plugin WordPress che permetta di implementare questa funzionalità.
Vedremo di pubblicarlo nei prossimi mesi dato che abbiamo già altri articoli pronti da pubblicare.
Grazie per essere passato da queste parti e non esitare a commentare qualsiasi altro nostro articolo per avere altri chiarimenti.
A presto,
Andrea
Stefano Ferrarini dice
Dopo aver letto il tuo articolo mi si sono schiarite le idee sulla programmazione in java, grazie
Stefano Ferrarini
Andrea Barghigiani dice
Ciao Stefano, è un piacere sapere che i nostri contenuti aiutano le persone a capire meglio i linguaggi di programmazione utilizzati nel web. Ricorda che oltre agli articoli sul nostro portale pubblichiamo anche corsi dettagliati che ti aiuteranno a migliorare ulteriormente le tue conoscenze.
Spero di vederti nuovamente sul nostro portale.
A presto,
Andrea