Categorie
HTML5 JavaScript

La nuova HTML5 History API cosa cambia

L’oggetto History per dire la verità non è affatto nuovo, ma già dai primi anni novanta i browsers supportavano le sue scarse funzionalità. L’oggetto history fin dall’inizio ha fornito un mezzo per lavorare con la storia di un particolare tab del browser (o una finestra prima che la navigazione a schede diventasse la norma).

Tuttavia le sue funzionalità erano limitate alla possiblità di simulare i pulsanti Avanti – Indietro del browser e poco di più. Con l’ascesa delle pagine Web dinamiche (AJAX), abbiamo bisogno di più controllo. Per fortuna, HTML5 ci dà questo controllo, estendendo l’API JavaScript History.

La vecchia History API

Inutile negare l’importanza degli URLs. Essi sono il mezzo per accedere alla sterminata mole di informazioni che si trova sul web. Possiamo usarli per creare collegamenti su qualsiasi documento HTML oppure copiarli per condividere le informazioni con i nostri amici.
Come accennato nell’introduzione la vecchia API History JavaScript offriva funzionalità molto semplici. Tutto quello che potevamo fare era contare il numero di elementi presenti nella storia di una finestra e navigare avanti ed indietro su questa:

// Verifico la lunghezza dello stack history
console.log(history.length);

// Mi sposto in avanti nello stack
console.log(history.forward());

// Mi sposto indietro nello stack
console.log(history.back());

//Mi sposto in avanti o indietro di un certo numero di elementi
console.log(history.go(-2));

Il problema

Con l’avvento di AJAX non c’è dubbio che l’esperienza utente nella navigazione ha subito un evidente miglioramento. Infatti la possibilità di poter eseguire uno scambio di dati in background fra browser e server, consente l’aggiornamento dinamico di una pagina web senza l’intero ricaricamento di questa.
Tuttavia uno dei primi problemi sorti con questa tecnologia è stato la possibilità di consentire all’utente di tornare ai contenuti visitati dopo una chiamata AJAX, visto che questa non modifica l’URL della pagina. Difatti con la vecchia API non era possibile modificare l’URL senza dover ricaricare la pagina.
Se io quindi invio ad un amico un link ad una pagina (dopo aver eseguito una richiesta AJAX) lui non vedrà lo stesso risultato che avevo intenzione di condividere in quanto anche se ho caricato un nuovo contenuto l’URL è rimasto lo stesso.

L’oggetto Location

Con la nuova API HTML 5 sono state aggiunte nuove capacità come manipolare l’URL del browser mantenendo lo stato, anche se questo, per la verità, era già (in parte) possibile prima attraverso l’oggetto location:

//Ottengo l'URL completo
console.log(location.href) //"http://www.miosito.it/"
//Ottengo solo l'hash
console.log(location.hash) //(stringa vuota visto che non esiste)
//Setto l'hash
location.hash = "contatti"
//Ottengo l'URL completo
console.log(location.href) //"http://www.miosito.it/#contatti"
//Ottengo l'hash
console.log(location.hash) //"#contatti"

Gli hashbang

Prima di HTML 5 l’utilizzo dell’hashbang (#!) era estremamente diffuso, infatti ci permetteva (e ci permette ancora) di risolvere almeno in parte il problema dei contenuti dinamici.
Come visto nell’esempio precedente con location.hash sono in grado di poter modificare l’hash dell’URL, non è molto, ma è già qualcosa.
Applicazioni note che fanno largo uso di AJAX come Facebook o Twitter, per esempio, in passato hanno utilizzato pesantemente questo “trucco”.
La tecnica in sè è piuttosto semplice, si memorizzano info nell’URL (dopo #!), le si analizzano (lato client) e si utilizza AJAX per caricarne il contenuto. Tutto molto bello ma ci sono anche i “lati oscuri”:

  • Avremo URL differenti che puntano allo stesso contenuto, ad esempio miosito.it/contatti e miosito.it/#!contatti. Twitter eseguiva appunto un redirect lato server per mantenere un unico insieme di URL attivi per tutti i contenuti del sito, quindi twitter.com/simogrima/ subiva un redirect nel nuovo stile twitter.com/#!/simogrima
  • In caso di JavaScript disabilitato sul browser il contenuto mostrato non sarebbe quello corretto.
  • Il routing deve essere eseguito esclusivamente lato client visto che il server non riceve il percorso che segue gli hashbang.
  • Gli URLs sono veramente brutti!

[box type=”note”]Gli hashbang non sono mai stati considerati come una soluzione a lungo termine, anzi i puristi hanno sempre criticato il loro utilizzo anche prima della nuova API.[/box]

La nuova API History

La nuova API History è piuttosto semplice, ed è nata appunto per permetterci di risolvere i problemi di cui abbiamo parlato in precedenza, permettendoci di trasformare gli URLs senza dover ricaricare la pagina.

History objects represent their browsing context’s session history as a flat list of session history entries. Each session history entry consists of a URL and optionally a state object, and may in addition have a title, a Document object, form data, a scroll position, and other information associated with it.

Interfaccia History

  • history.back(): Consente di passare all’URL precedente nello stack history.
  • history.forward(): Consente di passare all’URL successivo nello stack history.
  • history.go([ delta ]): Consente di passare all’URL in corrispondenza di uno specificio indice dello stack storia. Ad esempio history.go(-4)
  • history.pushState(data, title [, url ] ): Aggiunge un URL allo stack con uno stato specifico. Es.history.pushState({foo: "bar"}, "titolo", "pagina.html"), dove il primo argomento è un oggetto di stato.
  • history.replaceState(data, title [, url ] ): Aggiorna l’URL corrente nello stack con le informazioni fornite. Ad esempio history.replaceState({foo: "bar"}, "titolo", pagina.html)
  • history.length: Restituisce la quantità di URL presenti nello stak history.
  • history.state: Restituisce l’oggetto di stato nella parte superiore dello stack history.

Attenzione: i metodi pushState() e replaceState() sono molto simili ma differiscono in una cosa sostanziale. Mentre il primo aggiunge una voce nello stack history, il secondo si limita ad aggiornare la voce corrente. Se per esempio vogliamo cambiare l’URL dinamicamente in base al testo immesso in un campo input non avrà senso aggiungere tutte le volte un elemento nello stack.

<input type="text" id="ricerca" />
<script>
$("#ricerca").keyup(function() {
  history.replaceState(null, null, "ricerca?=" + $("#ricerca").val());
});
</script>

[box type=”note”]Sono nate anche diverse librerie che ci vengono in aiuto per i modelli più comuni di utilizzo come per esempio caricare dati via Ajax od intercettare links, una di queste è sicuramente History.js[/box]

Supporto

Ancora non tutti i browsers supportano questa API, per esempio IE inizerà a supportarla dalle versione 10.
Dovremo quindi utilizzare metodi come pushState() o replaceState() solo quando sono riconosciuti dal browser, garantendo però la navigazione all’interno delle pagine anche a chi utilizza browsers più datati.
Utilizzando il classico esempio di una chiamata AJAX, prima di tutto bisogna cercare di inserire sempre all’interno dell’attributo href l’URL della pagina da caricare anche se abbiamo intenzione di eseguire una richiesta asincrona. Questo garantirà la funzionalità anche sui browsers che non supportano JavaScript.
Poi possiamo utlizzare (per esempio) uno script come questo (lo script, come il precedente, prevede l’uso di jQuery):

if ("pushState" in history) {
    $("nav a").on("click", function() {
        history.pushState(null, this.textContent, this.href);
        return false;
    });
}

Un esempio di utilizzo è appunto il Crome Web Store. Una volta arrivati sulla home possiamo navigare tra le varie categorie senza dover ricaricare la pagina (chiamate Ajax), tuttavia l’URL cambia in base alla categoria scelta.
Visto che IE come detto ancora (versione 9) non supporta questa API ecco come cambierà l’URL dopo aver cliccato sulla categoria estensioni:
Chrome: https://chrome.google.com/webstore/category/extensions
IE: https://chrome.google.com/webstore/category/home#category/extensions
Notiamo come ancora l’URL creato su IE contenga la tecnica dell’hash non potendo fruire delle nuove potenzialità dell’API HTML5
Attraverso questo indirizzo possiamo essere sempre aggiornati sul supporto della nuova API

In conclusione

Spero che questo articolo abbiamo chiarito meglio le novità introdotte dalla nuva API History.
Una delle prime cose da fare quando si inizia a sviluppare un nuovo sito riguarda la strutturazione e l’organizzazione degli URLs. Questi dovranno essere accessibili anche senza il supporto JavaScript.
Dobbiamo anche tenere a mente che dovranno essere presentate sempre le stesse info quando l’utente aggiorna la pagina. Può sembrare ovvio, ma non lo è quando si lavora molto con chiamate AJAX. E’ fondamentale che l’URL creato tramite pushState() sia reale e che risponda sul server in caso di chiamata diretta.

Risorse

http://www.w3.org/TR/html5/history.html
http://caniuse.com/#search=history

Una risposta su “La nuova HTML5 History API cosa cambia”

Excellent goods from you, man. I have understand your stuff previous to and you’re just extremely magnificent. I actually like what you have acquired here, certainly like what you are stating and the way in which you say it. You make it entertaining and you still care for to keep it sensible. I can’t wait to read far more from you.
This is actually a terrific site.

Lascia un commento

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

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.