Creative Commons Attribution 3.0 License BY-NC-ND
Un linguaggio e API associate per HTML e XHTML
alla base del nuovo Web
quello che il W3C identifica con "Un Web per Tutti"
Richiede una serie di passi, in cooperazione tra i membri W3C e l'intera comunità Web W3C
Specifica | 1st WD | Last Call | CR | PR | Rec |
---|---|---|---|---|---|
HTML5 | 2008 | 2011 Q2 | 2012 Q4 | 2014 Q4 | 2014 Q4 |
HTML 5.1 | 2012 Q4 | 2014 Q3 | 2015 Q1 | 2016 Q4 | 2016 Q4 |
HTML 5.2 | 2015 |
Recommendation: sarà pubblicata nel quarto quadrimestre del 2014
Posso utilizzare HTML5 già adesso?
SI Posso!
(con qualche eccezione...)
polyfill aggiungono una "zeppa" JavaScript per i browser che non supportano l'API standard
Utilizza Web fonts
grafica WebGL
e altri elementi introdotti con l'ultima versione del linguaggio...
OPEN WEB PLATFORM
I've seen the F U T U R E
It's in my
<!DOCTYPE html> <!-- dichiarazione semplificata --> <html lang="it"> <!-- dichiarazione linguaggio --> <head> <title>HTML5</title> <meta charset="utf-8" /> <!-- set di caratteri unicode --> </head> <body> <p>Ciao mondo!</p> </body> <html>
capacità di leggere e scrivere un file system locale in modalità sandbox (sicura e protetta)
Un FileEntry ha proprietà e metodi tipici di un filesystem standard
// crea e accede un filesystem
window.requestFileSystem(window.PERSISTENT /* window.TEMPORARY */, 5*1024*1024 /* dimensione in MegaByte */,
function(filesystem) { fs = filesystem;})
// crea un file nel filesystem
fs.root.getFile('log.txt', {create: true, exclusive: true /* errore se esiste */},
// Crea un oggetto FileWriter per il nostro FileEntry (es.: log.txt)
fileEntry.createWriter(
// scrive un nuovo oggetto Blob object nel file
fileWriter.write(new Blob(['Lorem Ipsum'], {type: 'text/plain'})
);
// altri metodi per fileEntry
remove, copyTo, moveTo
// proprietà di fileEntry
isFile: True se un file
isDirectory: True se una directory
da Eric Bidelman (html5rocks), autore del libro "Using the HTML5 Filesystem API"
<DOCTYPE html><html>
... <!-- SVG inline in HTML5 -->
<svg width="12cm" height="4cm" viewBox="0 0 800 400">
<desc>Example circle01 - circle filled with red and stroked with blue</desc>
<circle cx="600" cy="200" r="100" fill="red" stroke="blue" stroke-width="10" />
</svg>
<rect x="1" y="1" width="448" height="198" fill="none" stroke="blue" stroke-width="2"/>
<g transform="translate(50,150)" fill="red" font-size="7">
<text id="TextElement">SVG2</text>
</g>
...
<animateMotion path="M 0 0 L 100 100" begin="1s" dur="5s" fill="freeze" />
<animateColor attributeName="fill" from="red" to="blue" begin="1s" dur="5s" fill="freeze" />
</svg></body></html>
<canvas id="myCanvas" width="300" height="200"> </canvas>
<script>var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d'); // 'webgl' = 3d
ctx.fillStyle = "rgb(255,0,0)";
ctx.fillRect(200,100,50,50);
ctx.fillStyle = "rgba(0, 0, 200, 0.3)";
ctx.fillRect (230, 40, 55, 50);
ctx.arc(75, 150, 20, 0, Math.PI*2, true);
ctx.arc(175, 150, 20, 0, Math.PI, true);
ctx.fill();</script>
Nessun plugin necessario per includere media: supporto nativo, implementato dai browser
<video id='myvideo' poster="image.jpg" controls='controls'>
<source src="filmato1.ogg" type="video/ogg" />
<source src="filmato2.mp4" type='video/mp4; codecs="mp4v.20.240, mp4a.40.2"' />
<track label="Sottotitoli in italiano" kind="subtitles" srclang="it" src="sottotitoli-it.vtt" default="default" />
Il tuo browser non supporta il tag video. Puoi scaricare il video al seguente indirizzo …
</video>
var v = document.getElementsByTagName("video")[0];
v.play();
<button onclick="document.getElementById('myvideo').play()">riproduzione</button>
<button onclick="document.getElementById('myvideo').pause()">pausa</button>
semplificazione e miglioramento rispetto alle precedenti recommendation
<audio id='myaudio' controls='controls' autoplay='true' loop='true'> // preload='none | metadata | auto'
<source src='RAI70-GuglielmoTell-Rossini.ogg#t=6,40' type='audio/ogg; codecs=vorbis' />
<source src='RAI70-GuglielmoTell-Rossini.mp3#t=6,40' type='audio/mpeg' />
Yuor browser does not support the audio tag
</audio>
var myaudio = document.getElementById('myaudio');
myaudio.seekable.start(0); // Restituisce il numero di secondi dell'inizio della riproduzione
myaudio.seekable.end(0); // Restituisce il numero di secondi della fine riproduzione
myaudio.currentTime = 122; // posizionamento al 122° secondo
myaudio.played.end(0); // Restituisce il numero di secondi riprodotti
<button onclick="document.getElementById('myaudio').play()">riproduzione</button>
<button onclick="document.getElementById('myaudio').pause();
document.getElementById('audioriprodotto').innerHTML='Secondi riprodotti: '
+document.getElementById('myaudio').played.end(0);">pause</button>
<button onclick="document.getElementById('myaudio').volume+=0.1">alza volume</button>
<button onclick="document.getElementById('myaudio').volume-=0.1">abbassa volume</button>
Audio API
FaceKat controllo basato su head tracking
Articolo (Opera) Head tracking con WebRTC
articoli e demo sul rilevamento di oggetti
Rilevamento del volto (funziona solo con browser compatibili con WebRTC)
Alveare (Web Audio API) controllato da api collegate in P2P via WebRTC articolo e video (demo)
<script>
localStorage.setItem('name', 'Hello world!'); // registra nel local storage la coppia chiave/valore
document.write(localStorage.getItem('name')); // Hello world
localStorage.removeItem('name'); // cancella la voce corrispondente dallo storage locale
</script>
Per chi ha bisogno di informazioni strutturate e di più spazio
var request = indexedDB.open(dbName); // // create a database
request.onsuccess = function(event) { // gestore della richiesta in caso di successo
// gestione risultato
};
request.onerror = function(event) { // gestore della richiesta in caso di errore
alert("Errore DB: " + event.target.errorCode);
};
request.onupgradeneeded = function(event) { // necessario per modificare la struttura di un DB. Qui possiamo creare/cancellare objectStore e indici
var myDB = event.target.result;
// create the object stores (una tabella in SQL)
var personStore = myDB.createObjectStore("Person", {keyPath: "id"});
// cre un indice per cercare persone per email, nessun duplicato ammissibile
personStore.createIndex("emailIndex", "email", { unique: true });
// crea una transazione e registra un record
var transaction = indexedDB.transaction("Person", "readwrite");
var store = transaction.objectStore("Person");
store.put({"id": "I2", "given_name" : "Anna", "family_name" : "Bianchi","email" : "anna.bianchi@w3c.it",... });
…
store.get("I3") // ottiene un record dato l'ID
// ottiene un record per Nome
var range = IDBKeyRange.only("Massimo");
var index = store.index("givennameIndex");
index.get(range)
// utilizza un cursore per ottenere i primi quattro record in ordine decrescente
personStore.openCursor(IDBKeyRange.bound(0, 5, true, false),"prev").onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
alert("Chiave: " + cursor.key + " valore: " + cursor.value.name);
cursor.continue();
}
else {
alert("Non ci sono più voci!");
}
};
store.clear() // cancella lo store
myDB.deleteDatabase(dbName); // cancella il database
…
}
Esempio, leggermente modificato da "Using the HTML5 IndexedDB API" by Brian J Stewart, IBM DeveloperWorks
<script>
function getPosition(position){
var lat = position.coords.latitude;
var long = position.coords.longitude;
var altezza = position.coords.altitude;
}
(in locale non funziona con Chrome)
<form>
<p><label>url:<input type="url" /></label></p>
<p><label>email:<input type="email" /></label></p>
<p><label>number:<input type="number" min="0" max="10" step="2" value="6" /></label></p>
<p><label>range:<input type="range" min="0" max="10" step="2" value="6" /></label></p>
<p><label>date:<input type="date" /></label></p>
<p><label>month:<input type="month"></label></p>
<p><label>week:<input type="week"></label></p>
<p><label>time:<input type="time"></label></p>
<p><label>datetime:<input type="datetime"></label></p>
<p><label>color:<input type="color"></label></p>
<p><label>required:<input required name="req"></label></p>
<p><label>range<input type="range" id="rangeinput" value="50" min="0" max="100" step="5" onchange="rangevalue.value=value"/></label> <output id="rangevalue">50</output> (output: result of a calculation)></p>
<p><label>pattern: <input type="text" pattern="[A-z]{3}.[0-9]{2}-[A-z]{1,}" placeholder="Abc.12.Bxxxxxx-" /></label></p>
<p><label>tel: <input type="tel" placeholder="phone" /></label></p>
<p><label>search: <input type="search" placeholder="search" /></label></p>
<p><label>datalist:<input list="cities" name="cities" > <em>(autocomplete)</em>
<datalist id="cities">
<option value="Arezzo"> <option value="Firenze"> <option value="Livorno"> <option value="Pisa">
</datalist></label></p>
<p><label>autocomplete off:<input type="text" name="autocompleteoff" autocomplete="off" /></label> - <label>autocomplete on: <input type="text" name="autocompleteon" autocomplete="on" /> </label></p>
<p><input type="submit" value="Go"></p>
</form>
<progress max="1000"></progress>
Indicare al browser cosa salvare nella cache di applicazion (una specifica non la cache normale)
Permette anche di navigare un sito offline
<!DOCTYPE HTML>
<html manifest="clock.appcache">
...
</html>
CACHE MANIFEST
# 2012-03-08:v1
# risorse esplicitamente in cache
index.html
./style/clock.css
./script/clock.js
# se offline mostra offline.html
FALLBACK:
/ /offline.html
# risorse richieste in una connessione online
NETWORK:
some.cgi
# risorse addizionali da mettere in cache
CACHE:
./images/clock.png
Esempio
Impostare il MIME type su Apache:
# in httpd.conf the MIME can be associated with to a specific extension:
# Apache mimetype configuration
# APACHE_HOME/conf/mime.types
text/cache-manifest manifest
#set the Web server so that the manifest file is never cached
# Cache settings for the manifest file
<IfModule mod_expires.c>
Header set cache-control: public
ExpiresActive on
# Prevent receiving a cached manifest
ExpiresByType text/cache-manifest "access plus 0 seconds"
</IfModule>
# manifest file must be served with the mime-type text/cache-manifest
AddType text/cache-manifest .appcache
{
"name": "The Example App",
"short_name": "Example",
"description": "Exciting Open Web development action!",
"launch_path": "/",
"version": "1.0",
"icons": {
"16": "/img/icon_16.png",
"48": "/img/icon_48.png",
"128": "/img/icon_128.png"
},
"developer": {
"name": "Foo Corp.",
"url": "http://example.org/dev"
},
"appcache_path": "/cache.manifest",
"locales": {
"es": {
"description": "¡Emocionante desarrollo Open Web en acción!",
"developer": {
"url": "https://example.org/dev/es-ES"
}
}
},
"default_locale": "en",
"permissions": {
"contacts": {
"description": "Required for auto-completion in the share screen",
"access": "read"
}
}
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>
var ws = new WebSocket('ws://localhost:8080/TomcatWebSockets/testWebSocket');
ws.onmessage = function (message) {
console.log("message received : " + message.data);
var messages = document.getElementById('messages');
messages.innerHTML += "<br>[in] " + message.data;
};
ws.onopen = function() {
console.log("Websocket Ready!!");
//sendMessage();
};
ws.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
sendmsg = function() {
var message = document.getElementById('message_to_send').value
document.getElementById('message_to_send').value = ''
ws.send(message);
console.log("message sent");
var messages = document.getElementById('messages');
messages.innerHTML += "<br>[out] " + message;
};
</script>
</head>
<body>
<form action="javascript:sendmsg()">
<input type="text" id="message_to_send" name="msg"/>
<input type="button" name="btn" id="sendMsg" value="Send" onclick="javascript:sendmsg();">
<div id="messages"></div>
</form>
</body>
</html>
Server diffonde (push) informazioni ai browser
// javascript
var source = new EventSource('http://localhost:8080/ServerSideEvents/SSE');
// register an SSE
source.onmessage=function(event){ // where a message arrives
document.getElementById("result").innerHTML=event.data; // show it
}
public class SSE extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response){
response.setContentType("text/event-stream");
PrintWriter pw = response.getWriter();
pw.write(information_i_want_to_push + "\n\n");
pw.close();
}
vedi esempio ServerSentEvents (netbeans)
var worker = new Worker('code_we_want_to_run_in_background.js');
worker.onmessage = function(event) {
console.log('Worker message: ' + event.data);
};
Esempio numeri primi (firefox)
Altre API
Per contribuire a decidere a sviluppare un Web per Tutti!
Se non è sul Web
...troverete le slides all'indirizzo http://www.w3c.it/talks/2013/smau2013/
Aprire la presentazione impostata con lo stile per la stampa in formato PDF