Sei sulla pagina 1di 104

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. 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.

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):

Google Chrome 16.0 373 Mozilla Firefox 9.0 330 Opera 11.60 329 Apple 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 HTML


Il 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.

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.

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

<!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>

Organizzare i contenuti con HTML5 - section


HTML5 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:

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>

<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 aside


Article
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.

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.

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>

Organizzare i contenuti con HTML5 - header, hgroup e footer


header
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>

</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>

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.

Organizzare i contenuti con HTML5 - figure e figcaption


figure 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:

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>

I media elements di HTML5: video, audio, source e track


HTML5 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 useragent. 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.

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.

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.

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.
o

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 progress


Il 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.

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

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:

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).

Nuovi elementi in HTML5 - meter e time


meter
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.

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 wbr


ruby
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.

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.

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>ininterrottodipen sieri</p>

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

Nuovi elementi in HTML5 - [ menu ] e command


Gli 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:

<menu type="toolbar"> <li> <menu label="File"> <button type="button" <button type="button" </menu> </li> <li> <menu label="Edit"> <button type="button" <button type="button" </menu> </li> <li> <menu label="Source"> <button type="button" <button type="button" </menu> </li> </menu>

onclick="new()">New</button> onclick="open()">Open File ...</button>

onclick="undo">Undo Text Change</button> onclick="redo()">Redo Text Change</button>

onclick="toggleC()">Toggle Comment</button> onclick="addBC()">Add Block Comment</button>

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)

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.

Nuovi elementi in HTML5 - details e summary


details 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:

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):

Nuovi elementi in HTML5 - datalist, keygen ed output


datalist
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.

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.

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.

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 datetimelocal 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="riccardobra@gmail.com"> <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.

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) Esempi


Ipotizziamo 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;

} .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="nome@dominio.it" 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>

</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:

Il medesimo caso gestito da Firefox:

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>

<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="datetimelocal"> </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>

Opera renderizza in questo modo i due controlli:

L'elemento canvas e le canvas API (parte 1) Fondamenti


HTML5 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:

<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 tenue context.fillStyle = "#ededed"; // # Creazione del rettangolo context.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>

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):

<!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();

// # 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.

L'elemento canvas e le canvas API (parte 2) Creazione di testi


Come 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.

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 canvas var canvasObj = document.getElementById("c_area"); context = canvasObj.getContext("2d"); // recupero il contesto // # Scelta del font context.font = "12px/2 Arial, sans-serif"; context.strokeStyle = "#555"; // # il metodo stroketext(text, x, y, [maxWidth]) scrive direttamente sul canvas context.strokeText("tempo", 80, 140);// label ascisse context.strokeText("valore", 10, 40);// label ordinate // Piano Cartesiano // # Ascisse context.beginPath(); context.moveTo(60, 20); context.lineTo(60, 120); context.stroke(); context.closePath(); // # Ordinate context.beginPath(); context.moveTo(50, 110); context.lineTo(180, 110); context.stroke(); context.closePath(); // # Colorazione del piano tramite gradiente var linearGradient = context.createLinearGradient(60, 20, 120, 90); linearGradient.addColorStop(0, '#ccc'); // grigio

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, trasformazioni


Gradienti
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.

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:

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

ace bdf 0 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 pixel
Tipi 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();

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.

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' onLoad function 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);

// # 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:

Per ottenere il bianco e nero basta modificare il ciclo for interno in questo modo:
for (x = 0; x < halfXOffset; x++) { var var var var rosso verde blu alpha = = = = imageData.data[srcPos++]; imageData.data[srcPos++]; imageData.data[srcPos++]; 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; imageData.data[outPos++] = valoreBN; imageData.data[outPos++] = valoreBN; imageData.data[outPos++] = alpha; // // ROSSO // VERDE // BLU 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:

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 HTML5


Nuovi 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.

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 visualmarkup (presentazionale); lo stesso vale per l'attributo start del tag ol.

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" (caseinsensitive) 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 HTML4
Come 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.

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. 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:


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


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 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 attribute attribute attribute attribute };

boolean enableHighAccuracy; long timeout; long maximumAge; boolean requireCoords; 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.

Le Geolocation APIs (versione 2) - parte 2


Continuiamo 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? readonly attribute double? readonly attribute double? readonly attribute double? readonly attribute double? readonly attribute double? readonly attribute double? readonly attribute double? }; latitude; longitude; altitude; accuracy; altitudeAccuracy; heading; speed; 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. 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 readonly attribute readonly attribute readonly attribute readonly attribute readonly attribute readonly attribute readonly attribute }; DOMString? DOMString? DOMString? DOMString? DOMString? DOMString? DOMString? DOMString? country; region; county; city; street; streetNumber; premises; 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;

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) - Esempi


Ora 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 richiesta navigator.geolocation.getCurrentPosition(success);

La stessa richiesta implementata gestita tramite una closure.


// # La richiesta navigator.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 handler var watchId = navigator.geolocation.watchPosition(success, error); function clickReset() {

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

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 nuova navigator.geolocation.getCurrentPosition(success, error, { maximumAge: 300000 }); // # OK function success (pos) { /* mostra la posizione */ } // # KO function 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 situazione navigator.geolocation.getCurrentPosition(success, error, { maximumAge: 300000, timeout: 0 }); // # OK function success (pos) { /* mostra la posizione */ } // # KO function 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 }); // # OK function success (pos) { // # Abbiamo la certezza si tratto di una posizione cached

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

Drag&Drop - fondamenti ed interfacce coinvolte


Esistono, 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:".

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)

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.
o

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
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; };

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

Drag&Drop - Gli eventi associati


Ogni 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> </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; } p { margin-top: 40px; text-align: center; } </style> <script> // # Definisco il type var format = "Text"; // # Gestione del dragstart function 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 drop function 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"); // # 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:

Drop:

Microdata - i fondamenti
L'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 chiavevalore. 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>

<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>

<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 API
Il 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/navi var 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:

// # Recupero la lista di Items con itemtype = http://esempi.it/navi var 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:

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 items for (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

Webstorage
Iniziamo 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 localStorage if (!localStorage.pageLoadCount) { localStorage.pageLoadCount = 0; // init

} 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.

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 - Fondamenti


In 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.

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;

};

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] attribute [TreatNonCallableAsNull] attribute [TreatNonCallableAsNull] attribute [TreatNonCallableAsNull] attribute [TreatNonCallableAsNull] attribute [TreatNonCallableAsNull] }; Function? Function? Function? Function? Function? Function? onloadstart; onprogress; onload; onabort; onerror; 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.

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 - Esempi


Partiamo 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"); } // # Istanzio il fileReader var fileReader = new FileReader(); return false;

// # 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>

<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>

</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) {

$("#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

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 useragents. 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.

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.

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.

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 - Esempi


Prima 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";

isFile); }

// # Scriviamo qualche informazione del file a video $("#fileInfo").html("Nome:" + fileEntry.name + "<br /> un file: " + }, 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.

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 filesystem function 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 filesystem function successHandler(fileSystem) { // # Creo il file

fileSystem.root.getFile("test_file", { create: true }, function(file) { 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> </body> </html>

Il risultato in Chrome:

Ed uno screenshot della console di Chrome che ci mostra la composizione della lista di oggetti:

WebWorkers
Quando 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'oggetto var webWorker = new Worker("pariodispari.js"); // # Listener per l'evento message webWorker.addEventListener("message", function(event) {

alert(event.data); }, false); // # Invio dei dati webWorker.postMessage({"par": "3"});

pariodispari.js
// # Il WebWorker, self rappresenta il worker stesso self.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 lavoranti num_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'oggetto var webWorker = new Worker("call.js"); // # Listener per l'evento message webWorker.addEventListener("message", function(event) { alert(event.data); }, false); // # Invio dei dati webWorker.postMessage({ url: "http://www.ilmiosito.it" });

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 onconnect onconnect = 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 threadsafe, cos come agli oggetti window e document, hanno tuttavia accesso a location, navigator e come abbiamo visto ad XMLHttpRequest.

Offline API
Anche 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.

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 MANIFEST index.html style.css index.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.

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 MANIFEST NETWORK: get_product_list.php chat.js CACHE: index.html style.css

Potremmo anche decidere di sviluppare una Home Page alternativa statica che mostri solamente le informazioni relative all'azienda.
CACHE MANIFEST FALLBACK index.html offline.html