Guida Html5

135
Introduzione L'obiettivo di questa guida è fornire agli autori (Web developers, Webmasters, grafici e chiunque veicoli contenuti formattati tramite codice HTML[5]) un primo strumento utile per entrare in contatto con le specifiche del nuovo linguaggio; si propone inoltre di essere un valido mezzo per la consultazione delle singole nuove features introdotte. La guida non tratta HTML nel suo complesso ma si concentra sulle differenze che intercorrono tra la versione 4.01 e la versione 5. Fonti e metodologia Per costruirla mi sono avvalso dei diversi documenti (Recommendations) che il W3C mette a disposizione; queste fonti ne hanno ispirato organizzazione e struttura ed hanno fornito lo spunto per redigere i vari capitoli. N.B.: Laddove ho percepito nella documentazione distonie che potessero essere fonte di diverse interpretazioni, quindi potenzialmente generanti entropia, ho stralciato le informazioni dubbie cercando di isolare quelle certe, questo approccio è stato adottato in ragione della natura mutevole del draft, con la convinzione che la raffinazione futura possa modificare le sfumature, ma difficilmente stravolgere i concetti base. Le definizioni formali di ogni elemento sono mie personali traduzioni di quelle fornite nelle specifiche (nelle quali non esiste un paragrafo "definizione formale"), talvolta integrate con esempi di utilizzo (mutuati dal documento, riadattati od ex-novo) quando questi si siano resi fondamentali per massimizzare la comprensione del contesto. Le espressioni "elemento" e "tag" sono stati considerati a tutti gli effetti sinonimi. Lo stesso principio di equivalenza è stato adottato per i termini "browser" e "user-agent". HTML5 HTML5 è un linguaggio di markup attualmente in fase di definizione. Il documento di specifica che lo descrive consiste al momento in una bozza in lavorazione (working draft); rappresenta l'evoluzione diretta di HTML 4.01, del quale è designato essere il successore.

description

Guida ad htlm 5

Transcript of Guida Html5

Page 1: Guida Html5

IntroduzioneL'obiettivo di questa guida è fornire agli autori (Web developers, Webmasters, grafici e chiunque veicoli contenuti formattati tramite codice HTML[5]) un primo strumento utile per entrare in contatto con le specifiche del nuovo linguaggio; si propone inoltre di essere un valido mezzo per la consultazione delle singole nuove features introdotte. La guida non tratta HTML nel suo complesso ma si concentra sulle differenze che intercorrono tra la versione 4.01 e la versione 5.

Fonti e metodologia

Per costruirla mi sono avvalso dei diversi documenti (Recommendations) che il W3C mette a disposizione; queste fonti ne hanno ispirato organizzazione e struttura ed hanno fornito lo spunto per redigere i vari capitoli.

N.B.: Laddove ho percepito nella documentazione distonie che potessero essere fonte di diverse interpretazioni, quindi potenzialmente generanti entropia, ho stralciato le informazioni dubbie cercando di isolare quelle certe, questo approccio è stato adottato in ragione della natura mutevole del draft, con la convinzione che la raffinazione futura possa modificare le sfumature, ma difficilmente stravolgere i concetti base.

Le definizioni formali di ogni elemento sono mie personali traduzioni di quelle fornite nelle specifiche (nelle quali non esiste un paragrafo "definizione formale"), talvolta integrate con esempi di utilizzo (mutuati dal documento, riadattati od ex-novo) quando questi si siano resi fondamentali per massimizzare la comprensione del contesto.

Le espressioni "elemento" e "tag" sono stati considerati a tutti gli effetti sinonimi. Lo stesso principio di equivalenza è stato adottato per i termini "browser" e "user-agent".

HTML5

HTML5 è un linguaggio di markup attualmente in fase di definizione. Il documento di specifica che lo descrive consiste al momento in una bozza in lavorazione (working draft); rappresenta l'evoluzione diretta di HTML 4.01, del quale è designato essere il successore.HTML5 è definito in modo da essere retrocompatibile: se da un lato agli autori si vieta in buona sostanza l'utilizzo dei vecchi elementi non inclusi nella nuova specifica, dall'altro è richiesto agli user-agents di mantenerne il supporto al fine di garantire la compatibilità con i documenti redatti in passato; il linguaggio prevede quindi requirements diversi per autori e user-agents eliminando di fatto la necessità di indicare le features obsolete come deprecate.

Enti e gruppi coinvolti

La stesura delle specifiche è a carico del W3C (World Wide Web Consortium) e del WHATWG (Web Hypertext Application Technology Working Group), un gruppo di professionisti provenienti da aziende fortemente interessate come Apple, Mozilla, ed Opera. Fu proprio il WHATWG a spendersi inizialmente, correva l'anno 2007, affinché il W3C si orientasse verso HTML5 a discapito di XHTML 2.0, ne propose il nome e ne ispirò la filosofia. In seguito alle pressioni ricevute, direttamente proporzionali al peso degli attori in causa, il W3C nel 2009 chiuse ufficialmente lo sviluppo di XHTML 2.0 ed iniziò a dedicarsi a tempo pieno alla stesura delle specifiche di HTML5/XHTML5.

Page 2: Guida Html5

RoadMap

La data attualmente prevista per la chiusura del processo di definizione è indicata intorno alla metà del 2014.

Data ultimo draft disponibile al momento della stesura di questa guida

4 Febbraio 2012

Perchè HTML5

La motivazione principale addotta per giustificare la necessità di creare un nuovo standard è dichiarata esplicitamente in uno stralcio del paragrafo 1.1 del documento provvisorio di specifica, di cui riporto la (mia) traduzione:

L'area più importante che (l'attuale) HTML non copre adeguatamente è quel nebuloso (vagamente definito) soggetto conosciuto come "Web Application". Questo documento cerca di risolvere questo problema e parallelamente di aggiornare le specifiche HTML per dare risposta alle questioni emerse negli ultimi anni.

L'obiettivo è in buona sostanza di semplificare il lavoro degli sviluppatori (e quindi delle aziende coinvolte nella creazione di Web applications) che negli ultimi anni hanno dovuto elaborare soluzioni, a volte molto complesse, per superare le limitazioni di HTML, un linguaggio non nativamente progettato per lo sviluppo di articolate interfacce grafiche e sofistificate interazioni con l'utente.

HTML5 e XHTML5

HTML5 possiede una serializzazione HTML (tipo MIME text/html) ed una serializzazione XML (tipi MIME application/xhtml+xml, application/xml), il nome della quale è XHTML5. Il working draft puntualizza:

Esistono varie sintassi concrete (implementazioni) che possono essere utilizzate per trasmettere le risorse che usano questo linguaggio "astratto" (HTML5). Due di queste sono definite in questo documento. La prima è la sintassi HTML [..] La seconda è quella XHTML, che è una applicazione di XML. Quando un documento viene trasmesso come application/xhtml+xml è trattato come un documento XML dal browser e processato coerentemente.

Adoption

Benché il linguaggio non sia ancora uno standard e malgrado le specifiche siano ancora parziali (quindi potenzialmente soggette a modifiche) i maggiori produttori di browsers migliorano la compatibilità HTML5 dei propri software ad ogni nuova release.Sussistono d'altra parte sensibili differenze tra produttore e produttore e soprattutto tra versioni recenti ed obsolete dei vari browsers presenti sul mercato.

Esistono svariate tabelle comparative sull'argomento e risorse online che permettono di valutare nei fatti quanto il proprio browser aderisca alle nuove specifiche, tra i più utilizzati strumenti online cito http://html5test.com; nel mese di Gennaio 2012 la situazione era la seguente (nota: a punteggio più alto equivale maggiore aderenza alle specifiche, max = 475 punti):

Page 3: Guida Html5

Google Chrome 16.0 373Mozilla Firefox 9.0 330

Opera 11.60 329Apple Safari 5.1 302

MS IE 9 141

Nella prossima lezione vedremo una breve cronologia dell'evoluzione del linguaggio HTML dagli anni '90 ad oggi.

Storia e cronologia di HTMLIl lungo cammino verso HTML5 parte dalla prima definizione di HTML avvenuta all'inizio degli anni '90. Il neonato Internet aveva bisogno di un linguaggio di formattazione dei contenuti che li rendesse fruibili in modo organizzato, questi sarebbero poi stati veicolati all'utente avvalendosi di un browser, un software cioè che li avrebbe mostrati così come indicato dai comandi (tags) che componevano il documento (ipertesto) HTML assieme all'informazione pura.Tim Berners-Lee, padre del Web, lo definì basandosi sul metalinguaggio SGML (Standard Generalized Markup Language) e gli affiancò un protocollo di trasporto, il ben noto HTTP.

Da HTML Tags ad HTML 4.01

Negli anni successivi l'affermazione del Web con la sua repentina ed inarrestabile diffusione aveva creato la necessità  di estendere e migliorare il linguaggio originale (HTML Tags), inizialmente composto da una manciata di elementi. Dopo alcune revisioni avvenute tra il 1991 ed il 1992, nel 1993 Lee insieme allo IETF (Internet Engineering Task Force, una comunità di tecnici interessata allo sviluppo di Internet) pubblicò "Hypertext Markup Language (HTML)" Internet-Draf, il primo documento ufficiale che proponeva (proposal) una bozza avente lo scopo di formalizzare il linguaggio.

Dopo ulteriori revisioni, il lavoro di stesura delle specifiche sfociò in HTML 2.0, a metà  del 1993.

Nel 1995 lo IETF rese pubblico un nuovo proposal che introduceva HTML 3.0. La specifica non ebbe successo per vari motivi, non ultimo dei quali l'imperversante guerra dei browser che in quel momento storico intercorreva tra Netscape e Microsoft.Le due aziende decisero di implementare solamente un subset delle funzionalità descritte nelle 150 pagine del documento aggiungendo al contempo estensioni proprietarie che miravano soprattutto al controllo dello stile e del look&feel delle pagine web (visual markup).Questo approccio era in aperto contrasto con la filosofia accademico/tecnica che intendeva HTML come un linguaggio esclusivamente di formattazione (markup).

Con l'abbandono dello IETF, formalizzato con la chiusura del proprio HTML Working Group nel 1996, la prima Recommendation del W3C uscì nel 1997 (HTML 3.2). Il documento si proponeva di ridurre la distanza tra le estensioni proprietarie promuovendone una sintesi accettabile ed adottando in parte i tags "stilistici" di Netscape.

Nel dicembre 1997 il W3C pubblicò una nuova Recommendation: HTML 4.0 (nome in codice "Cougar") che prevedeva tre varianti:

Strict: gli elementi deprecati erano proibiti.

Page 4: Guida Html5

Transitional: gli elementi deprecati erano permessi. Frameset: in buona sostanza veniva permesso l'utilizzo dei soli elementi strettamente legati

ai frames.

HTML 4.0 inoltre deprecava i tags Netscape relativi allo stile, tra i quali il tag font, caldeggiando in alternativa l'uso dei CSS (Fogli di stile - Cascading Style Sheets).

Preceduta e seguita da alcune piccole correzioni (errata), nel Dicembre del 1999 fu pubblicata la Recommendation HTML 4.01 che attualmente rimane l'ultima rilasciata per il linguaggio.

XHTML

XHTML (eXtensible HyperText Markup Language) è una applicazione di XML così come HTML lo è di SGML. Il W3C fornisce questa definizione per la prima versione del linguaggio:

XHTML 1.0 è una riformulazione di HTML 4.01 in XML, combina la robustezza di HTML4 con la potenza di XML.

Il documento XHTML può essere validato da un parser XML, il documento HTML al contrario ne richiede uno specifico.

Qualche caratteristica:

XML è case-sensitive per elementi ed attributi. il processamento di un documento che produca errori di parsing semplicemente viene

terminato. il doctype deve essere sempre presente perchè il documento possa essere validato. tutti i tags devono essere chiusi.

XHTML è quindi molto più restrittivo di HTML, in conseguenza del fatto che XML di cui è applicazione è un subset molto più restrittivo di SGML rispetto a quanto lo sia HTML.

Tra gli obiettivi della sua creazione la volontà di spingere gli autori di contenuti Web verso una sintassi più vicina all'XML allo scopo di semplificare l'interoperabilità con altri formati XML come ad esempio SVG (Scalable Vector Graphics).

La versione 1.0 diventò Recommendation W3C il 26 Gennaio 2000.

La spinta successiva soffiò nella direzione della modularizzazione XHTML, ossia la pacchettizzare del linguaggio in moduli con lo scopo di renderlo estensibile. L'idea era quella di renderlo flessibile per l'utilizzo su media come dispositivi mobile e TV connesse alla rete.

Il lavoro portò alla realizzazione di una nuova specifica: XHTML 1.1.

Oltre ad eliminare alcuni attributi ed aggiungere dei tags per migliorare il supporto per le lingue asiatiche il linguaggio doveva essere trasmesso con un media type particolare (application/xhtml+xml) e non come HTML; questa limitazione nè limitò fortemente l'adozione tanto da spingere nel 2009 il W3C a rilassare la restrizione permettendo che il documento si potesse servire come HTML.

Page 5: Guida Html5

Venne iniziato poi il lavoro di stesura delle specifiche di XHTML 1.2 abbandonato definitivamente nel 2010.

XHTML 2.0

Nel 2002 il W3C rilasciò il primo draft per un nuovo linguaggio che non prevedeva la retrocompatibilità nè con XHTML 1.x nè con HTML 4.01.XHTML 2.0 doveva adottare XML DOM al posto del Document Object Model, tra le novità prevedeva che ogni elemento avrebbe potuto comportarsi come un link a fronte della sola aggiunta di un attributo href e includeva tra gli altri un nuovo tag nl per implementare liste di navigazione.Le pressioni esercitate in senso contrario al linguaggio dal WHATWG, dovute in massima parte al disaccordo sulla mancanza di backward compatibility, portarono all'abbandono definitivo del progetto nel 2009 spianando definitivamente la strada ad HTML5.

Il DOCTYPE di HTML5

La sintassi HTML di HTML5 richiede la dichiarazione di un doctype in testa al documento per assicurare che il browser renderizzi correttamente la pagina; quando la risorsa è servita come HTML (tipo MIME text/html) la sintassi corretta è riportata nel codice minimale che segue:

<!doctype html><html> <head> <meta charset="UTF-8"> <title>Titolo documento</title> </head> <body> <p>paragrafo</p> </body></html>

Notate l'utilizzo di meta per indicare l'encoding della pagina, la sintassi affianca la già precedentemente valida dichiarazione equivalente:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

L'esempio pone in evidenza la semplificata dichiarazione del doctype, diversa dalla specifica HTML 4.01 che ne prevede tre diverse, esattamente come per XHTML 1.0.

Come confronto riporto le sintassi sino ad ora utilizzate:

HTML 4.01 Strict

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

XHTML 1.0 Strict

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

HTML 4.01 Transitional

Page 6: Guida Html5

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

XHTML 1.0 Transitional

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

HTML 4.01 Frameset

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

XHTML 1.0 Frameset

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

In XHTML 1.1 la dichiarazione prevedeva questa sintassi:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

Come emerge dagli esempi le dichiarazioni dei Doctype in HTML 4.01 ed XHTML richiedevano un rimando ad un DTD poichè il linguaggio era basato su SGML; HTML5 non è implementazione di SGML, quindi non lo richiede.

La dichiarazione è case-insensitive. Questo si traduce nell'equivalenza tra:

<!doctype html>

e

<!DOCTYPE html>

Personalmente preferisco "normalizzare" il codice scrivendo tags ed attributi in lowercase, per questo motivo opto per la prima variante.

Qualora si intendesse servire il documento come XML (MIME application/xhtml+xml oppure application/xml) il doctype non sarebbe richiesto; di seguito un esempio conforme alla sintassi XML di HTML5:

<?xml version="1.0" encoding="UTF-8"?><html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Titolo documento</title> </head> <body> <p>paragrafo</p> </body></html>

Page 7: Guida Html5

Organizzare i contenuti con HTML5 - sectionHTML5 introduce un buon numero di nuovi elementi, inizieremo a descrivere quelli strettamente connessi alla organizzazione dei contenuti ed alla strutturazione della pagina.

Il working draft elenca in questa macrocategoria i seguenti elementi:

section article aside hgroup header footer nav figure figcaption

Darò per ognuno, oltre alla traduzione della definizione fornita del W3C, qualche suggerimento per l'utilizzo, attenendomi quanto più strettamente possibile alle linee indicate nel documento.

Prima di iniziare permettetemi una paio di brevi digressioni, la prima a proposito di ciò che il W3C descrive come Sectioning content: si tratta del contenuto che definisce l'ambito di headings (h1, h2, h3, h4, h5, h6, hgroup) e footers. Gli elementi che fanno parte di questa classificazione sono:

article aside nav section

ai quali si aggiungono i sectioning root: blockquote, body, details, fieldset, figure, td.

Ognuno di questi elementi potenzialmente possiede un heading (e quindi un outline) ed un footer; tratteremo brevemente l'outline nell'ambito della descrizione del tag hgroup.

La seconda digressione riguarda i global attributes, gli attributi globali, applicabili cioè a tutti gli elementi, compongono la lista:

accesskey class dir id lang style tabindex title

HTML5 ne introduce di nuovi:

Page 8: Guida Html5

contenteditable: indica che l'elemento rappresenta una area editabile; è possibile per l'utente modificare il contenuto e manipolare il markup, dedicheremo uno spazio apposito nella guida per questo attributo.

contextmenu: da utilizzare per puntare ad un context menu fornito dall'autore. gli attrinuti data-* (attributi custom definibili dall'utente) draggable e dropzone: da utilizzare insieme alle nuove Drag&Drop API. hidden: (booleano) indica che un elemento non è ancora o non è più rilevante. Il browser

non deve mostrare elementi che abbiano questo attributo. role e aria-* (assistive technology). spellcheck: esplicitato per indicare se il contenuto richieda un controllo a livello di spelling.

Section

Definizione formale

L'elemento section rappresenta una sezione generica del documento o dell'applicazione. Una sezione, in questo contesto, è un raggruppamento tematico di contenuti, tipicamente corredato da un heading.

La specifica indica chiaramente quando utilizzarlo e quando avvalersi di altri costrutti. Alcuni casi d'uso suggeriti:

un capitolo in una guida. i vari tabs di un documento (ovviamente strutturato a tabs). le sezioni numerate di una tesi. le varie sezioni (boxes) di una Home Page che raggruppano contenuti generici

(introduzione, contatti, news).

section deve essere quindi utilizzato ogni qualvolta si intenda veicolare del contenuto che richiede una intestazione. L'elemento non deve essere utilizzato come aggregatore di stili per contenuti disomogenei; in questi casi è accettato l'utilizzo del tag div, contenitore più generico, che rimane nelle specifiche benché se ne scoraggi l'uso: il draft lo definisce letteralmente "last resort" (traducibile con "ultima spiaggia").

Nel caso di posts di un blog o di un forum, per articoli di un giornale o commenti inseriti dall'utente è preferibile l'utilizzo dell'elemento article, che vedremo a breve.

Ecco l'esempio minimale della sintassi di section fornito nel draft:

<section><h1>Titolo sezione</h1><p>Contenuti</p></section>

Notate la presenza di un heading, rappresentato dall'elemento h1.

Ora vediamone una applicazione leggermente più elaborata (che ricorre volutamente al "last resort" come contenitore esterno):

<!doctype html><html><head>

Page 9: Guida Html5

<title>Guida HTML5</title> <style> #container { margin: 0 auto; width: 400px;} </style></head><body><div id="container">

<section><h1>Introduzione ad HTML5</h1><p>Definizione</p><p>Perchè HTML5</p>

</section> <section>

<h1>Storia</h1><p>Da HTML Tags ad HTML 4.01</p><p>XHTML</p>

</section> <section>

<h1>Nuovi tags</h1><p>Section</p><p>Article</p><p>Nav</p><p>Aside</p><p>...</p>

</section> </div></body></html>

Ecco il risultato mostrato da Firefox:

Benché le sezioni possano contenere headings di qualsiasi livello o rank (da 1 a 6) il W3C consiglia l'uso di h1 o comunque di un heading correlato al livello di indentazione della sezione stessa.

Organizzare i contenuti con HTML5 - article, nav ed asideArticle

Definizione formale

L'elemento article rappresenta una porzione di contenuto indipendente di un documento, di una pagina o di un sito, tale porzione è sostanzialmente distribuibile e riusabile indipendentemente dal contesto in cui viene definita.

Page 10: Guida Html5

Come accennato nella descrizione di section, campi di applicazioni di article possono essere i un post di un forum, un articolo di un magazine, un commento inserito da un utente.Anche una widget interattiva è candidata a rappresentare il contenuto di un elemento article.

I tags article possono essere innestati e tipicamente contengono un heading per il titolo; un esempio di caso reale riportato nella documentazione: un articolo in un blog ed alcuni commenti ad esso correlati. A scopi didattici ho semplificato l'esempio eliminando alcuni elementi che non sono stati ancora trattati in questa guida ed aggiungendo (poco) stile:

<!doctype html><html><head> <title>Il mio Blog</title> <style> article { border: 1px solid #ccc; width: 350px; padding: 4px; } section article { width: 300px; margin: 0 auto; } </style></head><body> <article> <h1>Titolo articolo</h1> <p>In questo articolo parleremo di ...</p> <section> <h1>Commenti</h1> <article> <p>Postato da: Riccardo Brambilla</p> <p>Pessimo articolo, sei stato esageratamente prolisso.</p> </article> </section> </article></body></html>

Il risultato in Opera:

È interessante notare il nesting dei due article(s) e le due diverse funzioni che ricoprono; se il ruolo assegnato al primo è quello più logicamente prevedibile (contenere il testo dell'articolo), l'utilizzo del secondo è più raffinato (è il contenitore di un commento all'articolo stesso).

La scelta di ricorrere al tag section come wrapper del commento ci permette di rivelarne un impiego solo apparentemente diverso dagli esempi presentati nel paragrafo ad esso dedicato; se infatti in questo caso non si tratta di elencare punti di un sommario è altrettanto chiara la coerenza rispetto alla definizione formale, poichè si intende trasmettere una informazione che richiede indubitabilmente la presenza di un heading.

nav

Definizione formale

L'elemento nav rappresenta la sezione della pagina che contiene i link a pagine esterne o ad altre parti della pagina stessa; è una sezione di link di navigazione.

Page 11: Guida Html5

La specifica puntualizza che nav non è pensato per contenere un generico gruppo di link presente in pagina, lo scopo principale per cui è stato introdotto è quello di raggruppare i link costituenti la navigazione principale (e se presente quelli della secondaria) del sito. Benché possa essere utilmente impiegato per contenere i link tipicamente presenti in un tag footer (elemento che vedremo nelle prossime lezioni) non è in quella situazione considerato necessario.

Il tipico contenuto di nav potrebbe essere una lista non ordinata (ul) di link di navigazione come esplicitato nell'esempio minimale che segue:

<nav> <ul> <li><a href="home.html">Home page</a></li> <li><a href="contatti.html">Contatti</a></li> <li><a href="dovesiamo.html">Dove siamo</a></li> </ul></nav>

È d'altra parte conforme alla specifica un elemento nav che contenga paragrafi a loro volta contenenti links, e che non utilizzi quindi liste.

aside

Definizione formale

L'elemento aside rappresenta una sezione della pagina che racchiude un contenuto solo tangenzialmente correlato a ciò che lo circonda e che può considerarsi come separato da esso. Queste sezioni sono spesso definite come sidebars (colonne laterali).

Il working draft attuale consiglia l'utilizzo di questo elemento per raggruppare contenuti pubblicitari ed elementi di navigazione che puntino all'esterno del documento.

Un box contenente l'archivio dei vecchi post di un blog, tipicamente collocato in una colonna sulla destra della pagina, è un potenziale candidato per l'impiego di aside; altrettanto calzante il caso di un gruppo di link che puntino a blog esterni (blogroll).

Altro possibile utilizzo: evidenziare una citazione all'interno di un articolo:

<p>Di professione Coder e Team Leader Riccardo ama molto la divulgazione scientifica:<q>Mi piacerebbe scrivere testi utili ed interessanti. La sfida in questi casi è ottenere che il lettore si appassioni all'argomento senza annoiarsi.</q></p>

<aside>Il mio sogno è di scrivere testi che appassionino il lettore.</aside>

<p>Nel frattempo si dedica allo sviluppo ...</p>

Page 12: Guida Html5

Organizzare i contenuti con HTML5 - header, hgroup e footerheader

Definizione formale

L'elemento header rappresenta un gruppo di informazioni introduttive o di aiuto alla navigazione.

Benché header sia primariamente pensato come un contenitore di headings questa applicazione non è l'unica possibile. L'elemento può essere utilmente impiegato per racchiudere qualsiasi contenuto abbia un intento introduttivo, come un sommario od un logo.

<header> <p>Benvenuti nel mio blog:</p> <h1>Ribrain Blog</h1></header>

N.B.: header non segna l'inizio di una sezione ma ne contiene solo l'intestazione.

È possibile definire più di un header in una pagina, il primo rappresentante l'introduzione alla pagina stessa, i successivi atti ad introdurre le varie sezioni presenti, come nell'esempio che segue:

<doctype html><html><head> <title>La mia Home Page</title></head><body> <header> <h1>Benvenuti nel mio sito personale</h1> <nav> <h1>Scopri le varie sezioni!</h1> <ul> <li><a href="home.html">Home</a> <li><a href="contatti.html">Contatti</a> <li><a href="dovesiamo.html">Dove siamo</a> </ul> </nav> </header> <div id="content"> <section> <header> <h1>News</h1> <p>Le novità più importanti della settimana, entra per scoprirle nel dettaglio.</p> </header> </section> <section> <header> <h1>Blog</h1> <p>Giorno per giorno, quello che mi ha colpito.</p> </header> </section> </div></body>

Page 13: Guida Html5

</html>

Come si evince dal codice header può contenere l'elemento nav; ho utilizzato section per definire i vari box poiché hanno, nella Home Page dell'esempio lo scopo di agire da sommario per le varie parti del sito: questo particolare utilizzo di section è esplicitamente indicato nel draft (vedi lezioni precedenti).

hgroup

Definizione formale

L'elemento hgroup rappresenta l'intestazione di una sezione. È utilizzato per raggruppare un set di elementi h1-h6 qualora l'heading possegga livelli multipli come sottointestazioni, titoli alternativi o taglines (slogan che solitamente accompagnano il brand, spesso riportati in corsivo ad es.: "Ribrain.Il tecnico al tuo servizio").

Nei casi di un sommario di un documento o di un indice (outline) il testo degli elementi appartenenti un tag hgroup è definito essere il testo dell'heading con rank più alto presente nel gruppo; qualora esistessero più elementi di uguale rank come il testo del primo di questi; laddove non esistesse alcun heading il testo di hgroup sarebbe una stringa vuota; altri heading (di più basso grado o rank) presenti in hgroup definiscono sottotitoli o sottointestazioni.

Un esempio minimale:

<hgroup> <h1>Storia di HTML</h1> <h2>Le prime fasi</h2></hgroup>

Un software che estraesse l'intestazione principale ignorando i sottotitoli (tale software esiste ed è detto outliner) mostrerebbe solo il testo dell'heading più alto in grado (rank) quindi "Storia di HTML".

hgroup non ha ovviamente senso laddove non vi sia necessità di utilizzare sottotitoli come nell'esempio che segue:

<article> <h1>Titolo dell'articolo</h1> <p>testo dell'articolo</p></article>

Nel caso in cui in aggiunta al titolo compaiano informazioni aggiuntive è corretto utilizzare l'elemento header:

<article> <header> <h1>Titolo dell'articolo</h1> <p>Redatto da Riccardo Brambilla</p> </header> <p>testo dell'articolo</p></article>

Page 14: Guida Html5

Quale è quindi lo scopo di introdurre hgroup? L'outliner. È aperta per questo motivo una vivace discussione che ha già portato una volta all'esclusione dell'elemento dalle specifiche, salvo poi reintegrarlo successivamente. Il destino di hgroup è di conseguenza, al momento, incerto..

footer

Definizione formale

L'elemento footer rappresenta il pié di pagina per il più vicino elemento che ne definisca l'ambito (article, aside, nav, section). Un footer tipicamente contiene informazioni a proposito della sezione a cui si riferisce come l'autore, link a documenti correlati, copyright.

Laddove il footer contenesse intere sezioni assumerà la funzione di appendice, di indice o di contenitore dei termini di lunghi contratti di licenza, nel caso in cui l'elemento parent più diretto fosse il body il footer si applicherà come pié di pagina per l'intero documento.

Il draft ricorda inoltre che sebbene tipicamente il footer appaia al termine di una sezione non è strettamente necessario definirlo come ultimo elemento.

La specifica consiglia inoltre di inserire informazioni come i contatti dell'autore e/o dell'editore in un tag address, opportunamente wrappato da un tag footer.

Il tag footer ha quindi l'effetto di sostituire linee di codice ora tipicamente definite in questo modo:

<div id="footer">© 2012 MrWebmaster.it - author Riccardo Brambilla</div>

con la nuova sintassi:

<footer>© 2012 MrWebmaster.it - author Riccardo Brambilla</footer>

Come esplicitato nella definizione l'elemento trova impiego anche nell'indicare informazioni addizionali di una sezione o di un articolo:

<article> <h1>Il tag footer</h1> <p>L'elemento footer rappresenta...</p> <footer>Pubblicato da Ribrain</footer></article>

L'elemento article qui definisce l'ambito del footer.

Ne deriva logicamente che possano esistere, come già descritto per il tag header, più elementi footer in un documento.

Una interessante annotazione presente nel draft ci indica come l'elemento possa utilmente contenere anche molto materiale: navigazione, testo e addirittura immagini. È in effetti un approccio molto comune nel design moderno dei siti web avvalersi dei cosiddetti "fat footers", sezioni molto consistenti in termini di spazio visivo occupato e di quantità di contenuti ospitati.

Page 15: Guida Html5

Organizzare i contenuti con HTML5 - figure e figcaptionfigure e figcaption

Definizione formale di figure

L'elemento figure rappresenta un insieme di elementi e testo, opzionalmente corredato da una didascalia, indipendente e tipicamente riconoscibile come entità atomica (nell'accezione di inscindibile) all'interno del documento.

Definizione formale di figcaption

L'elemento figcaption rappresenta la didascalia o legenda per il resto del contenuto dell'elemento che ne è parent (contenitore diretto), ossia dell'elemento figure.

Il draft indica tra gli usi consigliati della coppia figure-figcaption: illustrazioni, diagrammi, foto, frammenti di codice; i perfetti candidati sono elementi referenziati dal contenuto principale della pagina, ma che se anche fossero spostati in altre sezioni, ad esempio a lato della pagina stessa, non ne intaccherebbero il significato generale.

L'impiego tipico è il posizionamento e la descrizione di un immagine:

<!doctype html><html> <head> <style> body { font-family: "Tahoma", "Arial", sans-serif; font-size: 12px; letter-spacing: 1px; } figure { width: 280px; height: 380px; text-align: center; } figure img { padding: 10px; border: 1px solid #888; } </style></head><body><figure> <img src="bambola.png" alt="bambola"> <figcaption>Operazione alla bambola!</figcaption></figure></body></html>

Il risultato su Firefox:

Page 16: Guida Html5

N.B.: Non è obbligatorio indicare una figcaption.

L'elemento figure trova applicazione non solo per le immagini, può essere utilizzato anche per contenere video; ne è consentito l'uso anche con del semplice testo, magari per evidenziare una citazione, come indicato nelle specifiche:

<figure> <p>Cum in Italiam proficisceretur Caesar, Ser. Galbam cum legione XII ... </p> <figcaption><cite>Giulio Cesare (incipit Libro III). De bello Gallico, 50 A.C.</cite></figcaption></figure>

Va inoltre sottolineato come sia possibile inserire più elementi (ad esempio immagini) all'interno di figure, descritti da una unica didascalia:

<figure> <img src="casa-1.jpg" alt="foto originale"/> <img src="casa-seppia.jpg" alt="foto virata seppia"/> <img src="casa_bw.jpg" alt="foto bw"/> <figcaption>Le immagini mostrano i vari effetti grafici applicabili.</figcaption></figure>

Page 17: Guida Html5

I media elements di HTML5: video, audio, source e trackHTML5 introduce due elementi appositamenti creati per facilitare l'inserimento di contenuti multimediali con l'obiettivo dichiarato di colmare le lacune sul tema presenti nella precedente specifica; appartengono alla categoria dei media elements:

video audio

Sono strettamente legati ai media elements i seguenti elementi:

source track

Definizione formale di media element

I media elements (elementi multimediali) sono utilizzati per presentare all'utente filmati e files audio.

Definizione formale di media resource

Il termine media resource (risorsa multimediale) si riferisce al file multimediale nel suo complesso, un file video completo od un file audio completo. Una risorsa multimediale può contenere files audio multipli così come tracce video multiple. Dal punto di vista del media element la risorsa multimediale è semplicemente (nel caso di un video) la traccia selezionata correntemente; allo stesso modo se la risorsa è un file audio la risorsa multimediale è il risultato del mix di tutte le tracce (audio) correntemente selezionate.

È interessante notare come entrambi gli elementi possano riprodurre files video e audio. La differenza risiede nell'assenza nel tag audio di una area dedicata alla riproduzione dell'immagine ed all'inserimento di didascalie. Ambedue espongono delle APIs in modo che gli autori (programmatori) possano definire interfacce custom per le loro applicazioni, nel caso tale opportunità non venga sfruttata il failover atteso è l'utilizzo dell'interfaccia predefinita dello user-agent.

Sono definiti attributi comuni per entrambi gli elementi:

src: la locazione della risorsa da riprodurre. crossorigin: enumerazione che può valere anonymous/use-credentials; utilizzata per

richieste di risorse cross-domain. preload: enumerazione che può assumere i valori

o none: indica (in buona sostanza) allo user agent che l'autore non richiede una alta priorità per la fruizione della risorsa

o metadata: indica allo user agent che l'autore non richiede una alta priorità per la fruizione della risorsa ma che ritiene ragionevole (in termini di traffico) ottenere informazioni come dimensioni, primo fotogramma, lista delle tracce, durata ecc.

o auto: suggerisce allo user agent che la risorsa può essere trasmessa all'utente senza alcun rischio per il server.

Page 18: Guida Html5

autoplay: booleano; indica se la riproduzione debba essere iniziata automaticamente o no. mediagroup: può essere utilizzato per linkare risorse multimediali multiple (più di un file

video/audio) loop: attributo booleano che, se specificato, indica se l'elemento debba "riavvolgere" la

risorsa e farla ripartire dall'inizio una volta raggiunto il termine del contenuto. muted: attributo che indica lo stato di default dell'audio per una risorsa video. controls: attributo, se omesso, che indica allo user agent di farsi carico di mostrare

l'interfaccia dei controlli per la risorsa. Per controlli si intendono soprattutto i classici tasti play/pause e la barra di avanzamento.

Iniziamo la descrizione puntuale dei due elementi partendo da video.

video

Definizione formale

L'elemento video è utilizzato per mostrare filmati, video e files audio con didascalia.

Il draft puntualizza che il tag può contenere testo ed informazioni ma afferma anche che questi non debbono essere mostrati dallo user-agent; qualora fossero presenti sarebbero definiti per indicare all'utente in possesso di un browser obsoleto vie alternative per fruire della risorsa multimediale.

Sono definiti per l'elemento oltre agli attributi comuni ad audio visti precedentemente:

poster width height

In particolare poster deve contenere l'indirizzo di una immagine alternativa da caricare laddove il video non fosse disponibile. È consigliabile scegliere come poster frame una immagine rappresentativa del filmato in questione, in modo da dare immediata indicazione all'utente di quale argomento tratti la risorsa.

Tralascerò in questa sede le definizioni tecniche riguardanti stato del video e dimensioni, riportate nel draft, poichè esulano dagli scopi di questa guida essendo direttive destinate agli user-agents e non agli autori.

Un esempio minimale della sintassi:

<video src="filevideo.vid" autoplay></video>

audio

Definizione formale

L'elemento audio rappresenta un suono o uno stream audio; può essere incluso del contenuto (testuale) all'interno dell'elemento. Gli user-agents non dovrebbero mostrare questo contenuto agli utenti, esso è presente al solo scopo di permettere ai vecchi browser di tentare il caricamento attraverso i plugin audio disponibili o di mostrare informazioni che descrivano vie alternative per accedere alla risorsa che si intende veicolare.

Page 19: Guida Html5

Un esempio minimale dell'utilizzo del tag audio:

<audio src="frank_sinatra-under_my_skin.mp3" preload="auto"></audio>

È importante sottolineare che non tutti i formati sono supportati dai singoli browsers; la considerazione vale sia per i codecs audio quanto per quelli video; l'HTML5 Working Group auspica venga individuato almeno un formato universalmente supportato, i vari produttori tuttavia sembrano spingere in questa fase in direzioni diverse alimentando polemiche incrociate nei confronti delle scelte altrui.

Allo scopo di evitare inaspettati disservizi ed essere ragionevolmente sicuri di veicolare la risorsa di interesse è stato creato l'elemento source:

source

Definizione formale

L'elemento source permette all'autore di specificare delle alternative per le risorse definite in un elemento multimediale (audio, video). L'elemento definito al di fuori di questo contesto non ha alcun significato.

Come ben chiarito dalla specifica il tag source permette di definire un semplice meccanismo di failover qualora il browser non fosse in grado di leggere e riprodurre la risorsa definita per prima nella lista delle sources. Vediamo un esempio pratico di quanto detto:

<audio> <source src="frankie.wav"> <source src="frankie.ogg"> Il browser non è in grado di riprodurre alcuno dei file indicati!</audio>

Notate il contenuto testuale fornito nel caso in cui entrambi i codecs non siano supportati. source si applica indistintamente ai tag audio e video.

Oltre all'attributo src (obbligatorio) la specifica aggiunge type per specificare il media type della risorsa:

<source src='video.mp4' type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>

track

Definizione formale

L'elemento track permette all'autore di specificare esplicitamente dei testi temporizzati per i media elements. Non ha alcun significato al di fuori di questo contesto.

L'elemento possiede i seguenti attributi:

kind: enumerazione che può valere:o subtitles: sottotitoli; traduzione dalla lingua originale, descrizione testuale in caso di

audio poco comprensibile; mostrati come sovraimpressione.

Page 20: Guida Html5

o captions: simile a subtitles ma più orientato alla descrizione ed all'inserimento di informazioni sulla risorsa in esecuzione.

o descriptions: descrizione testuale del componente video quando questo non sia disponibile o poco chiaro.

o chapters: pensato per la navigazione interattiva nella risorsa.o metadata: non visibile all'utente, pensato per essere fruito tramite script.

src: indica la locazione dei dati testuali per la risorsa. srclang: obbligatorio quando kind si trovi in stato subtitle, indica la lingua in cui è veicolata

la risorsa. label: fornisce il titolo della risorsa in modo comprensibile all'utente. default: se specificato indica che la traccia è quella attivata per default.

Esempio dell'utilizzo combinato con il tag video, riadattato da quello proposto nel draft:

<video src="discorso_di_gandhi.vid"> <track kind=subtitles src=discorso_di_gandhi.en.vtt srclang=en label="English"> <track kind=subtitles src=discorso_di_gandhi.it.vtt srclang=it lang=it label="Italiano"> <track kind=subtitles src=discorso_di_gandhi.fr.vtt srclang=fr lang=fr label="Francais"> </video>

Il video in questione possiede quindi sottotitoli (osservate lo stato di kind) in tre lingue diverse. srclang in questo caso è obbligatorio.

Nuovi elementi in HTML5 - embed, mark e progressIl working draft elenca una serie di nuovi elementi non classificandoli esplicitamente, compongono la lista:

embed mark meter progress time ruby, rt e rp bdi wbr canvas command details datalist keygen output

Li analizzeremo in ordine, uno ad uno, partendo da embed.

Page 21: Guida Html5

embed

Definizione formale

L'elemento embed rappresenta un punto di integrazione per una applicazione esterna (tipicamente non-HTML) o per un contenuto interattivo.

embed prevede la presenza dei seguenti attributi:

src: l'indirizzo della risorsa da includere type: il MIME type in base al quale verrà selezionato il plugin da istanziare. width height

src e type sono sostanzialmente obbligatori affinchè embed abbia un significato.

Il draft sottolinea due importanti osservazioni: la prima è che embed non è influenzato dal comando CSS "display: none", il plugin selezionato tramite type viene comunque istanziato; la seconda si riferisce al fatto che embed non prevede un fallback content, ossia del contenuto da mostrare nel caso in cui il browser non trovi il plugin adatto per l'applicazione, se infatti questo avvenisse lo user-agent dovrebbe caricare un plugin di default, detto plugin potrebbe anche solo mostrare una stringa che avverte dell'impossibilità di caricare l'applicazione/contenuto interattivo.

Un esempio minimale:

<embed type="video/quicktime" src="vacanze.mov" width="200" height="200">

embed è in realtà presente sul web da lungo tempo ma il W3C lo inserisce tra i nuovi tags; la ragione di questa apparente discrasia risiede semplicemente nel fatto che l'elemento non era ufficialmente parte di HTML4 sebbene molti user-agents lo supportassero, con sfumature leggermente diverse soprattutto per quanto riguarda gli attributi. HTML4 supportava ufficialmente soltanto object, peraltro ancora presente in HTML5 ed i cui casi d'uso in molte occasioni possono essere sovrapponibili a quelli applicabili ad embed.

mark

Definizione formale

L'elemento mark rappresenta una porzione di testo in un documento evidenziata (marcata) a scopo di riferimento per la sua rilevanza in un altro contesto. Quando utilizzato per una citazione o in un altro blocco di testo indica una parola o frase importante che non era originariamente presente, ma che è stata aggiunta per portare l'attenzione del lettore su di una porzione di testo che l'autore potrebbe non avere considerato importante nel momento della stesura originale, ma che in quel contesto acquista una rilevanza precedentemente non prevista. Quando utilizzato nella prosa principale di un documento indica una parte del documento stesso che è stata evidenziata a causa della rilevanza che assume per l'attività corrente dell'utente.

Il tag in buona sostanza ottiene a video l'effetto grafico di un evidenziatore e va utilizzato ogniqualvolta si debba marcare una parte di testo allo scopo di attirarvi fortemente l'attenzione di chi legge. Il draft propone diversi esempi di impiego, mi limito a mostrarvene un paio, con le

Page 22: Guida Html5

dovute modifiche; il primo è riferito al caso in cui si vogliano isolare le parole corrispondenti ad una ricerca testuale effettuata dall'utente:

<p>Ho letto diversi libri di <mark>Hemingway</mark>. Lo trovo un narratore straordinario.Adoro l'<mark>Hemingway</mark> perso tra le assolate strade spagnole così come lo scrittore innamorato del mare.In una parola Ernest <mark>Hemingway</mark>!</p>

il risultato in Opera:

Importanza vs Rilevanza

Quando si voglia denotare importanza è bene utilizzare l'elemento strong, mark è applicabile quando si debba sottolineare la rilevanza di un estratto di testo. A tale proposito il draft propone un esempio, che vedremo leggermente riadattato. Lo scenario è quello di un libro di testo pensato come materiale base per sostenere un esame. Le sezioni di testo che possiedono rilevanza per l'esame sono contenute in elementi mark, le sezioni importanti invece sono wrappate dal tag strong:

<p>PHP5 è un linguaggio di scripting server side.<mark>PHP è debolmente tipizzato e supporta la programmazione ad oggetti (OOP).</mark>.</p><p>Nasce nel 1995 ad opera di <strong>Rasmus Lerdorf.</strong></p><p><mark>Uno script PHP deve essere sempre aperto dal <em>delimiter</em> <?php</strong> e chiuso da ?></mark></p><p>[..]</p><p>Vediamo un frammento di codice di esempio nel quale abbiamo inserito un errore:</p><pre> <code><?php function compare($var) { return <mark>$var = 1</mark> ? true : false; }</code></pre>

Notate come anche per evidenziare l'errore nel codice sia stato utilizzato mark.

Una considerazione personale: trovo l'effetto visivo predefinito dell'elemento (l'evidenziatore) stilisticamente poco piacevole. Suggerisco di limitarne l'uso il più possibile associandovi in casi particolari anche un foglio di stile che ne modifichi la renderizzazione standard, il draft non lo vieta.

progress

L'elemento progress rappresenta il progresso nel completamento di un task (operazione). Il progresso può essere indeterminato, qualora un avanzamento sia stato compiuto ma non risulti chiaro quanto occorra per il completamento (ad esempio quando il task è in attesa di una risposta da un host remoto) oppure può essere un numero compreso tra 0 ed un valore massimo, indicando la frazione di lavoro rimanente perchè il task giunga a conclusione.

L'elemento possiede due attributi:

Page 23: Guida Html5

value: la misura del valore attuale nel completamento del task. max: il valore indicante il raggiungimento del completamento dell'attività. L'omissione del

valore indica un progresso indeterminato.

Entrambi gli attributi devono essere, se presenti, valorizzati con numeri validi a virgola mobile (floating point es: 0.0 -> 1.0); valgono le seguenti regole: max > value && value >= 0 && max > 0.

Vi sottopongo uno scenario di utilizzo che sfrutta jQuery per agire sul value della progressbar:

<doctype html><html><head><script src="jquery.js"></script><script>// # Al DOM Ready$(function() { var progressBar = $("#progress_bar");// caching del selettore // # Al click sul bottone $("#progress_button").click(function() { // # Aumento il valore di 1 progressBar.attr("value", progressBar.attr("value") + 1); // # Aggiorno il valore testuale $("#progress_value").val(progressBar.attr("value")); });});</script></head><body>

<section> <h2>Avanzamento attività</h2> <p>Progress: <progress id="progress_bar" value=0 max=10><span id="progress_value">0</span>%</progress></p><button id="progress_button">+ 1!</button></section>

</body></html>

Il risultato in Opera:

Per motivi didattici l'avanzamento della barra avviene qui al click del bottone da parte dell'utente. In casi reali lo stato potrebbe dipendere dal completamento di chiamate asincrone al server oppure dallo step di avanzamento nel contesto di un wizard (procedure di installazione a steps, processi di acquisto e pagamento).

Page 24: Guida Html5

Nuovi elementi in HTML5 - meter e timemeter

Definizione formale

L'elemento meter rappresenta una misura scalare all'interno di un intervallo definito, oppure un valore frazionario; per esempio l'utilizzo di un disco rigido, la rilevanza del risultato di una query oppure la frazione della popolazione votante che ha optato per un particolare candidato.

A differenza di progress, meter non è pensato per indicare un avanzamento nel completamento di un task, nè per indicare valori come una altezza od un peso quando non vi sia un valore massimo cui rapportarli.

L'elemento prevede 6 attributi:

value: obbligatorio, indica il valore misurato min: estremo inferiore del range max: estremo superiore del range low, high, optimum: permettono di indicare dei subrange che delimitino le sezioni

corrispondenti a valori bassi, alti ed ottimi.

Tutti gli attributi, se presenti, debbono avere come valori validi numeri in virgola mobile. Ovviamente valgono inoltre le seguenti disuguaglianze:

min < value < max min < low < max (se low è specificato) min < high < max (se high è specificato) min < optimum < max (se optimum è specificato) low < high (se entrambi sono specificati)

Qualora max e min non siano specificati il range è supposto essere 0..1 e value deve conseguentemente essere compreso tra questi valori.

Un esempio di utilizzo valido:

Clienti paganti/visite totali <meter value=10 max=100>10 clienti su 100 terminano la procedura di pagamento</meter>

Ed un esempio non corretto:

Sono alto <meter value="1.78">1.78m</meter> e peso <meter value="88" title="misura espressa in Kilogrammi">88</meter>

Gli errori qui sono due (ripetuti per entrambe le misure). Il primo errore è il tentativo di utilizzare meter per rappresentare valori che non prevedono un limite massimo (potremmo fissare l'altezza massima di un essere umano a 2.80m, ma sarebbe comunque un limite aleatorio); il secondo errore è conseguenza diretta dell' omissione degli attributi min e max che implica l'adozione di un range predefinito tra 0 ed 1,ne consegue che valori maggiori (in questo caso 1.78 ed 88) risultino fuori scala.

Page 25: Guida Html5

L'attributo globale title in questo contesto permette di indicare l'unità di misura, altrimenti non specificata.

time

Definizione formale

L'elemento time rappresenta i propri contenuti corredati con un forma comprensibile agli elaboratori del contenuto stesso definita nell'attributo datetime. Il tipo di contenuto è limitato a vari tipi di date, orari, time-zones offsets (fusi orari), durate.

Il valore datetime dell'elemento time è stabilito essere il valore dell'attributo datetime qualora fosse presente, come il testo contenuto dall'elemento stesso altrimenti.

Datetime value definito tramite attributo:

<time datetime="2011-11-12"></time>

Datetime value definito tramite "textContent":

<time>2011-11-12</time>

Un esempio di formato valido per esprimere una durata:

<time>4h 18m 3s</time>

Un esempio comprensivo di ora e timezone:

<time datetime="2011-12-25T00:00:00Z"></time>

Nuovi elementi in HTML5 - ruby, rt, rb, bdi e wbrruby

Definizione formale di ruby

L'elemento ruby permette di marcare con ruby annotations uno o più frammenti di testo. Le ruby annotations sono piccole parti di testo presentate in associazione al testo base, utilizzate soprattutto nella tipografia asiatica come guida per la pronuncia o per includere altre annotazioni.

Il contenuto dell'elemento è definito essere quello del tag non compreso nelle annotazioni (rt).

Definizione formale di rt

L'elemento rt contraddistingue il contenuto testuale di una ruby annotation.

Ogni elemento rt figlio di un elemento ruby si riferisce al testo che lo precede nell'elemento stesso, esclusi i tags rp.

Page 26: Guida Html5

Un esempio riportato nel draft:

<ruby>漢<rt>かん</rt>字<rt>じ</rt></ruby>

Per ognuno degli ideogrammi giapponesi è associata la traslitterazione hiragana.

rp

Definizione formale

L'elemento rp può essere utilizzato per inserire parentesi intorno al componente testuale di una ruby annotation, per essere mostrato dagli user agents che non supportano le ruby annotations.

Si tratta in buona sostanza di un meccanismo di fallback per browsers non HTML5 compliant, rivediamo l'esempio precedente arricchito dai tags rp:

<ruby>

漢 <rp>(</rp><rt>かん</rt><rp>)</rp> 字 <rp>(</rp><rt>じ</rt><rp>)</rp></ruby>

Qualora il browser supportasse ruby il risultato sarà il medesimo dell'esempio già visto per rt, altrimenti verrà  renderizzato in questo modo:

漢 (かん) 字 (じ)

bdi

Definizione formale

L'elemento bdi rappresenta una porzione di testo da isolare rispetto al contesto che la circonda agli scopi della scrittura bidirezionale [BIDI].

Esistono due diverse direzioni di scrittura possibili right-to-left (RTL) e left-to-right (LTR), alcuni linguaggi (Arabo ed Ebraico) devono essere letti da destra a sinistra a differenza delle scritture occidentali. Quando sia necessario isolare sezioni di testo (tipicamente nomi) la cui direzione è potenzialmente diversa rispetto al contesto generale è opportuno utilizzare l'elemento bdi.

L'attributo globale dir assume un significato particolare per questo elemento ed assume il valore di default auto.

<ul> <li>Cognome <bdi>Brambilla</bdi>: 20 articoli. <li>Cognome <bdi>إيان</bdi>: 15 articoli.</ul>

Eliminando l'elemento l'algoritmo bidirezionale andrebbe in confusione; la stringa "15" verrebbe spostata a sinistra, accostandosi alla stringa "Cognome", così come nell'immagine che segue.

Page 27: Guida Html5

wbr

Definizione formale

L'elemento wbr rappresenta una opportunità  di interruzione di linea (a capo).

Poniamo di dovere riportare in un testo un flusso di coscienza:

<p>Permoltotempo<wbr>lamiamentehavagato<wbr>inquestoflusso<wbr>ininterrottodipensieri</p>

Il tag wbr indica al browser le opportunità suggerite per andare a capo qualora fosse necessario.

Nuovi elementi in HTML5 - [ menu ] e commandGli elementi menu e command fanno parte della famiglia degli interactive elements, che comprende anche details e summary. Come suggerisce la classificazione sono pensati per implementare interazioni con l'utente.

Sebbene il tag menu non sia propriamente di nuova introduzione lo inserisco nella lista dei nuovi elementi perchè ha subito un significativo cambiamento semantico atto a renderlo il fulcro delle nuove interfacce interattive.

menu

Definizione formale

L'elemento menu rappresenta una lista di comandi.

Possiede gli attributi type (non obbligatorio) e label; type è una enumerazione indicante il tipo di menu che si vuole implementare e prevede tre stati:

context: per indicare un context menu (menu contestuale). L'utente può interagire con i comandi solo se il context menu è attivato.

toolbar: per indicare una barra degli strumenti. L'utente può immediatamente interagire con i comandi.

list (default): per indicare che si vuole implementare una semplice lista di comandi non rientrante nelle precedenti classificazioni; il menu potrebbe contenere una lista di elementi li ciascuno rappresentante un comando oppure del contenuto che descriva le funzionalità a disposizione.

L'attributo label fornisce il nome al menu od al sottomenu in modo che il browser possa mostrarlo all'utente;

Non è obbligatorio utilizzare degli elementi command (che vedremo a breve) per le voci del menu, vediamo un esempio replicante parte del menu (toolbar) dell'editor Eclipse:

Page 28: Guida Html5

<menu type="toolbar"> <li> <menu label="File"> <button type="button" onclick="new()">New</button> <button type="button" onclick="open()">Open File ...</button> </menu> </li> <li> <menu label="Edit"> <button type="button" onclick="undo">Undo Text Change</button> <button type="button" onclick="redo()">Redo Text Change</button> </menu> </li> <li> <menu label="Source"> <button type="button" onclick="toggleC()">Toggle Comment</button> <button type="button" onclick="addBC()">Add Block Comment</button> </menu> </li> </menu>

Un elemento menu può contenere comandi, separatori, options, select, elementi li ed altri menu (sottomenu con o senza attributo label).

Laddove un elemento nella pagina preveda l'associazione ad un menu contestuale deve fornire un attributo contextmenu indicante l'id di un elemento menu facente parte del DOM.

<input name="copiaincolla" type="text" contextmenu="copiaincollacm" required><menu type="context" id="copiaincollacm"> <command label="Copia" onclick="copia()"> <command label="Incolla" onclick="incolla()"></menu>

command

Definizione formale

L'elemento command rappresenta un comando che l'utente ha la possibilità di invocare.

Un elemento command può utilmente fare parte di un menu contestuale o di una toolbar nel contesto di elemento menu.

Gli elementi command vengono renderizzati se e solo se parte di un elemento menu.

Possiede 7 attributi:

type: è una enumerazione che può valere command, checkbox o radio. Ogni valore mappa lo stato corrispondente

command: l'elemento rappresenta un comando associato ad una azione. checkbox: l'elemento rappresenta una opzione che può essere selezionata/deselezionata. radio: l'elemento rappresenta la selezione di una voce appartenente ad una lista di items. label: fornisce un nome da mostrare all'utente per il comando; è obbligatorio e non deve

essere valorizzato alla stringa vuota. icon: fornisce una immagine da utilizzare come icona del comando (deve essere una URL

valida)

Page 29: Guida Html5

disabled: booleano; se valorizzato a false indica che il comando non è disponibile nello stato attuale.

checked: booleano; se presente indica che il comando è attualmente selezionato. Da omettere quando il type valga command.

radiogroup: fornisce il nome al gruppo di comandi che verrà selezionato/deselezionato alla selezione/deselezione del comando stesso. (se e solo se type = radio).

title: fornisce una indicazione sulle funzionalità del comando, che potrebbero essere mostrate come help all'utente.

Un esempio mimimale che utilizza jQuery per intercettare l'evento click sui vari commands:

<!doctype html><html><head><title>L'elemento command</title><script src="jquery.js"></script><script>

// # Al DOM Ready$(function() {

$("#c_open").click(function() { alert("file aperto"); /* esercita una azione per l'apertura del file */ });

$("#c_close").click(function() { /* esercita una azione per la chiusura */ }); $("#c_save").click(function() { /* esercita una azione per il salvataggio */ });

});

</script></head><body> <menu> <command type="command" id="c_open" label="Apri" icon="open.png">Apri</command> <command type="command" id="c_close" label="Chiudi" icon="close.png">Chiudi</command> <command type="command" id="c_save" label="Salva" icon="save.png">Salva</command> </menu></body></html>

Ci sono vie alternative per definire un comando; eccone alcune:

un elemento a con attributo href un elemento button un elemento input con type compreso in: submit, button, reset, image, radio, checkbox. una option valorizzata (non a stringa vuota) figlia di un select. un elemento label o legend con attributo acccesskey definito.

Page 30: Guida Html5

Nuovi elementi in HTML5 - details e summarydetails e summary

Definizione formale

L'elemento details rappresenta informazioni addizionali o controlli che l'utente può ottenere su richiesta, l'elemento summary ne fornisce il sommario, la legenda o la descrizione.

Lo scenario che ci aspettiamo è quindi quello in cui un utente richieda delle informazioni addizionali non visualizzate di default o comunque che possano essere nascoste; un esempio reale potrebbe essere una widget (un box implementabile con un accordion ad esempio) contenente informazioni extra non strettamente necessarie ma che possano risultare interessanti per l'utente in alcuni casi.

A fianco dei dati anagrafici base di un paziente potrebbe essere utile permettere al curante di visualizzare informazioni addizionali come malattie pregresse o stili di vita; in aggiunta alle fotografie delle camere di un hotel risulterà utile dare la possibilità con un click di mostrarne la descrizione testuale e magari i prezzi.

Fino ad ora per ottenere l'effetto era necessario utilizzare Javascript (vedi accordion di jQuery UI), l'elemento details minimizza l'effort implementando la funzionalità nativamente.

Summary fornisce il titolo del box di dettaglio.

Pensiamo ai commenti che spesso vengono posti al termine di un articolo di giornale o del post di un blog:

<!doctype html><html> <head> <title>Il mio blog</title> </head> <body> <article> <h1>HTML5 details</h1> <p>Un ottimo elemento direi.</p> <details> <summary>Una osservazione</summary> <p>Sei stato davvero utile...</p> </details> </article> </body></html>

Ed ecco l'effetto (box aperto in seguito a click) su Chrome:

Page 31: Guida Html5

details possiede un attributo booleano open; laddove presente open indica che summary ed informazioni extra debbono essere inizialmente visibili all'utente (box aperto). Qualora open fosse assente sarebbe visibile inizialmente solamente il summary.

Vediamo un esempio di details legato ad un form di inserimento in cui le informazioni sono in parte inizialmente nascoste ed in parte già rivelate all'utente:

<section> <h1>Dati anagrafici</h1> <label for="nome">Nome</label> <p><input type="text" name="nome" id="nome"></p> <details> <summary><label for="nomeconiuge">Nome del coniuge (se presente)</label></summary> <p><input type="text" name="nomeconiuge" id="nomeconiuge"></p> </details></section><section> <h1>Dati societari</h1> <details open> <summary>Informazioni sulla compilazione</summary> <p>Per compilare la sezione procurarsi i dati relativi al capitale sociale ...</p> </details></section>

Ed ecco come la pagina viene visualizzata (su Chrome):

Page 32: Guida Html5

Nuovi elementi in HTML5 - datalist, keygen ed outputdatalist

Definizione formale

L'elemento datalist raggruppa un insieme di opzioni che rappresentano quelle predefinite per altri controlli. I contenuti (testuali) dell'elemento hanno lo scopo di agire come fallback per i vecchi browsers; questo contenuti sono inframezzati dalle opzioni (relative). L'elemento non ha un significato visuale, per cui dovrebbe essere reso invisibile. Ogni elemento datalist è agganciato ad un elemento input attraverso l'attributo list dell'input stesso.

Le varie options incluse in datalist (quando non vuote) debbono ognuna possedere una label ed un valore.

Un esempio:

<label>Regione di appartenza:<input type="text" name="region" list="region"> <datalist id="region"> <option value="Lombardia">Lombardia</option> <option value="Umbria">Umbria</option> <option value="Campania">Campania</option> <option value="Sicilia">Sicilia</option> </datalist></label>

keygen

Definizione formale

L'elemento keygen rappresenta un generatore di chiavi doppie. Quando il form cui appartiene viene inviato al server la chiave privata viene salvata nel "repository" locale e la chiave pubblica inviata al server.

Possiede i seguenti attributi:

autofocus challenge: se specificato viene "impacchettato" e spedito insieme alla chiave disabled form: associa il keygen al form relativo keytype: enumerazione relativa al tipo di chiave (rsa ad esempio, che rappresenta il default

qualora keytype non fosse dichiarato). Il draft non da indicazioni su quali keytypes debbano essere accettati dagli user-agents, paradossalmente uno specifico user-agent potrebbe non supportarne affatto.

name

La specifica non fornisce indicazioni precise di quello che il server potrebbe fare della chiave inviata, l'unico esempio che propone è lo scenario in cui al client viene ritornato un certificato a scopo di autenticazione.

Page 33: Guida Html5

Un esempio minimale:

<form id="unform" action="server.php" method="post"> <keygen name="chiavesicurezza" keytype="rsa" /></form>

output

Definizione formale

L'elemento output rappresenta il risultato di una elaborazione.

Possiede i seguenti attributi:

for: permette di stabilire una relazione esplicita tra il risultato dell'elaborazione e gli elementi che hanno portato al calcolo o che in qualche modo l'hanno influenzato. Deve consistere in una lista di token (gli ID degli elementi coinvolti) separati da spazi.

form: associa in modo esplicito l'output al relativo form. name

Vi porto all'attenzione un semplice esempio presente nel draft:

<!doctype html><html><head> <title>Un semplice calcolatore</title></head><body> <form onsubmit="return false;" oninput="output.value = add_1.valueAsNumber + add_2.valueAsNumber"> <input name="add_1" id="add_1" type="number" step="any"> + <input name="add_2" id="add_2" type="number" step="any"> = <output name="output" for="add_1 add_2"></output> </form></body></html>

Notate l'evento oninput del form e gli attributi type settati alla stringa "number", li analizzeremo nella prossima lezione.

N.B.: output non deve necessariamente contenere il risultato di una operazione numerica, potrebbe contenere i risultati di una query o qualsiasi altro contenuto generato da una elaborazione.

Page 34: Guida Html5

Progettare i forms con HTML5 (parte 1)HTML5 si propone di offrire una esperienza totalmente nuova nella fruizione dei forms; i mezzi per assicurarla passano attraverso l'introduzione di una corposa lista di nuove tipologie di input e l'adozione di attributi espressamente pensati per implementare i controlli base sulla compilazione senza ricorrere a Javascript.

Attività molto comuni come l'assegnazione del focus od il toggle del suggerimento inserito in un campo per dare indicazioni di compilazione all'utente ora richiedono del semplice markup, senza script.

Il ventaglio di tipologie prevede campi di inserimento appositamente progettati per numeri di telefono, mail, date. Si offre in questo modo all'utente una interfaccia più chiara ed allo sviluppatore meno lavoro sulla produzione di codice Javascript, con conseguente riduzione del peso della pagina in termini di KB con relativo miglioramento delle performance di caricamento.

Un aspetto interessante risiede nel comportamento dei browser obsoleti davanti ai nuovi types: mostrano semplicemente un campo text; sarebbe quindi teoricamente possibile utilizzarli sin d'ora senza patemi, implementando personalmente i controlli custom lato client; il mio consiglio tuttavia è di attendere che l'adoption di queste nuove features da parte degli user-agents si ampli ancora.

I nuovi valori dell'attributo type di input: tel search url email datetime date month week time datetime-local number range color

Il significato di text è ben noto, per quanto riguarda search le differenze con text sono puramente stilistiche, in piattaforme che prevedano una differenza visiva tra normali campi di testo e campi di ricerca gli input di type=search potrebbero essere stilisticamente coerenti con i search inputs della piattaforma stessa.

url rappresenta un indirizzo Internet nella forma http://[www.]dominio[.estensione] qualora l'utente non dovesse inserire il protocollo (http) sarà cura dello user-agent aggiungerlo

Per email il controllo sarà formale (per quanto volutamente piuttosto lasco come indicato esplicitamente nel documento), il tipo email possiede una ulteriore features molto utile: laddove fosse indicato l'attributo multiple lo user-agent si aspetterebbe una lista di emails separate da virgola, ognuna di queste ovviamente formalmente valida.

Page 35: Guida Html5

È interessante notare come non vengano forniti per input di tipo tel particolari controlli sintattici; se è vero che in Italia i numeri telefonici sono numerici questo non vale nel resto del mondo, così che il controllo formale deve essere a carico dello sviluppatore che può associare una funzione di check attraverso il metodo setCustomValidity().

Ricca anche la scelta tra i campi in qualche modo relativi alle date, e più in generale ad un istante temporale: date rappresenta una data nella forma yyyy-mm-dd (user-agent inglese), time rappresenta un orario nella forma hh:mm; month rappresenta un anno-mese nella forma yyyy-mm; week una data nella forma yyyy-Www dove ww vale un numerico (da 01, 02 etc); per datetime-local vale il discorso di date, arricchito dalla localizzazione.

Range e color sono controlli particolari; range prevede la valorizzazione di un attributo min, un attributo max e opzionalmente di uno step e denota un intervallo numerico; color implementa un utilissimo color-chooser.

I nuovi attributi legati a form, input, textarea e select

input e textarea prevedono ora un attributo autofocus per aiutare l'utente nell'inserimento dei dati. Fino ad ora il risultato era ottenuto attraverso l'utilizzo di un linguaggio di scripting (Javascript ad esempio). Allo stesso modo gli elementi prevedono anche un attributo placeholder per suggerire all'utente la struttura del dato che dovrà inserire.

Il nuovo attributo form vale per gli elementi input, output, select, textarea, button, label, object e fieldset. Ora i campi di un form possono essere ubicati ovunque nella pagina senza necessariamente essere figli diretti del tag form a cui si riferiscono:

<p>Inserisci i tuoi dati</p><label>Nome</label><input type="email" form="contact_form" name="email" placeholder="[email protected]"><form id="contact_form"></form>

Il nuovo attributo required si applica agli input (eccetto quando type="hidden" oppure type="image" o per alcuni tipi di button come submit), alle select ed alle textarea; indica che l'utente è tenuto a valorizzare il campo affinchè il form sia inviato. Nel caso delle select la prima option deve essere un placeholder con valore stringa vuota.Ecco un esempio:

<label>Occupazione: <select name="occupazione" required> <option value="">Seleziona <option>Ingegnere <option>Avvocato <option>Programmatore</select></label>

L'elemento textarea ha inoltre altri due nuovi attributi: maxlength e wrap, il secondo indica il comportamento per gli "a capo" del contenuto inviato.

L'elemento form acquisisce l'attributo novalidate che implica la disabilitazione di ogni controllo di validazione rendendo il form sempre inviabile.

Page 36: Guida Html5

Input e button ora prevedono formaction, formenctype, formmethod, formnovalidate e formtarget in aggiunta alla lista degli attributi disponibili; quando presenti vanno a sovrascrivere action, enctype, method, novalidate, e target dell'elemento form.

Progettare i forms con HTML5 (parte 2) - EsempiIpotizziamo di voler creare un form di inserimento da proporre all'utente utilizzando quanto più possibile le nuove possibilità offerte:

<!doctype html><html><head> <title>Disegnare i forms con HTML5</title> <style> body { margin: 0; padding: 0; font-size: 12px; font-family: "Verdana", sans-serif; color: #444; } section { width: 400px; height: 230px; margin: 0 auto; border-left: 1px solid #ccc; border-right: 1px solid #ccc; margin-top: 10px; padding: 15px; padding-top: 5px; } fieldset { clear: left; border: 0px; border-bottom: 1px dotted #dcdcdc; padding: 10px; height: 30px; } label { font-weight: bold; width: 100px; float: left; } input, textarea { border: 1px solid #dcdcdc; padding: 4px; width: 250px; color: #444; float: left; } button { margin-left: 100px; border: 1px solid #ccc; padding: 10px; color: #444;

Page 37: Guida Html5

} .firstSection { border-top: 1px solid #ccc; height: 200px; } .lastSection { border-bottom: 1px solid #ccc; height: 185px; } .longLine { height: 70px; } .note { font-size: 11px; font-style: italic; } .noBottomBorder { border: 0; } </style></head><body><form><section class="firstSection"> <h2>Dati anagrafici</h2> <p class="note">L'asterisco (*) indica i campi obbligatori</p> <fieldset> <label>Nome *</label><input name="nome" id="nome" type="text" required autofocus="autofocus"> </fieldset> <fieldset> <label>Numero Figli</label><input name="n_figli" id="n_figli" type="number" min="0" max="10">

</fieldset></section><section> <h2>Dati commerciali</h2>

<fieldset> <label>Telefono *</label><input name="telefono" id="telefono" type="tel" required>

</fieldset><fieldset>

<label>P. Iva</label><input name="piva" id="piva" type="text"></fieldset><fieldset>

<label>Email *</label><input name="email" id="email" type="email" placeholder="[email protected]" required>

</fieldset><fieldset>

<label>Sito Personale</label><input name="sito" id="sito" type="url" placeholder="www.sito.com">

</fieldset></section><section class="lastSection"> <h2>Informazioni extra</h2>

<fieldset class="longLine"> <label>Commenti</label><textarea name="commenti" id="commenti" placeholder="www.sito.com" maxlength="100" wrap="soft"></textarea>

</fieldset><fieldset class="noBottomBorder">

<button name="commenti" id="commenti">Invia</button></fieldset>

Page 38: Guida Html5

</section></form></body></html>

Ed ecco il risultato così come renderizzato da Opera, corredato da commenti:

Il comportamento in caso di click sul submit ed email mancante:

Page 39: Guida Html5

Il medesimo caso gestito da Firefox:

Page 40: Guida Html5

Ecco un form specifico per i campi relativi alle date:

<!doctype html><html><head> <title>Disegnare i forms con HTML5 [ le date ]</title> <style> body { margin: 0; padding: 0; font-size: 12px; font-family: "Verdana", sans-serif; color: #444; } section { width: 400px; height: 420px; margin: 0 auto; border: 1px solid #ccc; margin-top: 10px; padding: 15px; padding-top: 5px; } fieldset { clear: left; border: 0px; border-bottom: 1px dotted #dcdcdc; padding: 10px; height: 30px; } label { font-weight: bold; width: 100px; float: left; } input { border: 1px solid #dcdcdc; padding: 4px; width: 250px; color: #444; float: left; } </style></head><body><section> <h2>Input con types relativi alle date</h2> <form>

Page 41: Guida Html5

<fieldset> <label>Time</label><input name="t" id="t" type="time"> </fieldset> <fieldset> <label>Datetime</label><input name="dt" id="dt" type="datetime"> </fieldset> <fieldset> <label>Week</label><input name="w" id="w" type="week"> </fieldset> <fieldset> <label>Month</label><input name="m" id="m" type="month"> </fieldset> <fieldset> <label>Datetime-Local</label><input name="dtl" id="dtl" type="datetime-local"> </fieldset> </form></section></body></html>

Il risultato in Opera:

Vediamo la sintassi corretta per i controlli range e color:

<fieldset> <label>Range</label><input name="ra" id="ra" type="range" min="0" max="10" step="2"></fieldset><fieldset> <label>Color</label><input name="color" type="color" id="color" type="datetime"></fieldset>

Page 42: Guida Html5

Opera renderizza in questo modo i due controlli:

L'elemento canvas e le canvas API (parte 1) - FondamentiHTML5 introduce l'elemento canvas (tela, area di disegno) e le relative APIs per permettere di generare o modificare elementi grafici (bitmap) con relativa semplicità.

Definizione formale

L'elemento canvas fornisce un'area di disegno che può essere sfruttata dagli scripts (tipicamente codice Javascript) per disegnare on the fly grafici, grafica per videogame, immagini; può avere un contesto (context) primario che è il primo contesto ad essere ottenuto per l'elemento; alla creazione canvas non deve avere un contesto primario.

Il contesto attualmente disponibile è l'HTML Canvas 2D Context (è teoricamente previsto anche un contesto 3D), le cui APIs sono definite in un documento apposito consultabile a questo indirizzo; l'ultimo draft disponibile è datato 6 Gennaio 2012.

N.B.: È errato utilizzare canvas per renderizzare l'intestazione di una pagina, qualora questa dovesse essere particolarmente elaborata graficamente sarebbe opportuno utilizzare un elemento h1 debitamente stilizzato attraverso i CSS.

È consigliabile inserire all'interno dell'elemento del contenuto testuale che agisca come descrizione e fallback qualora non fosse possibile mostrare il bitmap.

Canvas prevede due attributi, utilizzati per controllare la dimensione dell'area disponibile (coordinate space):

width: larghezza dell'area di disegno, quando non esplicitata il default è 300px. height: altezza dell'area di disegno, quando non esplicitata il default è 150px.

Alla creazione del canvas e ad ogni resize successivo (ottenuto tramite modifiche su width e height) il bitmap ed ogni context associato vengono (ri)puliti e (re)inizializzati con le nuove dimensioni indicate.

La sintassi base dell'elemento è la seguente:

Page 43: Guida Html5

<canvas id="c_area">Il browser non supporta il tag canvas</canvas>

Il tag così definito rappresenta un'area invisibile di dimensione standard 300x150 pixels; come potete notare è definito un contenuto testuale per il fallback.

La prima operazione da metter in atto per poter iniziare a disegnare è ottenere un context (2D):

// # Come da esempio precedente, nella pagina esiste un elemento // # canvas con id="c_area"var canvasObj = document.getElementById("c_area");

// # Ottengo il contesto (2D)context = canvasObj.getContext("2d");

Tramite il context possiamo ora iniziare a disegnare; partiamo da un bitmap semplice, una forma geometrica:

// # Colore riempimento, un grigio molto tenuecontext.fillStyle = "#ededed";

// # Creazione del rettangolocontext.fillRect(100, 50, 100, 50);

Il codice genera un rettangolo di dimensioni width=100, height=50 e coordinate (100, 50), perfettamente centrato e di colore grigio chiaro.

Ecco il codice completo dell'esempio base:

<!doctype html><html><head><title>La prima forma geometrica</title><style> canvas { border: 1px solid #222; }</style><script src="jquery.js"></script><script>

// # Al DOM Ready$(function() {

// # Ottengo l'oggetto relativo al canvas var canvasObj = document.getElementById("c_area"); context = canvasObj.getContext("2d"); // ottengo il contesto

//# Colore riempimento, un grigio molto tenue context.fillStyle = "#ededed";

// # Creazione del rettangolo context.fillRect(100, 50, 100, 50);});</script></head><body> <canvas id="c_area">Impossibile mostrare il canvas</canvas></body></html>

Page 44: Guida Html5

ed il risultato così come mostrato da Firefox:

Prima di presentarvi un esempio più elaborato vi fornisco una lista delle principali funzioni esposte dalle APIs riguardanti le forme geometriche:

context.beginPath();

Crea/resetta il path corrente.

context.closePath();

Contrassegna come chiuso il subpath corrente e ne inizia un altro con coordinate di partenza uguali a quelle finali del path appena chiuso.

context.fill();

Colora il subpath con lo stile definito in fillStyle.

context.stroke();

Tratteggia il subpath con lo stile definito in strokeFill.

contextarc(x, y, radius, startAngle, endAngle [, anticlockwise ])

Disegna un arco partendo dalle coordinate (x, y), di raggio radius, angolo di partenza starAngle e angolo di arrivo endAngle; anticlockwise indica la direzione di disegno (false di default, quindi clockwise: senso orario).

context.rect(x, y, w, h)

Disegna un rettangolo (subpath chiuso) a partire dalle coordinate (x, y), di larghezza w, altezza h

context.lineTo(x, y);

Aggiunge il punto di coordinate x, y al subpath corrente, connesso al precedente da una linea retta.

Un primo esempio di utilizzo di canvas

Ora possiamo approcciare l'esempio, generosamente commentato (utilizza jQuery solo per intercettare l'evento DOM ready):

Page 45: Guida Html5

<!doctype html><html><head><title>Un simpatico amico</title><script src="jquery.js"></script><script>

// # Al DOM Ready$(function() {

// # Ottengo l'oggetto relativo al canvas var canvasObj = document.getElementById("c_area"); context = canvasObj.getContext("2d"); // ottengo il contesto

// # "Costanti" per i colori riutilizzati var REDHEX = "#990000";// porpora var BLACKHEX = "#222"; // antracite var BLUEHEX = "#0066cc"; // blu

// # Definizione inizio path context.beginPath(); // # Il viso, un arco a (125, 75) raggio 70, angolo da 0 a 2Math.PI (sfera), clockwise context.fillStyle = "#ffcc99"; context.arc(125, 150, 70, 0, Math.PI*2, true); context.fill(); context.stroke(); // disegno effettivamente la curva // chiudo il path context.closePath();

// # Sopracciglio sx (arco) context.beginPath(); context.arc(100, 125, 20, 0, Math.PI, true); context.stroke(); context.closePath();

// # Sopracciglio dx (arco) context.beginPath(); context.arc(150, 125, 20, 0, Math.PI, true); context.stroke(); context.closePath();

// # occhio sx (sfera) context.beginPath(); context.strokeStyle = BLACKHEX; context.fillStyle = BLUEHEX; context.arc(100, 135, 5, 0, Math.PI*2, true); context.fill(); context.stroke(); context.closePath();

// # occhio dx (sfera) context.beginPath(); context.strokeStyle = BLACKHEX; context.fillStyle = BLUEHEX; context.arc(150, 135, 5, 0, Math.PI*2, true); context.fill(); context.stroke(); context.closePath();

Page 46: Guida Html5

// # naso (sfera) context.beginPath(); context.strokeStyle = BLACKHEX; context.fillStyle = REDHEX; context.arc(125, 155, 8, 0, Math.PI*2, true); context.fill(); context.stroke(); context.closePath();

// # bocca (semisfera) context.beginPath(); context.strokeStyle = REDHEX; context.fillStyle = REDHEX; context.arc(125, 180, 12, 0, Math.PI, false); context.fill(); context.stroke(); context.closePath();

// # cappello (rettangolo + linea della tesa) context.beginPath(); context.strokeStyle = BLACKHEX; context.fillStyle = BLACKHEX; context.moveTo(55, 95); context.lineTo(195, 95); context.rect(80, 0, 90, 95); context.fill(); context.stroke(); context.closePath();});</script></head><body><article><!-- Impostiamo l'altezza a 300px, la width è 300px per default, l'area è un quadrato --><canvas id="c_area" height="300px">Impossibile mostrare il canvas</canvas></article></body></html>

Importante: gli angoli devono essere definiti in radianti, ricordo la regola di conversione per cui: radianti = 180/PI gradi; per gli angoli più comuni vale quindi:

30° = Math.PI/6. 60° = Math.PI/3 90° = Math.PI/2 180° = Math.PI 360° = 2*Math.PI

Rammentate le basi di geometria, ecco finalmente il nostro bitmap così come renderizzato in Firefox.

Page 47: Guida Html5

L'elemento canvas e le canvas API (parte 2) - Creazione di testiCome abbiamo visto le APIs espongono funzionalità per disegnare forme geometriche, semplici o complesse, ma non si limitano a questo; fanno parte delle specifiche una serie di settings e funzioni dedicate alla creazione di testi:

context.font

Se non facente parte di un assegnamento ritorna il font-setting corrente; può essere impostato seguendo la sintassi CSS della proprietà  font, l'ordine di definizione delle varie componenti è il seguente: font-style font-variant font-weight font-size/line-height font-family; esempio: context.font = italic normal 14px/20px Tahoma, sans-serif;

context.textAlign

Se non facente parte di un assegnamento ritorna l'allineamento del testo corrente; può essere impostato ad uno dei seguenti valori:

start (è il default) end left right center

context.textBaseline

Se non facente parte di un assegnamento ritorna il baseline alignment (allineamento del testo al margine inferiore della riga) corrente; può essere impostato ai valori: top, hanging, middle, alphabetic, ideographic, bottom.

Page 48: Guida Html5

context.fillText(text, x, y [, maxWidth ]), context.strokeText(text, x, y [, maxWidth ])

Rispettivamente, riempie/tratteggia sul canvas la stringa text partendo dalle coordinate (x, y); quando maxWidth è valorizzato ed uguale a true il font viene ridimensionato per rispettare la larghezza massima indicata.

metrics = context.measureText(text)

Ritorna un oggetto TextMetrics con le informazioni metriche del testo in oggetto nel font corrente.

metrics.width

Ritorna (getter) la larghezza del testo passata al metodo measuredText().

Ecco un esempio completo che disegna un piano cartesiano assegnando le label per le ascisse e per le ordinate.

<!doctype html><html><head><title>La mia presentazione</title><script src="jquery.js"></script><script>

// # Al DOM Ready$(function() {

// # Ottengo l'oggetto relativo al canvasvar canvasObj = document.getElementById("c_area");context = canvasObj.getContext("2d"); // recupero il contesto

// # Scelta del fontcontext.font = "12px/2 Arial, sans-serif";context.strokeStyle = "#555";

// # il metodo stroketext(text, x, y, [maxWidth]) scrive direttamente sul canvascontext.strokeText("tempo", 80, 140);// label ascissecontext.strokeText("valore", 10, 40);// label ordinate

// Piano Cartesiano// # Ascissecontext.beginPath();context.moveTo(60, 20);context.lineTo(60, 120);context.stroke();context.closePath();

// # Ordinatecontext.beginPath();context.moveTo(50, 110);context.lineTo(180, 110);context.stroke();context.closePath();

// # Colorazione del piano tramite gradientevar linearGradient = context.createLinearGradient(60, 20, 120, 90);linearGradient.addColorStop(0, '#ccc'); // grigio

Page 49: Guida Html5

linearGradient.addColorStop(1, '#efefef'); // grigio tenue

context.fillStyle = linearGradient;context.rect(60, 20, 120, 90);context.fill();

});</script></head><body><article><canvas id="c_area" height="300px">Impossibile mostrare il canvas</canvas></article></body></html>

Il risultato così come mostrato in Firefox 9:

L'elemento canvas e le canvas API (parte 3) - Gradienti, ombreggiature, trasformazioniGradienti

Per colorare il piano cartesiano della lezione precedente ho utilizzato un gradiente lineare, vediamo nel dettaglio tutte le possibilità che vengono offerte per definire gradienti:

gradient = context.createLinearGradient(x0, y0, x1, y1)

Restituisce un oggetto CanvasGradient che rappresenta un gradiente lineare che colora la linea definita dalle coordinate passate come parametri.

gradient = context.createRadialGradient(x0, y0, r0, x1, y1, r1)

Restituisce un oggetto CanvasGradient che rappresenta un gradiente radiale che colora il cono rappresentato dal cerchio definito dai parametri in input.

gradient.addColorStop(offset, color)

Aggiunge un colore al gradiente (color, esadecimale/stringa/rgb) all'offset indicato (da 0.0 inizio gradiente sino a 1.0 fine gradiente).

Definito un gradiente è sufficiente assegnarlo al fillStyle del contesto e chiamare la funzione fill() per applicarlo.

Page 50: Guida Html5

Altra area di applicazione delle canvas APIs sono le immagini. Possiamo caricare immagini preesistenti e modificarle. Le APIs offrono alcune interessanti funzionalità, applichiamone qualcuna in un esempio:

<!doctype html><html><head><title>Immagini e canvas</title><script src="jquery.js"></script><script>

// # Al DOM Ready$(function() {

// # Ottengo l'oggetto relativo al canvas var canvasObj = document.getElementById("c_area"); context = canvasObj.getContext("2d"); // recupero il contesto

// # Istanzio l'oggetto immagine var immagine = new Image(); // # l'immagine è sul filesystem immagine.src = "canvasimage.png"; // # al caricamento disegno l'immagine alle coordinate indicate, con dimensioni 182x173 immagine.onload = function() { context.drawImage(immagine, 50, 40, 182, 173); }

// # Applico una ombreggiatura context.shadowOffsetX = 6; context.shadowOffsetY = 6; context.shadowBlur = 5; context.shadowColor = "#333";

// # ridimensiono l'immagine al 60% delle dimensioni originali context.scale(0.6, 0.6); });</script></head><body><article><canvas id="c_area" height="300px">Impossibile mostrare il canvas</canvas></article></body></html>

Ecco l'immagine originale:

Page 51: Guida Html5

ed il risultato delle elaborazioni:

Ombreggiature

Nell'esempio abbiamo applicato una ombreggiatura, per definirla abbiamo a disposizione quattro proprietà :

context.shadowColor [ = valore]: getter/[setter] per definire il colore dell'ombra. context.shadowOffsetX [ = valore]: getter/[setter] per definire l'offset sul piano delle

ascisse (orizzontale) dell'ombra. context.shadowOffsetY [ = valore]: getter/[setter] per definire l'offset sul piano delle

ordinate (verticale) dell'ombra. context.shadowBlur [ = valore]: getter/[setter] per definire il grado di sfocamento

dell'ombra.

Trasformazioni

Ho introdotto nell'esempio anche una semplice trasformazione, ottenuta attraverso il metodo scale (ridimensiona), nel draft vengono descritti e resi disponibili nelle APIs i seguenti metodi:

context.scale(x, y): ridimensiona l'immagine secondo i parametri forniti; x è il ratio orizzontale, y quello verticale.

context.rotate(angle): applica una rotazione (l' angolo è in radianti). context.translate(x, y): trasla l'immagine in accordo con i parametri forniti; x è lo

spostamento orizzontale, y quello verticale. context.trasform(a, b, c, d, e, f) (notazione alternativa dei parametri: m11, m12, m21,

m22, dx, and dy): modifica la matrice di trasformazione esistente moltiplicandola per la matrice formata dai parametri spediti in input.La matrice è una 3x3 così composta

Page 52: Guida Html5

a c eb d f0 0 1.

context.setTransform(a, b, c, d, e, f): resetta la matrice alla matrice di identità, poi effettua una chiamata al metodo transform con i parametri passati in input.

L'elemento canvas e le canvas API (parte 4) - Tipi di linee e manipolazione per pixelTipi di linee

La specifica mette a disposizioni diverse varianti per modificare lo stile delle linee che è possibile disegnare:

context.lineWidth [ = value ]: getter/[setter] per definire la dimensione (spessore) della linea.

context.lineCap [ = value ]: getter/[setter] per definire il line cap style (lo stile con cui viene disegnata la terminazione della linea), i valori definibili sono butt, round, and square.

context.lineJoin [ = value ]: getter/[setter] per definire il line join style (lo stile con cui vengono connesse due linee), può essere bevel round o meter

context.miterLimit [ = value ]: getter/[setter] per definire il miterLimit, è utilizzabile solo quando il lineJoin=miter, evita per angolazioni molto strette di avere cuspidi troppo "spesse", quando ciò accade (il valore di miterLimit è superato) l'angolo viene renderizzato come bevel[led].

Vediamo un esempio che disegna diversi tipi di linee sul canvas:

<!doctype html><html><head><title>Tipi di linee</title><script src="jquery.js"></script><script>

// # Al DOM Ready$(function() {

// # Ottengo l'oggetto relativo al canvas var canvasObj = document.getElementById("c_area"); context = canvasObj.getContext("2d"); // recupero il contesto // # Colore linea context.strokeStyle = "#222"; context.beginPath(); // # linea con lineCap butt // # tutte le linee avranno spessore 6 context.lineWidth = "6"; context.lineCap = "butt"; context.moveTo(60, 20); context.lineTo(60, 120); context.stroke();

Page 53: Guida Html5

context.closePath(); context.beginPath(); // # linea con lineCap round context.lineCap = "round"; context.moveTo(80, 20); context.lineTo(80, 120); context.stroke(); context.closePath(); context.beginPath(); // # linea con lineCap square context.lineCap = "square"; context.moveTo(100, 20); context.lineTo(100, 120); context.stroke(); context.closePath(); context.strokeStyle = "#990000"; context.beginPath(); // # Disegno due linee collegate con lineJoin = miter e // miterLimitn = 3 context.lineJoin = "miter"; context.miterLimit = "3" context.moveTo(130, 20); context.lineTo(130, 120); // # Prima di chiudere il path disegno la seconda linea context.lineTo(200, 80); context.stroke(); context.closePath();});</script></head><body><article><canvas id="c_area" height="300px">Impossibile mostrare il canvas</canvas></article></body></html>

Il risultato in Opera: da sinistra lineCap butt, poi round, square; a destra due linee contigue con lineJoin = miter.

Page 54: Guida Html5

Manipolazione per pixel

Le canvas APIs offrono funzionalità molto potenti che permettono di manipolare un'immagine a basso livello, si possono creare immagini da zero per poi riempirle pixel per pixel oppure modificare immagini esistenti. Ecco quali sono i metodi coinvolti:

imagedata = context.createImageData(sw, sh): crea un oggetto ImageData di dimensioni sw, sy composto da pixels neri (transparent black).

imagedata = context.createImageData(imagedata): crea un oggetto ImageData, con le dimensioni dell'oggetto preso in input, composto da pixel neri (transparent black)

imagedata = context.getImageData(sx, sy, sw, sh): crea un oggetto ImageData contenente i dati dell'immagine per la porzione rettangolare del canvas delimitata dai parametri inviati. Qualora uno degli argomenti non fosse un numero finito o mancasse uno tra i parametri width ed height (sw, sh) il metodo lancerebbe una eccezione.

imagedata.width, imagedata.height: getters riferiti alle dimensioni dell'oggetto ImageData (in pixels relativi al dispositivo).

imagedata.data: getter per l'array (Canvas Pixel ArrayBuffer) contenente i dati RGBA (RedGreenBlueAlpha) sottoforma di numeri compresi tra 0 e 255.

context.putImageData(imagedata, dx, dy [, dirtyX, dirtyY, dirtyWidth, dirtyHeight ]): disegna sul canvas una immagine le cui caratteristiche sono definite dall'oggetto ImageData. Qualora uno degli argomenti non rappresentasse un numero finito il metodo lancerebbe una eccezione, inoltre se fosse fornito un "dirty rectangle" ([, dirtyX, dirtyY, dirtyWidth, dirtyHeight ]) solo i pixels appartenenti a tale rettangolo sarebbero disegnati.

Vediamo un esempio concreto di manipolazione dei pixel di una immagine esistente, lo script mostrerà a sinistra l'immagine originale, a destra il risultato delle elaborazioni:

<!doctype html><html><head><title>Manipolazione dei pixels con le canvas APIs</title><script src="jquery.js"></script><script>

// # Funzione invocata all' onLoadfunction afterLoad(event) {

// # Recupero l'oggetto canvas canvasObj = document.getElementById("c_area");

// # Ottengo il contesto context = canvasObj.getContext("2d");

// # Recupero l'immagine dall'evento immagine = event.target; // # Recupero width ed height del canvas width = parseInt(canvasObj.getAttribute("width")); height = parseInt(canvasObj.getAttribute("height"));

// # Disegno effettivamente l'immagine context.drawImage(immagine, 0, 0);

// # Recupero i dati dell'immagine (array descrittivo dei pixels) imageData = context.getImageData(0, 0, width, height);

Page 55: Guida Html5

// # halfXOffset rappresenta il punto delle ascisse dove inizia // # il disegno della seconda immagine var halfXOffset = Math.ceil(width/2);

// # Ciclo l'immagine pixel per pixel for (y = 0; y < height; y++) { // #¯pos pixel sorgente srcPos = y * width * 4; // # posizione traslata del pixel nella seconda immagine outPos = srcPos + halfXOffset * 4 // # Ciclo interno for (x = 0; x < halfXOffset; x++) { // # Manipolazione dei pixels imageData.data[outPos++] = imageData.data[srcPos++] / 2; // ROSSO imageData.data[outPos++] = imageData.data[srcPos++] * 2; // VERDE imageData.data[outPos++] = imageData.data[srcPos++]; // BLU imageData.data[outPos++] = imageData.data[srcPos++]; // ALPHA } }

// # Disegno la nuova immagine a destra dell'originale context.putImageData(imageData, 0, 0);}

// # Al DOM Ready$(function() {

// # Creo l'immagine var immagine = new Image();

// # Definisco la funzione da invocare all'onLoad immagine.onload = afterLoad;

// # Indicazione del file sorgente immagine.src = "candeline.jpg";});</script></head><body><article><canvas id="c_area" height="400px" width="500px">Impossibile mostrare il canvas</canvas></article></body></html>

Il risultato:

Page 56: Guida Html5

Per ottenere il bianco e nero basta modificare il ciclo for interno in questo modo:

for (x = 0; x < halfXOffset; x++) {

var rosso = imageData.data[srcPos++]; var verde = imageData.data[srcPos++]; var blu = imageData.data[srcPos++]; var alpha = imageData.data[srcPos++];

// # Il valore è dato dalla somma dei canali fratto 3 var valoreBN = (rosso + verde + blu) / 3;

// # Manipolazione dei pixels imageData.data[outPos++] = valoreBN; // ROSSO imageData.data[outPos++] = valoreBN; // VERDE imageData.data[outPos++] = valoreBN; // BLU imageData.data[outPos++] = alpha; // ALPHA}

Il risultato:

Possiamo anche modificare solamente il valore di alpha:

for (x = 0; x < halfXOffset; x++) {

// # I colori non cambiano imageData.data[outPos++] = imageData.data[srcPos++]; imageData.data[outPos++] = imageData.data[srcPos++]; imageData.data[outPos++] = imageData.data[srcPos++]; // # impostiamo alpha mezzi imageData.data[outPos++] = imageData.data[srcPos++] / 2;}

ottenendo:

Page 57: Guida Html5

Per chiudere uno screenshot in cui possiamo notare grazie a FireBug la composizione dell'oggetto imagedata.data: un Uint8ClampedArray.

Nuovi attributi, attributi ed elementi modificati in HTML5Nuovi attributi

HTML5 introduce alcuni nuovi attributi a vari elementi che erano già parte di HTML4:

Gli elementi a ed area ora possiedono l'attributo media per coerenza con l'elemento link. L'elemento area per coerenza con a e link ora possiede hreflang, type e rel. L'elemento base ora prevede la presenza di un attributo target, per corenza con a. L'elemento meta ora possiede un attributo charset (feature già  ampiamente supportata). L'elemento fieldset ora prevede l'attributo disabled, la cui funzione è di disabilitare tutti i

controlli figli, e l'adozione dell' attributo name utile per gli accedere tramite script all'elemento.

L'elemento menu possiede ora due nuovi attributi, type e label; la loro funzione risiede nella possibilità di trasformare l'elemento in un tipico menu da interfaccia avanzata, (anche come context menu tramite l'utilizzo dell'attributo contextmenu).

L'elemento style ha ora un nuovo attributo scoped che può essere utilizzato per attivare fogli di stile relativi ad uno specifico ambito. Le regole ivi definite si applicano solamente all'alberatura locale.

Page 58: Guida Html5

L'elemento script acquisisce l'attributo async che influenza il caricamento e l'esecuzione dello script.

L'elemento html possiede ora un attributo manifest che punta ad un application cache manifest utilizzato in accoppiata con le API per le Offline Web Applications.

L'elemento link ha un nuovo attributo: size; può essere utilizzato nell'ambito delle favicon, ad esempio (attraverso l'attributo rel) per indicarne la dimensione. Possono in questo modo essere definite icone di diverse dimensioni.

L'elemento ol acquisisce l'attributo reversed. Quando presente indica che l'ordine della lista è decrescente.

L'elemento iframe accoglie tre nuovi attributi: sandbox, seamless, srcdoc che permettono di nascondere contenuto (ad es.: commenti in un blog).

Elementi ed attributi in HTML5 il cui significato è stato modificato

La specifica include delle ridefinizioni per alcuni elementi allo scopo di riflettere meglio il loro utilizzo acquisito nel tempo o per renderli maggiormente utili:

L'elemento a senza un attributo href ora rappresenta un segnaposto per un link che potrebbe essere definito successivamente (o avrebbe potuto esserlo). Può anche contenere flow content (altri elementi) e non più solamente phrasing content (testo).

L'elemento address è ora definito nell'ambito del nuovo concetto di sectioning. L'elemento b ora rappresenta un porzione di testo dove richiamare l'attenzione per motivi di

utilità  senza aggiungere altra importanza e senza implicare un cambiamento "emozionale". Un paio di esempi: le parole chiave in una bozza, il nome dei prodotti in una rassegna.

L'elemento cite ora rappresenta solamente il titolo di un opera, di un artifact (un libro, un giornale, un poema, una canzone, un film, un gioco etc.). L'utilizzo in HTML4 per marcare il nome di una persona non è più considerato conforme.

L'elemento dl ora rappresenta una lista di associazioni nome-valore (una mappa) e non è più considerata appropriato per il dialogo.

L'elemento head non consente più l'inclusione tra i propri figli di un elemento object. L'elemento hr ora rappresenta un'interruzione tematica a livello di paragrafo. L'elemento i ora rappresenta una porzione di testo da leggere con altra intonazione, oppure

uno spostamento dalla prosa normale indicante una differente qualità  del testo come accade per termini tecnici, frasi appartementi ad altre lingue, pensieri.

Il browser non deve più spostare il focus dall'elemento label al controllo (input) correlato se questo comportamento non fa già  parte dello standard dell'interfaccia utente della piattaforma sottostante.

L'elemento menu è ridefinito per essere utile per toolbars e menu contestuali (vedi sezione apposita nella guida).

L'elemento s ora rappresenta contenuti che non sono (per obsolescenza) più accurati o rilevanti.

L'elemento small ora rappresenta delle piccole note a margine. L'elemento strong ora sottointende importanza piuttosto che forte enfasi. L'elemento u ora rappresenta una porzione di testo con una annotazione non testuale

inarticolata, benché esplicitata, come nell'indicazione di un testo come nome proprio in Cinese o nell'indicazione di un testo ortograficamente errato.

Attributi modificati L'attributo value per l'elemento li non è più deprecato perchè non è considerato visual-

markup (presentazionale); lo stesso vale per l'attributo start del tag ol.

Page 59: Guida Html5

L'attributo target per gli elementi a ed area non è più deprecato perchè considerato utile per le applicazioni Web, specialmente se in accoppiata con iframe.

L'attributo type riferito a script e style non è più obbligatorio se rispettivamente il linguaggio di scripting è ECMAScript e lo styling language è CSS.

L'attributo border per l'elemento table accetta solo il valore "1" e la stringa vuota.

Attributi consentiti ma da evitare L'attributo border per le immagini: deve avere valore "0" se presente; utilizzare i CSS. L'attributo language per il tag script. È obbligatorio valga la stringa "JavaScript" (case-

insensitive) se presente e non deve essere in conflitto con l'attributo type; si consiglia semplicemente di ometterlo.

Gli attributi width ed height di img e di altri elementi non possono più contenere valori percentuali.

Elementi ed attributi assenti (non inclusi) in HTML5 ed altre differenze con HTML4Come indicato all'inizio di questa guida non esistono in HTML5 veri e propri elementi deprecati; esistono tuttavia tags obsoleti che gli autori non devono più utilizzare e che invece gli user agents sono ancora chiamati a supportare per retrocompatibilità , vediamo di quali elementi stiamo parlando.

Elementi considerati come visual-markup e i cui effetti sono più correttamente ottenibili con i CSS:

basefont big center font strike, utilizzare del se si tratta di evidenziare una modifica, altrimenti s. tt

Elementi considerati dannosi per l'accessibilità  e l'usabilità : frame frameset noframes

In sostituzione degli elementi legati ai frames è consigliato ricorrere all'elemento iframe in combinazione con i CSS; in alternativa è suggerito il caricamento di contenuti (pagine complete) server-side.

Elementi non inclusi perchè poco utilizzati, generanti confusione o le cui funzionalità sono implementate da altri elementi:

acronym non è incluso perchè ha generato molta confusione. Agli autori è suggerito ricorrere ad abbr per le abbreviazioni.

applet è diventato obsoleto in favore di object. isindex: le sue funzionalità  possono essere ottenute attraverso l'utilizzo dei form controls. dir è diventato obsoleto in favore di ul.

Page 60: Guida Html5

Discorso a parte per il tag noscript; conforme nella sintassi HTML di HTML5, non incluso nella sintassi XML perchè il suo impiego richiede un parser HTML.

Attributi assenti (non inclusi)

Alcuni attributi presenti in HTML4 non sono più permessi (limitatamente in relazione ad alcuni elementi, messi tra parentesi) nella nuova specifica, gli autori devono quindi evitare:

rev e charset (link ed a); utilizzare rel al posto di rev per il tag link. shape e coords (tag a); si consiglia di utilizzare un HTTP Content-Type Header per la

risorsa linkata. longdesc attribute (img ed iframe); utilizzare un normale elemento a per linkare la

descrizione nel caso di iframe, una imagemap per le immagini. target (link); non necessario. nohref (area); è sufficiente omettere href. profile (head); non necessario. version (html); non necessario. name (img); utilizzare l' attributo id. scheme (meta); utilizzare un solo scheme per campo. archive, classid, codebase, codetype, declare e standby (object); evitare standby facendo

in modo che la risorsa si carichi velocemente (sic!). valuetype e type (param); utilizzare name e value evitando la dichiarazione del tipo. axis ed abbr (td e th); utilizzare al posto di abbr l'attributo title in modo da chiarificare il

contenuto. scope (td). summary (table); descrivere la tabella in un paragrafo introduttivo o in un tag caption

all'interno di table, magari avvalendosi dell'elemento details.

HTML5 inoltre esclude tutti gli attributi legati alla presentazione dell'informazione spingendo gli autori ad utilizzare i CSS per ottenere gli stessi risultati:

align riferito a caption, iframe, img, input, object, legend, table, hr, div, h1, h2, h3, h4, h5, h6, p, col, colgroup, tbody, td, tfoot, th, thead e tr.

alink, link, text e vlink, background riferiti al tag body. bgcolo riferito a table, tr, td, th and body. border riferito ad object. cellpadding e cellspacing riferiti a table. char e charoff riferiti a col, colgroup, tbody, td, tfoot, th, thead e tr. clear riferito a br. compact riferito a dl, menu, ol e ul. frame riferito a table. frameborder riferito a iframe. height riferito a td e th. hspace e vspace riferito ad img e object. marginheight e marginwidth riferiti ad iframe. noshade riferito ad hr. nowrap riferito a td e th. rules riferito a table. scrolling riferito ad iframe. size riferito ad hr. type riferito a li, ol e ul.

Page 61: Guida Html5

valign riferito a col, colgroup, tbody, td, tfoot, th, thead e tr. width riferito a hr, table, td, th, col, colgroup e pre.

Altre differenze tra HTML5 ed HTML4

MathML (MathML Mathematical Markup Language) ed SVG (Scalable Vector Graphics)

La sintassi HTML di HTML5 permette di utilizzare gli elementi SVG e MathML all'interno di un documento, il draft propone un semplice esempio:

<!doctype html><title>SVG in text/html</title><p> A green circle: <svg> <circle r="50" cx="50" cy="50" fill="green"/> </svg></p>

Una breve digressione su SVG, definizione (in)formale

Per Scalable Vector Graphics si intende la tecnologia derivata da XML che permette di renderizzare elementi grafici vettoriali (forme geometriche, testi, immagini); definisce quindi le immagini in termini di vettori e non di pixel, ciò preserva la qualità iniziale dell'elemento grafico anche in seguito a ridimensionamenti.

In ambito Web esistono molte librerie che permettono la creazione di grafica svg tramite javascript, una delle più apprezzate (e a proposito della quale troverete in questo sito alcuni articoli) è raphael.js.

SVG si contrappone per certi versi a canvas ed alle API ad esso correlate che generano bitmap. Quale dei due approcci utilizzare dipende dal tipo di task che si deve portare a termine.

Abbiamo ricordato SVG, spendiamo qualche parola anche per MathML.

MathML è un applicazione di XML creata per includere espressioni matematiche (con la loro particolare notazione) all'interno delle pagine Web.

Poichè l'approfondimento di queste particolari tecnologie (SVG e MathML) esula dallo scopo della guida vi rimando ai documenti di specifica del W3C che le trattano rispettivamente qui e qui

L'attributo contenteditable

Dedichiamo uno spazio particolare a contenteditable; si tratta di una enumerazione, può valere:

true: indica che l'elemento è editabile false: indica che l'elemento non è editabile stringa vuota (equivale a true)

Esiste uno stato inherit che indica all'elemento figlio di comportarsi come il contenitore più prossimo.

È possibile ricavare/impostare il valore di contenteditable attraverso il getter/setter:

Page 62: Guida Html5

element.contentEditable [ = value ]

è possibile accedere all'informazione anche tramite:

element.isContentEditable

È permesso rendere l'intero documento editabile attraverso document.designMode [ = value ] che assume i valori "on" od "off".

Esiste un getter/setter anche per attivare il controllo sintattico dei contenuti inseriti nell'elemento, si tratta di element.spellcheck [ = value ].

Vediamo un esempio:

<!doctype html><html><head> <title>ContentEditable</title> <style> body { font-size: 12px; } #diveditabile { width: 300px; height: 50px; border: 1px solid #999; color: #333; padding: 10px; text-align: center; } </style></head><body> <div contenteditable="true" id="diveditabile"> <span spellcheck="false">Scrivi pure ciò che pensi!</span> </div></body>

La scrittura nell'area editabile in Firefox:

Varie (Miscellaneous)

HTML ora prevede il supporto nativo per IRIs (Internationalized Resource Identifiers), completamente sfruttabile solo se l'encoding del documento è UTF-8 o UTF-16.

L'attributo lang può essere valorizzato con la stringa vuota in aggiunta ad un valido identificatore di linguaggio così come xml:lamg in XML.

Le Geolocation APIs (versione 2) - parte 1

Page 63: Guida Html5

Le APIs di geolocalizzazione non sono tecnicamente parte delle specifiche HTML5, sono descritte in un documento separato (che trovate qui)che riporta come "incipit": "le APIs definiscono un'interfaccia di alto livello allo scopo di fornire, tramite script, accesso alle informazioni relative alla posizione geografica associata ad un device (dispositivo)".

Per dispositivo si intende un cellulare, un tablet, laptop ospitante l'applicazione richiedente le informazioni.

Attualmente esiste un draft datato ottobre 2011 che descrive le specifiche della versione 2, esplicitamente retrocompatibili con la versione 1.

Ho deciso di inserire le APIs in questa guida perchè fanno parte, a mio modo di vedere, di quello sforzo teso a dotare il Web di quegli strumenti di cui necessita per effettuare un ulteriore, importante passo avanti, in termini di funzionalità ed interattività.

N.B.: Nel processo di stesura delle specifiche è coinvolto solamente il W3C.

Introduzione

Le APIs sono agnostiche delle sottostanti sorgenti che forniscono la localizzazione: queste sorgenti tipicamente comprendono: GPS, dati ricavati dalla rete come l'IP del "chiamante", RFID, WiFi, celle telefoniche; esse non garantiscono in alcun modo che venga ritornata la posizione del dispositivo. Sono supportate sia richieste one-shot, sia richieste ripetute; è implementata la funzionalità di ricerca (query) sulle posizioni "cached" (precedentemente ricavate).

Le informazioni sulla localizzazione sono rappresentate nella forma di coordinate geografiche: longitudine e latitudine. Il documento indica che le informazioni così recuperate, potenzialmente lesive della privacy qualora fossero diffuse, vengano rese disponibili, in una implementazione conforme, esclusivamente dietro esplicito permesso dell'utente, espresso tramite una interfaccia (o ereditato da rapporti commerciali già vigenti tra le parti).

Le APIs

N.B.: Le APIs definiscono interfacce, le implementazioni sono a carico delle varie piattaforme.

Il meccanismo alla base del funzionamento delle API ruota intorno all'interfaccia Geolocation; definisce tre metodi, che analizziamo nel dettaglio.

getCurrentPosition

Signature

void getCurrentPosition(in PositionCallback successCallback, in optional PositionErrorCallback errorCallback, in optional PositionOptions options);

Descrizione

Il metodo accetta da uno fino a tre parametri in entrata; quando viene invocato deve immediatamente "ritornare" (ripassare il controllo al chiamante) e successivamente tentare in modalità asincrona di ottenere la posizione attuale del dispositivo. Quando il tentativo di recupero

Page 64: Guida Html5

approda a buon fine deve essere invocata la funzione di callback legata a questo evento (la handleEvent dell'oggetto successCallback) con un nuovo oggetto Position contenente la localizzazione del dispositivo, altrimenti il controllo deve passare all'oggetto errorCallback con un oggetto PositionError che descriva le cause del fallimento della richiesta.

watchPosition

Signature

long watchPosition(in PositionCallback successCallback, in optional PositionErrorCallback errorCallback, in optional PositionOptions options);

Descrizione

Il metodo watchPosition accetta da uno a tre parametri. Quando chiamato deve immediatamente ritornare un numero (di tipo long) che identifichi univocamente una operazione di watch/monitoraggio (un watchID) e poi iniziare asincronicamente l'operazione stessa.

Il flusso di funzionamento dell'operazione con la chiamata a successCallback/errorCallback procede in modo identico a quanto avviene per getCurrentPosition. L'operazione di monitoraggio della posizione del dispositivo deve poi continuare ed invocare l'appropiato callback ogniqualvolta la posizione muti o comunque finchè non intervenga una invocazione al metodo clearWatch (utilizzando come chiave il watchID).

clearWatch

Signature

void clearWatch(in long watchId);

Descrizione

Il metodo clearWatch accetta in input un argomento, l'identifier del monitoraggio attualmente in corso (generato da watchPosition). Qualora il watchID non corrispondesse a nessuno di quelli attesi relativi a processi in corso il metodo deve ripassare immediatamente il controllo al chiamante. Laddove invece l'identificatore fosse riconosciuto il processo ad esso relativo dovrebbe essere immadiatamente fermato senza richiamare alcun callback.

È importante notare che nel caso in cui l'utente non acconsentisse a rivelare la propria posizione i metodi getCurrentPosition e watchPosition chiamerebbero immediatamente la errorCallback passando come error code PERMISSION_DENIED.

L'interfaccia PositionOptions

getCurrentPosition e watchPosition prevedono come terzo parametro opzionale un oggetto PositionOptions: vediamolo più da vicino:

interface PositionOptions { attribute boolean enableHighAccuracy; attribute long timeout; attribute long maximumAge;

Page 65: Guida Html5

attribute boolean requireCoords; attribute boolean requestAddress;};

Analizziamone gli attributes:

enableHighAccuracy

Fornisce l'indicazione che l'applicazione si attende il massimo risultato in termini di precisione; la richiesta implica un possibile rallentamente nei tempi della risposta oppure un consumo più elevato di risorse (batterie ad esempio).

L'utente potrebbe anche "disabilitare" questa possibilità o equivalentemente il dispositivo potrebbe non essere in grado di ottenere dati più accurati rispetto ad una richiesta con l'attributo non specificato.

Lo scopo reale dell'attributo è quindi pensato al contrario (enableHighAccuracy = false o attributo assente), informare l'implementazione che non è richiesta nessuna particolare precisione, in modo che siano risparmiati tempi di attesa e batterie.

timeout

L'attributo definisce la massima latenza accettata (in millisecondi) entro cui getCurrentPosition e watchPosition passino il controllo ai relativi successCallback. Nel caso in cui questo tempo di attesa superi quello indicato verrà chiamata in causa la errorCallback passando un parametro PositionError il cui attributo error sarà valorizzato a TIMEOUT. Il tempo speso in attesa del permesso dell'utente non rientra nel computo totale del timeout. Il valore di default per l'attributo è Infinity.

maximumAge

Indica che l'applicazione accetta posizioni cached non più vecchie del valore definito (in millisecondi). Quando il valore è 0 oppure non esistono posizione precedentemente ricavate verrà immediatamente cercata una nuova posizione. Nel caso invece valesse Infinity l'implementazione restituirebbe una cached position senza valutarne il tempo di acquisizione.Attenzione: per watchPosition il valore temporale è calcolato sulla prima posizione ricavata (prima chiamata).

requireCoords

Comunica allo user agent che qualora non fosse possibile recuperare le informazioni per gli attributi Position.coords.latitude, Position.coords.longitude e Position.coords.accuracy la chiamata dovrebbe essere considerata fallita ed errorCallback dovrebbe essere invocato. Se settato a true (default) l'applicazione deve garantire che i suddetti attributi siano valorizzati (non nulli).

requestAddress

L'attributo indica che l'applicazione vorrebbe ricevere un indirizzo. Lo scopo è di evitare che questa informazione, costosa dal punto di vista dei tempi di recupero venga inutilmente cercata quando non richiesta (requestAddress = false o assente). Laddove l'attributo valesse true e l'indirizzo non fosse trovato la richiesta non dovrebbe comunque essere considerata fallita.

Page 66: Guida Html5

Le Geolocation APIs (versione 2) - parte 2Continuiamo in questa lezione la nostra analisi delle interfacce implicate nella geolocalizzazione.

L'interfaccia Position

L'interfaccia funziona come contenitore delle informazioni di geolocalizzazione ottenute tramite le APIs.

Signature

interface Position { readonly attribute Coordinates? coords; readonly attribute Address? address; readonly attribute DOMTimeStamp timestamp;};

Analizziamo i vari attributi partendo da coords: rappresenta un oggetto contenente le coordinate geografiche ed alcune infomazioni aggiuntive, la analizzeremo a breve; l'attributo è opzionale.

address contiene un insieme di properties che descrivono la posizione del dispositivo in termini di indirizzo, analizzeremo a breve l'oggetto; l'attributo è opzionale.

timestamp viene valorizzato con l'istante in cui la posizione è stata acquisita ed è rappresentato da un oggeto DOMTimestamp (mappato in un oggetto Date in Javascript).

Il draft suggerisce alle implementazioni che, sebbene siano entrambi opzionali, qualora coords ed address fossero entrambi assenti il processo di acquisizione delle informazioni dovrebbe essere considerato fallito.

L'interfaccia Coordinates

Signature

interface Coordinates { readonly attribute double? latitude; readonly attribute double? longitude; readonly attribute double? altitude; readonly attribute double? accuracy; readonly attribute double? altitudeAccuracy; readonly attribute double? heading; readonly attribute double? speed; readonly attribute double? verticalSpeed;};

Gli attributi

latitude e longitude sono espressi in gradi, se assenti debbono essere valorizzate a null. altitude rappresenta l'altezza sul livello del mare, specificata in metri; quando assente deve

valere null. accuracy come già accennato rappresenta la precisione della misurazione (in metri,

numerico, livello di confidenza 95%); laddove latitude e longitude fossero nulli accuracy varrebbe null.

Page 67: Guida Html5

altitudeAccuracy: come accuracy, riferito però ad altitude. heading indica la direzione di viaggio specificata in gradi riferiti al nord (punto cardinale)

contando in senso orario; null qualora non fosse possibile recuperare l'informazione, NaN laddove il dispositivo sia stazionario (speed = 0).

speed indica la velocità orizzontale dello spostamento; specificata in metri al secondo, vale null se non è possibile ottenere l'informazione.

vertical speed: come speed ma riferito allo spostamento verticale.

Tutti gli attributi sono opzionali ma nel caso in cui valgano tutti null lo stesso oggetto Coordinates dovrebbe valere null.

L'interfaccia address

Signature

interface Address { readonly attribute DOMString? country; readonly attribute DOMString? region; readonly attribute DOMString? county; readonly attribute DOMString? city; readonly attribute DOMString? street; readonly attribute DOMString? streetNumber; readonly attribute DOMString? premises; readonly attribute DOMString? postalCode;};

Gli attributi

country indica la nazione, specificata tramite il codice ISO a due lettere (Italia = IT). region può indicare, in accordo alle divisioni amministrative dei singoli stati, uno stato

americano, una regione italiana, un dipartimento francese e così via. county rappresenta un zona di una regione (la provincia italiana). city ("Senago, Milano"). street ("Via Roma") streetNumber indica il numero civico. premises può indicare il nome di un edificio o di un blocco di edifici ad esempio ("Palazzo

Reale"). (premise = "edificio con terreno") postalCode indica il codice di avviamento postale (CAP in Italia, zipCode negli USA).

Equivalentemente a quanto detto per Coordinates anche per Address vale la regola per cui qualora tutti gli attributi siano nulli anche l'oggetto sarà null.

L'interfaccia PositionError

Signature

interface PositionError { const unsigned short PERMISSION_DENIED = 1; const unsigned short POSITION_UNAVAILABLE = 2; const unsigned short TIMEOUT = 3; readonly attribute unsigned short code; readonly attribute DOMString message;};

Page 68: Guida Html5

PositionError rappresenta l'oggetto da ritornare all'errorHandler qualora la richiesta di geolocalizzazione dovesse fallire.

Possibili valori dell'attributo code

PERMISSION_DENIED (valore numerico 1): il fallimento della richiesta è dovuto alla negazione del permesso da parte dell'utente.

POSITION_UNAVAILABLE (valore numerico 2): impossibile determinare la posizione del dispositivo.

TIMEOUT (valore numerico 3): la richiesta non è stata soddisfatta entro la scadenza del timeout impostato.

L'attributo message sarà valorizzato con un testo che spiega i dettagli dell'errore (a scopo di debug e non di comunicazione all'utente).

Le Geolocation APIs (versione 2) - EsempiOra che abbiamo padroneggiato la teoria il draft ci viene in aiuto portandoci all'attenzione una serie di esempi divisi per tipo di richiesta:

Richieste "one-shot"function success (pos) { // # Mostra una mappa centrata a [ pos.coords.latitude, pos.coords.longitude ]}

// # La richiestanavigator.geolocation.getCurrentPosition(success);

La stessa richiesta implementata gestita tramite una closure.

// # La richiestanavigator.geolocation.getCurrentPosition(function(pos) { // # Mostra una mappa centrata a [ pos.coords.latitude, pos.coords.longitude ]});

Richieste ripetute (update posizione) e gestione degli errori (error handler)// # Gestione della visualizzazione (success callback)function success(pos) { }

// # Gestione degli errori (error callback)function error (error) { }

// # Richiesta ripetuta // # Creazione di un (watch) ID per le successive richieste// # Notate come venga definito anche il nome della funzione che gestirà il // # successo e quello per l' error handlervar watchId = navigator.geolocation.watchPosition(success, error);

function clickReset() { // # Reset delle informazioni al click su di un bottone navigator.geolocation.clearWatch(watchId);}

Page 69: Guida Html5

Richiesta posizione cached// # Effettua la richiesta di una posizione cached (vecchia al massimo di 5 minuti)// # Nel caso non ne esistessero di così "fresche" verrà effettuata la richiesta per // # ottenerne una nuovanavigator.geolocation.getCurrentPosition(success, error, { maximumAge: 300000 });

// # OKfunction success (pos) { /* mostra la posizione */ }

// # KOfunction error(error) { /* gestisci l'errore */ }

Richiesta forzata di una posizione cached// # Effettua la richiesta di una posizione cached (vecchia al massimo di 5 minuti)// # Nel caso non ne esistessero non verrà inoltrata una ulteriore richiesta ma il controllo // # passerà direttamente all'error handler che potrà gestire la situazionenavigator.geolocation.getCurrentPosition(success, error, { maximumAge: 300000, timeout: 0 });

// # OKfunction success (pos) { /* mostra la posizione */ }

// # KOfunction error(error) {

// # È importante distinguere tra gli errori switch(error.code) { case error.TIMEOUT:

// # Possiamo decidere di mostrare una posizione di default od effettuare la richiesta

// # per una nuova posizione

break; default: // # gestisci ogni altro tipo di errore break; };}

Richiesta di una qualsiasi posizione cached// # Effettua la richiesta di una posizione cached qualsiasi// # Qualora non ne esistessero il controllo passerà direttamente all'error handler (error.TIMEOUT)navigator.geolocation.getCurrentPosition(success, error, { maximumAge: Infinity, timeout: 0 });

// # OKfunction success (pos) { // # Abbiamo la certezza si tratto di una posizione cached}

// # KOfunction error(error) { /* Gestione come nell'esempio precedente */ }

Page 70: Guida Html5

Drag&Drop - fondamenti ed interfacce coinvolteEsistono, nascosti dietro le luci sfavillanti di HTML5 alcuni tesori nascosti, trattati separatamente e senza intorno il clamore suscitato da altre features.

Stiamo parlando del meccanismo di Drag&Drop nativo e dei microdata; iniziamo dal primo (il cui draft trovate a questo indirizzo): la ben nota ( sin da quando vennero sviluppate le APIs per IE5) operazione di Drag&Drop è descritta nel documento come un evento mousedown seguito da una serie di eventi mousemove.Leggendo le specifiche ho trovato alcuni punti piuttosto confusi ma cercherò come sempre fatto in questa guida di isolare le informazioni certe e chiare.

Il documento indica come rendere un elemento draggabile, per raggiungere lo scopo sono necessarie due semplici operazioni:

aggiungere all'elemento un attributo draggable. associare un event listener per l'evento dragstart che si occupi di salvare i dati relativi all'

operazione in un oggetto DataTransfer.

Aggiungerei che un elemento draggable dovrebbe possedere una proprietà CSS "cursor: move;", in modo che sia visivamente chiaro che l'elemento è "trascinabile".

L'attributo draggable

Tutti gli elementi HTML possono avere un attributo draggable, che è una enumeration e consiste in tre stati:

state = true: l'elemento è trascinabile. state = false: l'elemento non è trascinabile state = auto (default); utilizza il comportamento di default dello user-agent.

Il getter/setter è nella forma: element.draggable [ = value ] dove value è ovviamente booleano (true o false).

L'attributo dropzone

Ciò che è trascinabile spesso è previsto abbia una zona di "deposito", la dropzone.

Tutti gli elementi HTML possono rappresentare una "dropzone". Quando l'attributo è specificato deve consistere in una lista di tokens separati da spazi, i valori previsti sono:

copy: indica che il drop di un elemento risulterà in una copia del draggable. move: indica che il drop di un elemento risulterà in una move del draggable nella nuova

locazione. link: indica che il drop di un elemento risulterà in un collegamento ai dati originali. una keyword di lunghezza >= ad 8 caratteri che inizi con "string:". una keyword di lunghezza >= a 6 caratteri che inizi con "file:".

Page 71: Guida Html5

I valori di keyword specificano il tipo di dato accettato, ad esempio "string:text/plain", "file:image/png".

L'attributo non può contenere più di uno tra i valori copy, move e link. Il default è copy.

Ecco un esempio base riportato nel draft e riadattato che definisce un'area di deposito ed alcuni elementi draggable:

<script>function dragStartHandler(event) { ...}

function dropHandler(event) { ...}</script><p>Lista prodotti</p><ol ondragstart="dragStartHandler(event)"> <li draggable="true" data-value="TV">Televisione fullHD</li> <li draggable="true" data-value="Tablet">Tablet Android</li> <li draggable="true" data-value="Mobile">Mobile UMTS</li></ol><p>Trascina i prodotti nel carrello:</p><ol dropzone="move string:text/x-example" ondrop="dropHandler(event)"></ol>

Il drag data store

I dati che viaggiano nel contesto di una operazione di Drag&Drop consistono in una collezione di informazioni conosciute come "drag data store":

la drag data store item list, in cui ogni item è composto da:

un "drag data item kind": Plain Unicode String oppure File. un "drag data item type": generalmente il MIME type ma può essere una stringa qualsiasi. il dato vero e proprio (actual data)

La lista è ordinata per ordine di inserimento così come in una coda FIFO (First In First Out).

Fanno parte del drag data store anche:

l'informazione del feedback di default dello user-agent (drag data store default feedback). una lista di uno o più elementi definita come drag data store elements list. opzionalmente una immagine bitmap e le coordinate di un punto dell'immagine stessa

(rispettivamente drag data store bitmap e drag data store hot spot coordinate). un drag data store mode che può valere

o Read/write (evento dragstart, nuovi dati possono essere aggiunti al drag data store)o Read-only (evento drop, nessun nuovo dato può essere aggiunto al drag data store)o Protected (ogni altro evento, i formati ed i tipi presenti nella drag data store item list

possono essere enumerati, ma gli actual data non sono disponibili, inoltre nessun nuovo dato può essere aggiunto)

un "drag data store allowed effects state", stringa.

Page 72: Guida Html5

Prima di produrre del codice funzionante affrontiamo l'analisi delle APIs, facendo conoscenza con le interfacce coinvolte.

DataTransfer

Signature

interface DataTransfer { attribute DOMString dropEffect; attribute DOMString effectAllowed;

readonly attribute DataTransferItemList items;

void setDragImage(Element image, long x, long y); void addElement(Element element);

/* old interface */ readonly attribute DOMStringList types; DOMString getData(DOMString format); void setData(DOMString format, DOMString data); void clearData(optional DOMString format); readonly attribute FileList files;};

Gli oggetti DataTransfer sono utilizzati all'interno degli eventi legati al Drag&Drop, e sono validi fintanto che gli eventi sono in corso.

Analizziamo uno per uno attributi e metodi dell'oggetto:

dataTransfer.dropEffect [ = value ]: getter/setter per il tipo di operazione selezionato (none, copy, link, move).

dataTransfer.effectAllowed [ = value ]: getter/setter per i tipi di operazione consentiti, possibili valori: "none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", "uninitialized".

dataTransfer.items: getter per la lista di item (oggetto DataTransferItemList). dataTransfer.setDragImage(element, x, y): utilizza element per effettuare un update del

drag feedback, rimpiazzando feedback specificati in precedenza. dataTransfer.addElement(element): aggiunge element alla lista di elementi usati per il

drag feedback. dataTransfer.types: ritorna una DOMStringList, un elenco in buona sostanza dei formati

impostati nell'evento dragstart; se un file dovesse essere stato trascinato, tra i tipi verrà inclusa la stringa Files.

data = dataTransfer.getData(format): ritorna il dato specificato, se non esistesse ritornebbe la stringa vuota.

dataTransfer.setData(format, data): aggiunge i dati specificati. dataTransfer.clearData([ format ]): rimuove i dati del formato specificato (o tutti qualora

format non fosse indicato). dataTransfer.files: ritorna un oggetto FileList contenente i file trascinati, qualora vi

fossero.

DataTransferItemList

Signature

Page 73: Guida Html5

interface DataTransferItemList { readonly attribute unsigned long length; getter DataTransferItem (unsigned long index); deleter void (unsigned long index); void clear();

DataTransferItem? add(DOMString data, DOMString type); DataTransferItem? add(File data);};

Vediamo nel dettaglio i vari campi e metodi:

items.length: getter che restituisce il numero di items nel drag data store. items[index]: getter per lo specifico item la cui posizione è descritta da index. delete items[index]: rimuove l'item all'indice index all'interno del drag data store. items.clear(): rimuove tutti gli items. items.add(data, [type]): aggiunge una nuova entry, il parametro type deve essere fornito in

caso in cui il dato sia plain text.

DataTransferItem

Signature

interface DataTransferItem { readonly attribute DOMString kind; readonly attribute DOMString type; void getAsString(FunctionStringCallback? callback); File? getAsFile();};

[Callback, NoInterfaceObject]interface FunctionStringCallback { void handleEvent(DOMString data);};

Analizziamo attributi e metodi:

item.kind: getter per il "drag data item kind", può valere quindi "string:" o "file:". item.type: getter per il drag data item type item.getAsString(callback): per item kind = "Plain Unicode string", invoca il callback con

la stringa come argomento. file = item.getAsFile(): ritorna un oggetto File (per item kind = "file:").

DragEvent

Signature

[Constructor(DOMString type, optional DragEventInit eventInitDict)]interface DragEvent : MouseEvent { readonly attribute DataTransfer? dataTransfer;};

dictionary DragEventInit : MouseEventInit { DataTransfer? dataTransfer;};

Page 74: Guida Html5

Possiede un solo membro dataTransfer, accessibile tramite event.dataTransfer.

Drag&Drop - Gli eventi associatiOgni evento che partecipa al processo di click, trascinamento e deposito può essere intercettato e gestito con un listener, gli eventi intercettabili sono:

dragstart drag dragenter dragleave dragover drop dragend

Iniziamo con un esempio semplice: intercettiamo il dragstart, l'inizio del trascinamento:

<!doctype html><html><head> <title>Drag&Drop - il dragstart</title> <style> #divdrag { width: 300px; height: 100px; background-color: #333; color: #fff; cursor: move; padding: 10px; } p { margin-top: 40px; text-align: center; } </style> <script> function dragStart(e) {

// # event (e).target è il nostro div "sorgente" var target = e.target;

// # Inserisco nell'oggetto DataTransfer un testo e.dataTransfer.setData("Text", "Te lo avevo detto"); // # consento il move e.dataTransfer.effectAllowed = "move"; // # cambio il colore del div target.style.backgroundColor = "#cc0000"; // # e ne modifico il testo prendendolo dall'oggetto DataTransfer target.innerHTML = "<p>" + e.dataTransfer.getData("Text") + "</p>"; } </script><body> <div id="divdrag" ondragstart="dragStart(event)" draggable="true"> <p>Se mi trascini divento rosso!</p>

Page 75: Guida Html5

</div></body></html>

L'esempio utilizza DataTransfer per incapsulare una stringa che poi utilizza per cambiare il testo dell'elemento trascinato.

Il div prima del trascinamento:

e durante:

Affrontiamo ora un caso leggermente più complesso, un drag finalizzato ad un drop.Utilizzeremo l'evento ondrop sull'area di deposito (un div) e cancelleremo gli eventi dragenter e dragover in modo da far capire allo user-agent che il div con id = "divdrop" è la nostra area di deposito.

Il meccanismo di "cancellazione" avviene aggiungendo agli handlers dragOver e dragEntered un event.preventDefault() (return false per IE).

<!doctype html><html><head><title>Drag & Drop, dragEnded, dragEnter, dragEnded, drop</title><style> #divdrag { width: 200px; height: 100px; background-color: #333; color: #fff; cursor: move; padding: 10px; } #divdrop { width: 300px; height: 150px; background-color: #ccc; color: #333; padding: 10px; margin-top: 10px; }

Page 76: Guida Html5

p { margin-top: 40px; text-align: center; }</style><script>

// # Definisco il typevar format = "Text";

// # Gestione del dragstartfunction dragStart(e) {

// # event (e).target è il nostro div "sorgente" var target = e.target; e.dataTransfer.setData(format, "Riccardo"); // # consento solo il move e.dataTransfer.effectAllowed = "move"; target.style.backgroundColor = '#cc0000';}

// # Gestione del dragenter (cancel)function dragEnter(e)

if(event.preventDefault) { event.preventDefault(); } return false; }

// # Gestione del dragover (cancel)function dragOver(e) {

if(event.preventDefault) { event.preventDefault(); } return false; }

// # Gestione del dragend function dragEnd(e) { e.target.parentNode.removeChild(e.target);}

//# Gestione del dropfunction drop(e) {

// # event (e).target qui è il nostro "drop" div var target = e.target;

// # Recupero la stringa "Riccardo" var data = e.dataTransfer.getData(format); target.innerHTML = "<p>Benvenuto...</p>"; // # Creo un elemento p var p = document.createElement("p");

Page 77: Guida Html5

// # Gli assegno "Riccardo" come testo p.textContent = data; // # Appendo p al div target.appendChild(p); }</script><body>

<div id="divdrag" ondragstart="dragStart(event)" ondragend="dragEnd(event)" draggable="true"> <p>Arrivo!</p> </div> <div id="divdrop" ondragenter="dragEnter(event)" ondragover="dragOver(event)" ondrop="drop(event)"> <p>Ti aspetto!</p> </div> </body></html>

Notate l'handler per l'evento dragend; al termine del'operazione l'elemento trascinato viene eliminato.

Nelle immagini che seguono, l'intero processo di Drag&Drop su Chrome:

Tempo 0:

Drag:

Page 78: Guida Html5

Drop:

Microdata - i fondamentiL'altro underdog di HTML5 si chiama microdata; l'idea è quella di estendere HTML aggiungendo un vocabolario personalizzato per le nostre pagine.

Il vocabolario è in buona sostanza un insieme (Item) di proprietà nella forma di una mappa chiave-valore.

Trovate il working draft dedicato qui.

itemscope ed itemprop

La creazione di un item passa dall'uso di un attributo itemscope. Per aggiungere una proprietà all'item creato è necessario ricorrere all'attributo itemprop su di uno dei discendenti dell'item.

Alcuni esempi minimali mutuati dal draft:

<div itemscope> <p>Mi chiamo <span itemprop="name">Riccardo</span>.</p></div>

per le immagini e le URL si utilizzano gli attributi src e href rispettivamente:

<div itemscope>

Page 79: Guida Html5

<img itemprop="image" src="lisbona.png" alt="Lisbona"></div>

per valori non human-readable come codici o UID viene utilizzato l'attributo value del tag data:

<h1 itemscope> <data itemprop="user-id" value="132455677U">User ID</data></h1>

per le date è opportuno utilizzare time ed il relativo attributo:

<div itemscope>Sono nato il <time itemprop="natoil" datetime="1980-04-23">4 Aprile 1980</time>.</div>

Le proprietà possono a loro volta essere itemscope per altre proprietà:

<div itemscope> <p>Nome: <span itemprop="nome">Riccardo</span></p> <p>Artista preferito: <span itemprop="artista" itemscope> <span itemprop="nome">Jeff Buckley</span></span></p></div>

Qui artista è property e comtemporaneamente item con una property "nome".

Le proprietà possono anche non essere discendenti dell'item cui si riferiscono a patto di utilizzare itemhref per indicare la relazione:

<div itemscope itemhref="p_nome b_artista"></div><p id="p_nome">Nome: <span itemprop="nome">Riccardo</span></p><p id="b_artista">Artista preferito: <span itemprop="artista" itemscope> <span itemprop="nome">Jeff Buckley</span> </span></p>

L'esempio è perfettamente equivalente al precedente.

È: possibile per un item avere property con nome uguale e valori diversi.

Properties con lo stesso valore possono essere raggruppate:

<div itemscope> <span itemprop="frutto-preferito sport-preferito">Pesca</span></div>

itemtype

Per definire un contesto per le properties è opportuno indicare un itemtype, in modo da fornirne una chiave di lettura più precisa.Gli itemtype devono essere URL:

<div itemscope itemtype="http://esempi.it/navi"> <p>La <span itemprop="classe">Nimitz</span> è una tipologia di navi militari che comprende alcune portaerei nucleari.</p></div>

Page 80: Guida Html5

<div itemscope itemtype="http://esempi.it/professori"> <p>Il prof. Massimo Di Noia insegna in <span itemprop="classe">5a</span> sezione C</p></div>

Nell'esempio l'itemtype definisce il valore semantico della property per i due itemscope, stesso nome per la proprietà, significati molto diversi.

Identicatori globali

Alcuni item possono fornire informazioni ralative da un identificatore globale: un itemid, che deve essere un URL. La specifica porta come esempio quello dell' isbn (International Standard Book Number) di un libro:

<dl itemscope itemtype="http://esempi.it/libri" itemid="urn:isbn:0-111-12345-1"> <dt>Titolo <dd itemprop="titolo">Guida ad HTML5 <dt>Autore <dd itemprop="autore">Riccardo Brambilla <dt>Pubblicato il <dd><time itemprop="data_pubblicazione" datetime="2012-08-30">30 Agosto 2012</time></dl>

Gli autori sono incoraggiati ad utilizzare gli itemtype in modo da rendere le properties globali o in alternativa a dare alle stesse properties nomi univocamente identificativi (utilizzando URLs).

Microdata - le APIIl significato di inserire informazioni aggiuntive negli elementi è tipicamente quello di utilizzarle per mostrarle all'utente. Esiste quindi un modo per accedervi tramite script, le microdata DOM APIs.

Per ottenere la lista di items è necessario ricorrere al metodo document.getItems(typeNames) che ritorna una NodeList contenente gli items del tipo indicato o tutti qualora non fosse fornito il parametro typeNames. Ovviamente ogni item è rappresentato da ogni elemento del DOM che possegga un attributo itemscope.

Utilizziamo come base un esempio della lezione precedente:

<div itemscope itemtype="http://esempi.it/navi"> <p>La <span itemprop="classe">Nimitz</span> è una tipologia di navi militari che comprende alcune portaerei nucleari.</p></div>

Recuperiamo i microdata:

// # Recupero la lista di Items con itemtype = http://esempi.it/navivar listaItems = document.getItems("http://esempi.it/navi");

Accedere alle proprietà è molto semplice, basta utilizzare l'attributo properties dell'item, che ritorna una lista di oggetti HTMLPropertiesCollection:

Page 81: Guida Html5

// # Recupero la lista di Items con itemtype = http://esempi.it/navivar listaItems = document.getItems("http://esempi.it/navi");var shipClass = listaItems.properties["classe"][0].itemValue;

Ho preparato un esempio più articolato, generosamente commentato e che fa uso di jQuery:

<!doctype html><html> <head> <script src="jquery.js"></script> <script> // # Al DOM Ready $(function() { // # Recupero la lista di Items // # c'è un unico itemtype (http://esempi.it/tecnologie) // # quindi non è necessario specificarlo var listaItems = document.getItems(); // # Ciclo gli items for (var item = 0; item < listaItems.length; item++) { // # Recupero le properties var properties = listaItems[item].properties; // # Scelgo solo tech var techProps = properties[ "tech" ]; // # Ottengo la lista dei valori var techValues = techProps.getValues(); // # Li appendo al div con id = "microdata_data", wrappati da tags p for (var pos = 0; pos < techValues.length; pos++) {

$("#microdata_data").append("<p>" + techValues[pos] + "</p>") } } }); </script> </head> <body> <div itemscope itemtype="http://esempi.it/tecnologie"> <p>Mi chiamo <span itemprop="nome">Marco</span> <span itemprop="cognome">Bianchi</span></p> <p>Conosco <span itemprop="tech">Java</span></p> <p>Ho utilizzato <span itemprop="tech">PHP5</span> e <span itemprop="tech">jQuery</span></p> </div> <h2>Tecnologie conosciute</h2> <div id="microdata_data"></div> </body></html>

Ecco il risultato mostrato in Firefox:

Page 82: Guida Html5

L'esempio ci permette di capire come accedere ai valori della properties; l'operazione avviene tramite il metodo getValues() chiamato sulla property.

È possibile accedere anche ai nomi delle properties attraverso l'attributo names:

var listaItems = document.getItems();

// # Ciclo gli itemsfor (var item = 0; item < listaItems.length; item++) { // # Recupero le properties var properties = listaItems[item].properties; // # Recupero la lista dei nomi var names = properties.names; for(i = 0; i < names.length; i++) { $("#microdata_data").append("<p>" + names[i] + "</p>") }}

Il codice appenderà le stringhe, nome, cognome e tech al div con id="microdata_data".

Chiudiamo la nostra lezione sui microdata analizzando più da vicino la signature delle interfacce coinvolte:

partial interface Document { NodeList getItems(optional DOMString typeNames); // microdata};

partial interface HTMLElement { // microdata attribute boolean itemScope; [PutForwards=value] readonly attribute DOMSettableTokenList itemType; attribute DOMString itemId; [PutForwards=value] readonly attribute DOMSettableTokenList itemRef; [PutForwards=value] readonly attribute DOMSettableTokenList itemProp; readonly attribute HTMLPropertiesCollection properties; attribute any itemValue;};

Abbiamo già visto gli attributi ed i metodi negli esempi, rimane da evadere una nota per itemValue; element.itemValue [ = value ] è il getter/setter per il valore del singolo elemento

Page 83: Guida Html5

WebstorageIniziamo con questa lezione il viaggio tra le specifiche meno note che ruotano intorno ad HTML5 in un orbita più "periferica".

Alcune delle features che vedremo sono ancora in una fase di definizione relativamente iniziale e l'adoption da parte dei vari user-agents è ancora assolutamente parziale. Eviteremo per questo di dettagliare a fondo i temi, preferendo dare una introduzione, per quanto corposa, dei vari argomenti.

Webstorage

Salvare i dati in sessione è operazione quotidiana per gli sviluppatori.

La specifica (il cui documento potete trovare qui)tratta due meccanismi per salvare dati strutturati client-side, sul modello dei session cookies.

Lo scopo è di evitare le limitazioni dei cookie stessi. Pensiamo ad uno scenario in cui un utente porti avanti due transazioni, (ad esempio l'acquisto di un libro o di un biglietto aereo) nel medesimo istante, su due finestre diverse, nel medesimo sito.Qualora per tenere traccia degli acquisti il sito usasse i cookie potrebbe crearsi la situazione in cui l'utente potrebbe trovarsi ad avere acquistato due libri (o due biglietti) senza averne l'intenzione.

Al fine di superare questi problemi la specifica Webstorage introduce un attributo sessionStorage. I siti lo utilizzeranno per salvare dati ed esso rimarrà accessibile da ogni pagina dello stesso sito aperta in quella finestra. Ogni finestra aperta (del sito) avrà la sua copia dell'oggetto sessionStorage.

Pensiamo alla situazione in cui ad un utente venga richiesto di dare un consenso tramite una checkbox:

<label> <input type="checkbox" onchange="sessionStorage.marketing = checked ? 'true' : ''"> Accetto che l'azienda mi spedisca mail informative sui nuovi prodotti</label>

Una pagina successiva potrà accedere all'informazione tramite:

sessionStorage.marketing

Il secondo meccanismo di salvataggio è pensato per finestre multiple e dura oltra la sessione corrente. Le applicazioni potrebbero decidere di salvare intere mailbox o documenti lato client, per questioni di performance. I cookie non sono adatti a questa situazione perchè vengono trasmessi ad ogni request. Allo scopo esiste l'attributo localStorage.

Il conteggio delle visite di un utente:

<p>Hai visitato la pagina <span id="count"></span> volte.</p><script>// # Controllo che esista pageLoadCount nel localStorageif (!localStorage.pageLoadCount) { localStorage.pageLoadCount = 0; // init

Page 84: Guida Html5

}

localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1;document.getElementById("count").textContent = localStorage.pageLoadCount;</script>

Ogni sito avrà la sua area di salvataggio dedicata.

L'interfaccia Storage

Signature

interface Storage { readonly attribute unsigned long length; DOMString? key(unsigned long index); getter DOMString getItem(DOMString key); setter creator void setItem(DOMString key, DOMString value); deleter void removeItem(DOMString key); void clear();};

Ogni oggetto Storage fornisce accesso ad una lista di coppie (items) chiave(stringa) - valore (stringa).

Storage possiede una length che indica il numero di coppie. Il metodo key(n) ritorna il nome della chiave posta ad offset n nella lista. Qualora n sia >= di length key(n) torna null.

getItem(key) torna il valore associato alla chiave spedita come parametro; null in caso la chiave non esistesse.

setItem(key, value) controlla che la chiave esista, se così fosse verrà effettuato un update del valore, altrimenti verrà creata una coppia ex-novo. Se qualcosa non funzionasse nel setting (quota dello storage superata, storage disabilitato) lancerà una QuotaExceededError exception.

removeItem(key) rimuove la coppia.

setItem() e removeItem() cambiano lo stato dello storage solo in caso di successo, qualora fallissero i dati salvatio non verrebbero alterati.

il metodo clear() svuota la lista di coppie.

SessionStorage

Signature

[NoInterfaceObject]interface WindowSessionStorage { readonly attribute Storage sessionStorage;};Window implements WindowSessionStorage;

L'attributo sessionStorage rappresenta un insieme di aree di salvataggio, univoche rispetto al contesto di navigazione.

Page 85: Guida Html5

LocalStorage

Signature

[NoInterfaceObject]interface WindowLocalStorage { readonly attribute Storage localStorage;};Window implements WindowLocalStorage;

localStorage fornisce un oggetto Storage per un origine.

L'evento storage

L'evento storage viene lanciato ogniqualvolta l'area di salvataggio subisca una modifica (tramite una setItem, una removeItem od una clear). Quando ciò accade lo user-agent lancia l'evento in broadcast per avvisare ogni finestra il cui Document object possegga un oggetto Storage che debba essere avvisato del cambiamento avvenuto.

StorageEvent

Signature

[Constructor(DOMString type, optional StorageEventInit eventInitDict)]interface StorageEvent : Event { readonly attribute DOMString key; readonly attribute DOMString? oldValue; readonly attribute DOMString? newValue; readonly attribute DOMString url; readonly attribute Storage? storageArea;};

dictionary StorageEventInit : EventInit { DOMString key; DOMString? oldValue; DOMString? newValue; DOMString url; Storage? storageArea;};

key rappresenta la chiave da modificare; oldValue rappresenta il valore precedente; newValue il nuovo valore assegnato; url indica l'indirizzo del documento la cui chiave è stata modificata; storageArea rappresenta l'oggetto Storage modificato.

Gli user-agent dovrebbero limitare lo spazio allocato per ogni origine (calcolando i terzi livelli), il documento suggerisce questo limite venga fissato a 5 megabytes.

File API - FondamentiIn questa lezione ci occuperemo di un'altra importante specifica relativa ad HTML5, descritta in un documento separato che potete consultare a questo indirizzo, si tratta File APIs che permettono di gestire i files lato client.

Page 86: Guida Html5

File APIs

Poiché lavorare con i files è un task quotidiano, anche sul web, HTML5 finalmente ci fornisce delle APIs standard per farlo. La specifica permette di leggere, scrivere, rimuovere file locali, sincronamente e soprattutto asincronamente.

Pensiamo ad un form che preveda l'invio al server di un file locale tramite un elemento input file: grazie alle APIs avremo finalmente la possibilità di controllare il MIME type lato client prima di inviarlo al server, leggerlo e persino decidere che i contenuti non sono quelli che ci aspettavamo, il tutto senza chiamare in causa il server.

Ci concentreremo sulle operazioni asincrone, quindi parleremo dell'interfaccia FileReader e non di FileReadersync perchè lo stesso draft dice chiaramente:

It is desirable to read data from file systems asynchronously in the main thread of user agents.

L'intero meccanismo gira intorno a quattro oggetti:

FileList

interface FileList { getter File? item(unsigned long index); readonly attribute unsigned long length;};

FileList possiede un attributo length che contiene il numero dei files nella lista e un metodo item(index) che ritorna l'oggetto File sito alla posizione index.

Blob

interface Blob { readonly attribute unsigned long long size; readonly attribute DOMString type; //slice Blob into byte-ranged chunks Blob slice(optional long long start, optional long long end, optional DOMString contentType);

};

Blob rappresenta dati grezzi immutabili. Fornisce il metodo slice per sezionare i dati in pezzi di lunghezza definita.Espone un attributo size (dimensione del Blob) e type (il MIME type del Blob).

File

interface File : Blob {

readonly attribute DOMString name; readonly attribute Date lastModifiedDate;};

Page 87: Guida Html5

Rappresenta un singolo File nella lista, ottenuto dal filesystem; possiede gli attributi name e la data di ultima modifica lastModifiedDate. File eredita da Blob.

FileReader

[Constructor]interface FileReader: EventTarget {

// async read methods void readAsArrayBuffer(Blob blob); void readAsBinaryString(Blob blob); void readAsText(Blob blob, optional DOMString encoding); void readAsDataURL(Blob blob);

void abort();

// states const unsigned short EMPTY = 0; const unsigned short LOADING = 1; const unsigned short DONE = 2;

readonly attribute unsigned short readyState;

// File or Blob data readonly attribute any result;

readonly attribute DOMError error;

// event handler attributes attribute [TreatNonCallableAsNull] Function? onloadstart; attribute [TreatNonCallableAsNull] Function? onprogress; attribute [TreatNonCallableAsNull] Function? onload; attribute [TreatNonCallableAsNull] Function? onabort; attribute [TreatNonCallableAsNull] Function? onerror; attribute [TreatNonCallableAsNull] Function? onloadend;

};

FileReader espone metodi per leggere oggetti File o Blob in memoria e di accedere ai dati attraverso eventi; permette letture asincrone su oggetti Blob singoli lanciando eventi progress (gestiti dagli event handlers associati) mano a mano che la lettura procede.

Gli event handlers previsti sono:

onloadstart onprogress onabort onerror onload onloadend

L'oggetto prevede tre stati, lo stato corrente è ottenibili tramite l'attributo readyState.

EMPTY (0): l'oggetto è istanziato a enon ci sono letture in corso; è lo stato iniziale. LOADING (1): è in corso la lattura di una File o di un Blob tramite uno dei metodi di

lettura.

Page 88: Guida Html5

DONE (2): la lettura del File o Blob è terminata oppure si è verificato un errore oppure la lettura è stata interrotta tramite la chiamata ad abort().

FileReader espone quattro metodi per leggere File e Blob in modo asincrono, ciascuno di essi valorizzerà l'attributo result al termine delle operazioni:

readAsArrayBuffer: result conterrà i dati del File o del Blob sottoforma di un oggetto ArrayBuffer.

readAsBinaryString(blob) deprecato in favore di readAsArrayBuffer(blob); result conterrà i dati sottoforma di una bynary string.

readAsText: result conterrà i dati del File o del Blob sottoforma di stringa (testo) decodificata di default in UTF-8 o nel formato indicato.

readAsDataURL: result conterrà i dati del File o del Blob sottoforma di URL data.

Una volta invocato uno di questi metodi gli handlers intercetteranno gli avanzamenti

File API - EsempiPartiamo dalla semplice lettura di un file con copia del contenuto nel browser; ho utilizzato jQuery solamente per rendere il codice più conciso ed elegante e la closure su fileReader.onload per lo stesso motivo:

<!doctype html><html> <head> <title>Leggere i Files tramite le File APIs</title> <style> fieldset {

width: 500px; padding: 10px; font-size: 11px;

} </style> <script src="jquery.js"></script> <script> // # Al DOM Ready $(function() { // # bind dell'evento change $("#fileinput").change(function(event) { // # in event.target.files trovo l'oggetto FileList // # in questo caso il file è uno solo quindi lo trovo // # nella posizione 0 var file = event.target.files[0]; // # Controllo la dimensione del file if(file.size > 200) { alert("Non sono consentiti file di dimensione maggiore di 200B"); return false; } // # Istanzio il fileReader var fileReader = new FileReader();

Page 89: Guida Html5

// # Leggo il file fileReader.readAsText(file); // # A caricamento terminato inserisco in pagina il contenuto fileReader.onload = function (event) { $("#contenuto_file").html(event.target.result); }; }); });

</script> </head> <body> <fieldset><legend>Scegli un file dal filesystem</legend> <input type="file" id="fileinput" name="fileinput"><br /> <output id="contenuto_file"></output> </fieldset> </body></html>

Il risultato in Opera quando proviamo ad inserire un file più grande di 200B:

il processo andato a buon fine al termine del caricamento di un piccolo file di testo:

Uno degli aspetti più interessanti riguarda la possibilità di monitorare il progresso del caricamento di un file senza fatica:

<!doctype html><html> <head> <title>Monitorare un upload tramite le File APIs</title> <style> fieldset {

width: 500px; padding: 10px; font-size: 11px;

} </style> <script src="jquery.js"></script>

Page 90: Guida Html5

<script> // # Al DOM Ready $(function() { // # caching del selettore per l'elemento progress var progressBar = $("#progress_bar"); // # bind dell'evento change $("#fileinput").change(function(event) { // # in event.target.files trovo l'oggetto FileList // # in questo caso il file è uno solo quindi lo trovo // # nella posizione 0 var file = event.target.files[0]; // # Istanzio il fileReader var fileReader = new FileReader(); // # imposto un handler per l'onprogress fileReader.onprogress = function(event) { // # Se è possibile effettuare il calcolo if (event.lengthComputable) { // # calcolo il loaded, sarà un numero compreso tra 0 ed 1 var loaded = event.loaded / event.total; if (loaded < 1) { // # imposto il valore dell'elemento progress progressBar.attr("value", loaded ); } } }; // # imposto un handler per l'onerror fileReader.onerror = function(event) { alert("Si è verificato un errore nel caricamento"); return false; }; // # Leggo il file fileReader.readAsArrayBuffer(file);

// # A caricamento terminato termino // # il riempimento della progressbar fileReader.onload = function (event) { progressBar.attr("value", 1 ); alert("Caricamento completato"); }; }); });

</script> </head> <body> <fieldset><legend>Scegli un file dal filesystem</legend> <input type="file" id="fileinput" name="fileinput"><br /> <progress id="progress_bar"></progress> </fieldset> </body>

Page 91: Guida Html5

</html>

La situazione durante il caricamento di un file di grosse dimensioni in Opera:

Il risultato visivo al termine del caricamento:

Notate nell'esempio la definizione degli handlers per l'evento progress e per l'evento error. Ho utilizzato il nuovo elemento progress per renderizzare la barra, elemento che in questo caso risulta indicatissimo.

Possiamo unire le potenzialità delle File APIs con le Drag&Drop APIs:

<!doctype html><html> <head> <title>File APIs e Drag&Drop</title> <style> #dropdiv {

width: 200px; height: 100px; padding: 10px; border: 2px dashed #999; text-align: center; line-height: 100px;

} </style> <script src="jquery.js"></script> <script> function drop(event) { if(event.preventDefault) { event.preventDefault(); } // # Recupero il file dall'oggetto DataTransfer var file = event.dataTransfer.files[0]; // # Istanzio il fileReader var fileReader = new FileReader(); // # Leggo il file fileReader.readAsText(file); // # A caricamento terminato inserisco in pagina il contenuto fileReader.onload = function (event) {

Page 92: Guida Html5

$("#contenuto_file").append(event.target.result); }; return false; } // "Cancel" di dragover function dragover(event) { if(event.preventDefault) { event.preventDefault(); } return false; } // "Cancel" di dragenter function dragenter(event) { if(event.preventDefault) { event.preventDefault(); } return false; } </script> </head> <body> <div id="dropdiv" ondrop="drop(event)" ondragover="dragover(event)" ondragenter="dragenter(event)">Trascina qui un file</div> <output id="contenuto_file"></output> </body></html>

Ecco l'area di deposito prima del caricamento:

ed il risultato dopo aver trascinato un file di testo all'interno:

Le FileSystem API - Fondamenti ed interfacce coinvolte

Page 93: Guida Html5

Naturale estensione delle File APIs sono le FileSystem APIs, il cui scopo risiede nel permettere ad una Web Application di richiedere uno spazio dedicato per salvare dati, in maniera temporanea o persistente. L'accesso avviene in modalità sandboxed: l'applicazione potrà cioè accedere alla sola porzione del filesystem ad essa dedicata.

Lo user-agent dovrà chiedere all'utente il permesso per allocare spazio sul disco qualora il tipo di storage richiesto sia persistent; in entrambi i casi comunque, i dati, persistenti o temporanei, potranno sempre essere eliminati dall'utente, manualmente o tramite interfaccia fornita dallo user-agents.

L'applicazione richiede l'allocazione di spazio attraverso una chiamata al metodo requestFileSystem dell'oggetto LocalFileSystem:

Signature

interface LocalFileSystem { const unsigned short TEMPORARY = 0; const unsigned short PERSISTENT = 1; void requestFileSystem (unsigned short type, unsigned long long size, FileSystemCallback successCallback, optional ErrorCallback errorCallback); void resolveLocalFileSystemURL (DOMString url, EntryCallback successCallback, optional ErrorCallback errorCallback);};

Il metodo requestFileSystem

type indica se la richiesta sia per il salvataggio persistente o temporaneo (PERSISTENT o TEMPORARY).

size indica lo spazio richiesto sul disco.

successCallback ed errorCallback sono le funzioni previste rispettivamente per la gestione del feedback positivo e degli errori.

Il metodo resolveLocalFileSystemURL

Il metodo permette di cercare tra le entries del filesystem un file od una directory localizzati all'url indicata.

L'interfaccia Flags permette di fornire parametri aggiuntivi ai metodi che leggono o creano files e directories:

Signature

[NoInterfaceObject]interface Flags { attribute boolean create; attribute boolean exclusive;};

create indica che si desidera creare un file/directory ex-novo, exclusive (in obbligatoria accoppiata con create) causa un fallimento dell'operazione nel caso in cui la risorsa già esista.

Page 94: Guida Html5

L'astrazione ruota intorna ad un oggetto FileSystem:

Signature

[NoInterfaceObject]interface FileSystem { readonly attribute DOMString name; readonly attribute DirectoryEntry root;};

che prevede un name ed una cartella di root; per ogni filesystem sono previste delle entries (files o directories); in alto nella gerarchia troviamo l'interfaccia Entry:

Signature

[NoInterfaceObject]interface Entry { readonly attribute boolean isFile; readonly attribute boolean isDirectory; void getMetadata (MetadataCallback successCallback, optional ErrorCallback errorCallback); readonly attribute DOMString name; readonly attribute DOMString fullPath; readonly attribute FileSystem filesystem; void moveTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback); void copyTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback); DOMString toURL (optional DOMString mimeType); void remove (VoidCallback successCallback, optional ErrorCallback errorCallback); void getParent (EntryCallback successCallback, optional ErrorCallback errorCallback);};

L'interfaccia espone una completa lista di strumenti per ottenere informazioni ed agire sul filesystem, vediamo gli attributi:

isFile: booleano, indica se la entry è un file. isDirectory: booleano, indica se la entry è una directory name fullPath filesystem: il filesystem cui la Entry appartiene

Vediamo ora i metodi

getMetadata (MetadataCallback successCallback, optional ErrorCallback errorCallback)

Accede ai metadata della risorsa.

moveTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback)

Sposta la entry in una locazione differente (parent) del filesystem rinominandola newName, qualora un file/directory con lo stesso nome esistesse nella destinazione verrà sovrascritta.

Page 95: Guida Html5

copyTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback)

Copia il file/directory dentro parent, con nuovo nome newName.

remove (VoidCallback successCallback, optional ErrorCallback errorCallback)

Elimina il file/directory. tentare di eliminare una directory vuota o la root genera un errore.

getParent (EntryCallback successCallback, optional ErrorCallback errorCallback);

Ritorna la Entry contenitore, se la Entry è la root del filesystem, torna la entry stessa.

toURL (optional DOMString mimeType)

Ritorno un URL identificativo per la entry.

Tutti i metodi ad eccezione di quest'ultimo prevedono un successCallback ed un errorCallback.

DirectoryEntry e FileEntry estendono Entry.

DirectoryEntry

Signature

[NoInterfaceObject]interface DirectoryEntry : Entry { DirectoryReader createReader (); void getFile (DOMString path, optional Flags options, optional EntryCallback successCallback, optional ErrorCallback errorCallback); void getDirectory (DOMString path, optional Flags options, optional EntryCallback successCallback, optional ErrorCallback errorCallback); void removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback);};

L'interfaccia espone quattro metodi:

createReader()

Crea un DirectoryReader per leggere le entries in questa directory. Le entries vengono ritornate dal metodo readEntries del reader.

getFile(DOMString path, optional Flags options, optional EntryCallback successCallback, optional ErrorCallback errorCallback)

Crea o cerca un file in path, passando opzionalmente un oggetto Flags.

getDirectory (DOMString path, optional Flags options, optional EntryCallback successCallback, optional ErrorCallback errorCallback)

Crea o cerca una directory in path, passando opzionalmente un oggetto Flags.

Page 96: Guida Html5

removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback);

Elimina la directory e ricorsivamente il suo contenuto.

Tutti i metodi ad eccezione di createReader prevedono un successCallback ed un errorCallback.

FileEntry

Signature

[NoInterfaceObject]interface FileEntry : Entry { void createWriter (FileWriterCallback successCallback, optional ErrorCallback errorCallback); void file (FileCallback successCallback, optional ErrorCallback errorCallback);};

FileEntry rappresenta una entry di tipo File nel filesystem; espone due metodi:

createWriter (FileWriterCallback successCallback, optional ErrorCallback errorCallback)

Crea un nuovo FileWriter per la risorsa.

void file (FileCallback successCallback, optional ErrorCallback errorCallback)

Ritorna un oggetto File che rappresenta lo stato corrente di questa entry.

Le APIs prevedono anche una versione sincrona del meccanismo; la base è l'oggetto

FileSystem API - EsempiPrima di vedere qualche esempio sottolineo che al momento soltanto Chrome supporta le APIs; partiamo con il codice necessario per ottenere un filesystem e per creare un file:

<!doctype html><html><head> <title>Ottenere un filesystem e creare un file</title> <script src="jquery.js"></script> <script> // # Se abbiamo ottenuto il filesystem function successHandler(fileSystem) { // # Creo il file

fileSystem.root.getFile("test_file", { create: true }, function(fileEntry) {

// # a scopo didattico var isFile = fileEntry.isFile ? "si" : "no";

Page 97: Guida Html5

// # Scriviamo qualche informazione del file a video $("#fileInfo").html("Nome:" + fileEntry.name + "<br />È un file: " +

isFile); }, errorHandler);

} // # gestione degli errori, questi possono essere generati dalla chiamata a requestFilesystem // # oppure dal successHandler function errorHandler(event) {

// # event.code racchiude il nostro codice di errore switch(event.code) { case 1:// NOT_FOUND_ERR $("#fileInfo").html("File non trovato") break; case 12: // PATH_EXISTS_ERR $("#fileInfo").html("Il file esiste già!") break;

default: $("#fileInfo").html("Si è verificato un errore!"); break; } } // # AL DOM Ready $(function() { // # webkitRequestFileSystem è una variante supportata da Chrome di requestFileSystem window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, successHandler, errorHandler); });

</script></head><body> <div id="fileInfo"></div></body></html>

Il risultato in Chrome:

Nell'esempio abbiamo definito un errorHandler e una logica minimale per trappare gli errori che si trovano in event.code; ecco i tipi di errori possibili:

NOT_FOUND_ERR: il file/directory non esiste. SECURITY_ERR: errore "generico", può essere il risultato di troppe chiamate per una

risorsa o per motivi di sicurezza, per esperienza personale mi è capitato di riceverlo perchè stavo utilizzando il protocollo file:// per testare gli esempi che vi propongo in questa lezione. La soluzione per evitarlo è mettere i file sotto Apache, utilizzando quindi http.

ABORT_ERR: codice da non utilizzare nel contesto di queste APIs.

Page 98: Guida Html5

NOT_READABLE_ERR: il file o la directory non sono accessibili in lettura tipicamente per problemi di permessi.

ENCODING_ERR: l'URL indicato non è formalmente corretto. NO_MODIFICATION_ALLOWED_ERR: si sta cercando di scrivere un file od una

directory che non possono essere modificati. INVALID_STATE_ERR: potrebbe essere notificato nel caso in cui si stia operando su di

un oggetto che è stato modificato successivamente al momento in cui è stato letto dal filesystem.

SYNTAX_ERR: codice da non utilizzare nel contesto di queste APIs. INVALID_MODIFICATION_ERR: modifica non permessa; spostare un file nella

directory padre senza rinominarlo o spostare una cartella padre in uno dei figli sono esempi di utilizzo errato che generano questo tipo di errore.

QUOTA_EXCEEDED_ERR: l'applicazione ha superato lo spazio (quota) ad essa dedicato.

TYPE_MISMATCH_ERR: notificato qualora di tentasse di operare sul tipo di oggetto errato (un FileEntry quando si tratta di una DirectoryEntry o viceversa).

PATH_EXISTS_ERR: impossibile creare la Entry perchè il path indicato esiste già.

Si tratta di una enumerazione i cui valori numerici partono da 1 (NOT_FOUND_ERR) ed arrivano a 12 PATH_EXISTS_ERR.

Vediamo come scrivere in un file, una volta ottenuto il filesystem la nostra funzione successHandler dovrà contenere questo codice:

// # Se abbiamo ottenuto il filesystemfunction successHandler(fileSystem) { // # Creo il file fileSystem.root.getFile("test_file", { create: true }, function(file) {

// # Creo un writer dal file file.createWriter(function(writer) { // # Alla fine della scrittura avviso con un messaggio writer.onwriteend = function(e) { alert("scrittura completata"); }; // # Creo un Blob (sintassi Chrome) var blob = new window.WebKitBlobBuilder(); blob.append("del testo"); // # Metto qualcosa nel Blob // # Scrivo nel file writer.write(blob.getBlob());

}, errorHandler);

}, errorHandler);}

La rimozione di un file avviene nel modo che segue:

// # Se abbiamo ottenuto il filesystemfunction successHandler(fileSystem) { // # Creo il file fileSystem.root.getFile("test_file", { create: true }, function(file) {

Page 99: Guida Html5

file.remove(function() { alert("File rimosso"); }, errorHandler);

}, errorHandler);}

Le operazioni sulle directory sono speculari a quelle sui files, unica differenza significativa la creazione che passa per il metodo getDirectory al posto di getFile.

È più interessante invece vedere un esempio in cui lo scopo sia leggere il contenuto di una directory o del filesystem:

<!doctype html><html><head> <title>Leggere il contenuto di una directory o del filesystem</title> <script src="jquery.js"></script> <script> // # Se abbiamo ottenuto il filesystem function successHandler(fileSystem) { // # Creo una directory fileSystem.root.getDirectory("Cartella_padre", { create: true }, function(dirEntry) { // # Istanzio un reader per il filesystem var reader = fileSystem.root.createReader(); // # Leggo il contenuto reader.readEntries(function(list) { // # Per ogni entry ricavo nome e tipologia $.each(list, function(i, item) { var dirOrFile = item.isFile ? "file" : "directory"; $("#fileInfo").append("<p>" + item.name + " - " + dirOrFile + "</p>"); }); });

}, errorHandler); } // # Gestione degli errori function errorHandler(event) { $("#fileInfo").html("Si è verificato un errore!"); } // # AL DOM Ready $(function() { // # webkitRequestFileSystem è una variante supportata da Chrome di requestFileSystem window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, successHandler, errorHandler); });

</script></head><body> <div id="fileInfo"></div>

Page 100: Guida Html5

</body></html>

Il risultato in Chrome:

Ed uno screenshot della console di Chrome che ci mostra la composizione della lista di oggetti:

WebWorkersQuando ragioniamo in termini di concorrenza la prima cosa che salta alla mente è la parola Thread, per alcuni il termine è associato a Java ed in particolare ad un esame universitario non particolarmente semplice da superare. Da oggi è possibile collegare a "concorrenza" un altro termine il cui campo di applicazione è il mondo client: i WebWorkers.

Si tratta di APIs che permettono di eseguire script (tipicamente lunghe elaborazioni) in background senza che la loro esecuzione blocchi in alcun modo l'interfaccia utente. Il draft dedicato, che potete trovare qui, mette in guardia dal loro abuso e ne consiglia un utilizzo limitato e responsabile.

Ogni WebWorker deve essere inserito in un file, il nome del quale va passato come parametro al costruttore:

var webWorker = new Worker("conteggio.js");

Il meccanismo alla base dei WebWorkers è semplice; viene istanziato l'oggetto indicando il file dove vive la business logic (che rappresenta il worker vero e proprio), si definisce un listener per l'evento message dalle due parti e si scambiano i dati attraverso il metodo postMessage(). Vediamo un esempio:

File principale

// #`Istanzio l'oggettovar webWorker = new Worker("pariodispari.js");

// # Listener per l'evento messagewebWorker.addEventListener("message", function(event) { alert(event.data);

Page 101: Guida Html5

}, false);

// # Invio dei datiwebWorker.postMessage({"par": "3"});

pariodispari.js

// # Il WebWorker, self rappresenta il worker stessoself.addEventListener("message", function(event) { // # Il messaggio" è nella bottiglia var dati = event.data; // # Il numero è nel messaggio var numero = dati.par; // # Notifichiamo il chiamante del risultato della elaborazione if(numero % 2 == 0) {

self.postMessage("è un numero pari"); } else {

self.postMessage("è un numero dispari"); }}, false);

È possibile per un worker "delegare" il lavoro a dei subworkers. Lo scopo è spalmare il lavoro su vari threads per sfruttare più CPU e migliorare le performances. Si tratta in buona sostanza di istanziare n workers figli all'interno di un worker padre:

// # Il worker padre, lo smistatore

// # 10 lavorantinum_subworker = 10;

for (var i = 0; i < num_subworker; i++) { // # la business logic risiede in subworker.js var worker = new Worker("subworker.js"); worker.postMessage(.. la tua parte di lavoro ..); ...}

È anche possibile importare file esterni in un worker tramite importScripts(filename).

L'utilizzo forse più logico di un WebWorker prevede la gestione di chiamate asincrone via get o post; l'esempio che segue implementa il recupero di informazioni attraverso una chiamata asincrona verso un sito (potrebbe essere un servizio REST che ritorna un qualche tipo di risposta attesa dall'applicazione):

//#`Istanzio l'oggettovar webWorker = new Worker("call.js");

// # Listener per l'evento messagewebWorker.addEventListener("message", function(event) { alert(event.data);}, false);

// # Invio dei datiwebWorker.postMessage({ url: "http://www.ilmiosito.it" });

Page 102: Guida Html5

call.js

self.addEventListener("message", function(event) { try { // # Utilizzo qui il buon vecchio XMLHttpRequest var xhr = new XMLHttpRequest(); xhr.open("GET", event.data.url, false); xhr.send(); // # Ritorno lo stato self.postMessage(xhr.statusText); } catch (e) { self.postMessage("ERRORE"); }}, false);

Esistono anche SharedWorkers: utilizzano APIs leggermente diverse e gestiscono connessioni multiple. Vediamo un semplice esempio riportato nel draft:

File principale

var worker = new SharedWorker("shared.js");worker.port.addEventListener('message', function(event) { alert (e.data);}, false);worker.port.start();worker.port.postMessage("ping");

shared.js

// # notate il listener onconnectonconnect = function(event) { var port = e.ports[0]; port.postMessage("Ciao!"); port.onmessage = function(event) { port.postMessage("pong"); }}

Importante: i WebWorkers non hanno accesso a tutti gli oggetti solitamente disponibili, proprio in ragione della lora natura: non possono accedere al DOM ad esempio perchè non è thread-safe, così come agli oggetti window e document, hanno tuttavia accesso a location, navigator e come abbiamo visto ad XMLHttpRequest.

Offline APIAnche in un periodo storico in cui quasi ogni dispositivo è connesso alla rete è necessario pensare ad un meccanismo che permetta di gestire le nostre Web Applications offline; pensate ad esempio ad un dispositivo mobile che per un certo lasso temporale perda la connessione per problemi di rete o perchè la zona in cui si trova ha una copertura insufficiente: l'utente potrebbe trovarsi a non poter fruire dei contenuti di cui necessita.

Page 103: Guida Html5

Per risolvere il problema vengono in nostro soccorso le Offline APIs, definite in un documento dedicato che potete trovare a questo indirizzo.

La soluzione passa dalla definizione di un file manifest che elenchi i files necessari perchè l'applicazione continui a funzionare (magari con features limitate) anche offline. Lo user-agent farà in modo di generare una copia dei files indicati perchè siano raggiungibili anche nel caso in cui la connessione di rete dovesse venire a mancare.

Manifest

Il file manifest è un semplice file di testo che consiste in una lista di stringhe (una per riga) rappresentanti i nomi delle risorse che il browser deve rendere accessibili offline, di seguito il contenuto di un ipotetico file demoapp.appcache:

CACHE MANIFESTindex.htmlstyle.cssindex.js

È necessario indicare nella pagina "principale" (quella che necessita dei suddetti files, qui la chiameremo index.html) nel tag html un attributo manifest che punti al file:

<!doctype html><html manifest="demoapp.appcache"> <head> <title>Demo</title> <script src="index.js"></script> <link rel="stylesheet" href="style.css"> </head> <body> <!-- la nostra webapp --> </body></html>

Firefox ci mostra un avviso quando accediamo alla pagina:

I file manifest sono serviti come tipo MIME text/cache-manifest.

Come avete potuto notare nel file manifest è stata inclusa la stessa index.html, la nostra "main page" così come raccomandato dal documento di specifica.

Il browser cercherà di aggiornare la cache dei files ogniqualvolta l'utente visiterà la pagina. Se il manifest dovesse essere stato modificato dall'ultima visita (ri)effettuerà il download di tutti i files.

I files vengono elencati nel manifest divisi per "categorie", tecnicamente namespaces, qualora non ne fosse esplicitamente definito alcuno il namespace di default è CACHE sotto il quale andranno definiti tutti i files da rendere disponibili offline.

È corretto utilizzare sia URL assoluti o relativi per indicare l'indirizzo dei files.

Page 104: Guida Html5

È possibile definire un namespace NETWORK per elencare files da non copiare localmente ed un namespace FALLBACK il cui scopo è indicare risorse che prevedano una versione online ed una offline.

Cerchiamo di visualizzare uno scenario che ci permetta di capire meglio le differenze.Poniamo di sviluppare un sito moderno che preveda una Home Page che oltre alle informazioni sull'azienda preveda un elenco di prodotti preso dal server ed una chat con un operatore. Offline sarebbe inutile includere il file che si occupa di reperire la lista dei prodotti dal server (un ipotetico get_product_list.php) ed inutile sarebbe includere il file che implementa la chat (chat.js).

Potremmo di conseguenza pensare ad un file manifest così strutturato:

CACHE MANIFESTNETWORK:get_product_list.phpchat.jsCACHE:index.htmlstyle.css

Potremmo anche decidere di sviluppare una Home Page alternativa statica che mostri solamente le informazioni relative all'azienda.

CACHE MANIFESTFALLBACKindex.html offline.html