Tecnologie come HTML5 e CSS3 si offrono agli sviluppatori possibilità incredibili per lo sviluppo di siti Web ed applicazioni moderne, veloci e sempre più simili alle loro controparti Desktop. Come rovescio della medaglia abbiamo la necessità di gestire la compatibilità cross-broser: alcune funzionalità di ultima generazione offerte da HTML5 e CSS3 non sono ancora standard completamente stabili, o non sono supportate alla stessa maniera da tutti i client.
Di versione in versione, Internet Explorer mostra ogni volta di più la particolare attenzione che Microsoft presta nei confronti degli standard Web. Nel corso degli ultimi anni, grandissimi miglioramenti sono stati apportati al browser di Redmond per essere sempre più aderente agli standard proposti dal W3C per lo sviluppo Web.
Il fatto che i più grandi produttori di browser si stiano sempre più muovendo in questa direzione, ovviamente, apre strade estremamente interessanti e si traduce in enormi benefici per gli sviluppatori di siti ed applicazioni Web. Infatti, questo rende possibile la realizzazione di prodotti moderni e che sfruttino tutte le potenzialità del Web di ultima generazione, senza doversi preoccupare della compatibilità con tutti i vari browser Web più diffusi.
HTML5 API
Fra le caratteristiche più rilevanti che possiamo trovare in Internet Explorer 10 c'è il supporto per tutta una serie di funzionalità che stanno davvero facendo di HTML5 il nuovo standard del Web.
Fra questi troviamo ad esempio i Web Sockets, che garantiscono canali di comunicazione bidirezionali e real-time verso server remoti, oppure, per quanto riguarda il front-end e la grafica, l'aggiunta del supporto per i Web Fonts o i filtri SVG, che consente una maggiore espressività ai Web Designers e un minor ricorso ad immagini pronte rispetto a contenuti grafici generati dinamicamente.
Analizziamo alcune delle HTML5 API più importanti supportate da Internet Explorer 10.
Pointer
Grazie ad un mercato in cui tablet e sistemi touch come Windows 8 sono molto diffusi, è necessario progettare i propri siti ed applicazioni Web che supportino input differenti.
IE10 ha introdotto le Pointer API e le Gesture API, che rendono trasparente allo sviluppatore se l'utente sta utilizzando un mouse, il dito o un pennino e aiutano nel riconoscimento delle interazioni gestuali. Attualmente le specifiche sono in draft, ma sono state inviate al W3C per l'accettazione come standard.
Le MSPointer API permettono di fare facilmente fallback alle vecchie modalità di interazione già supportate da tutti i browser. Quindi ad esempio, è possibile effettuare la feature detection e scoprire se queste API sono supportate dal browser dell'utente, o appoggiarsi al tradizionale evento "mousemove" se le nuove funzionalità non sono supportate, in un codice come il seguente per una piccola applicazione di disegno:
var canvas = document.createElement("canvas");
canvas.style = "-ms-touch-action: none";
if (window.navigator.msPointerEnabled) {
canvas.addEventListener("MSPointerMove", draw, false);
} else {
canvas.addEventListener("mousemove", draw, false);
}
E la funzione di callback draw
potrà usare in modo trasparente qualunque delle due API:
function draw (e) {
canvas.getContext("2d").fillRect(e.clientX, e.clientY, 2, 2);
}
Lo stile CSS -ms-touch-action: none serve a specificare che gli eventi touch sull'elemento non devono essere gestiti automaticamente, poiché altrimenti porterebbero al normale scrolling della pagina invece che essere intercettati e gestiti dalla nostra applicazione di disegno.
WebWorkers
I Web Workers permettono di migliorare sostanzialmente le performance delle applicazioni Web spostando l'elaborazione di codice JavaScript su thread differenti da quello dell'interfaccia grafica. In questo modo, l'esecuzione della pagina rimane fluida anche effettuando operazioni JavaScript lunghe e complesse.
Per creare un nuovo WebWorker è sufficiente utilizzare il costruttore, passandogli come parametro il file JavaScript contenente il codice da eseguire sul thread separato del worker:
var worker = new Worker("operazionecomplessa.js");
I worker comunicano fra loro tramite lo scambio di messaggi, quindi possiamo sottoscriverci all'evento di messaggio ricevuto da un certo worker per sapere quando ha finito il suo lavoro, e poi inviargli un messaggio - che può essere un qualunque oggetto JS - di inizio del processamento tramite la funzione postMessage()
:
worker.onmessage = function (e) {
alert("Worker ha finito!");
};
worker.postMessage({
employee: { firstname: "Daniele", lastname: "Midi" },
operation: "makepayment",
month: "January"
});
A questo punto non ci resta che scrivere il codice dello script "operazionecomplessa.js" da far eseguire al WebWorker. Sarà sufficiente registrarsi all'evento onmessage per ricevere il messaggio di avvio che il thread principale manderà con i dati da processare:
self.onmessage = function (e) {
var employee = e.data.employee;
// effettua il pagamento
self.postMessage({ result: "OK" });
close();
}
Alla fine del processamento, è buona norma invocare il metodo close() per terminare il thread e liberare risorse. Inoltre, può essere una buona pratica separare un'operazione molto complessa (qualora sia parallelizzabile) in un numero di WebWorkers pari a 4 o suoi multipli, poiché questo è il numero di processori più comunemente presente nei PC di tutto il mondo al momento.
È da sottolineare che poiché i WebWorker vivono in un thread diverso dalla UI, non hanno accesso al DOM.
IndexedDB
Il supporto per gli IndexedDB permette agli sviluppatori di memorizzare informazioni strutturate lato client, avendo così la possibilità di realizzare applicazioni Web in grado di continuare a funzionare anche in modalità offline pur continuando ad appoggiarsi ad una tecnologia standard ed il più possibile cross-browser.
Gli IndexedDB non sono tradizionali DB relazionali, ma sono definiti "Object Stores", più simili ad un NoSQL DB, molto in voga al momento. Poiché ora la specifica delle API è ufficiale e stabile, gli IndexedDB funzionano alla stessa maniera su tutti i browser che li supportano.
Negli IndexedDB tutte le operazioni sono asincrone e possono essere eseguite solo all'interno di transazioni.
Vediamo un semplice esempio di utilizzo degli IndexedDB con Internet Explorer 10 per memorizzare una lista di cose da fare.
var request = window.msIndexedDB.open("ToDoManager", 1);
request.onsuccess = function (e) {
// leggiamo gli elementi della lista già memorizzati
};
request.onupgradeneeded = function (e) {
var db = e.target.result;
var tr = e.target.transaction;
var objStore = db.createObjectStore("todos", { keyPath: "timestamp" });
tr.oncomplete = function () { alert("DB creato con successo."); };
}
request.onerror = function () { alert("Si è verificato un errore."); };
request.onblocked = function () { alert("Creazione del DB bloccata."); };
Il codice è molto semplice: prima di tutto apriamo la connessione ad un database chiamato ToDoManager
, specificando un numero di versione. Se il DB esiste già con il numero di versione specificato, viene eseguita la funzione di callback onsuccess, dove procederemo a leggere gli elementi della ToDoList
. Se invece il DB non esiste, o la versione è diversa, verrà eseguito il codice della funzione onupgradeneeded, dove procederemo a richiedere la creazione di un Object Store di nome "todos" in cui la chiave primaria degli elementi è la proprietà timestamp. Gli altri due callback servono a gestire gli eventuali errori.
Per aggiungere elementi al database è sufficiente usare codice come il seguente:
var tr = db.transaction(["todos"], "readwrite");
var objSt = tr.objectStore("todos");
var insertReq = objSt.put({
"timestamp" : new Date().getTime(),
"msg": "Nuova cosa da fare"
});
insertReq.onsuccess = function(e) {
// aggiornare gli elementi di ToDo mostrati nella pagina
};
insertReq.onerror = function (e) { alert("Errore durante la lettura: " + e.value); };
In questo snippet di codice semplicemente apriamo una nuova transazione per l'Object Store todos, quindi creiamo un nuovo elemento della ToDo list assegnandogli un timestamp e un messaggio, e specifichiamo anche le funzioni di callback per successo o errore.
Per leggere elementi dal database, invece, il codice deve essere come il seguente:
var todoUL = document.getElementById("ULToDoList");
todoUL.innerHTML = "";
var tr = db.transaction(["todos"], "readwrite");
var objSt = tr.objectStore("todos");
var cursorReq = objSt.openCursor();
cursorReq.onsuccess = function (e) {
var cur = e.target.result;
if (cur) {
var todoLI = document.createElement("li");
todoLI.innerHTML = cur.value.msg;
todoUL.appendChild(todoLI);
cur.continue();
}
};
In questo snippet apriamo di nuovo una transazione, richiediamo un cursore per scorrere gli elementi nell'Object Store todos, e per ognuno di essi andiamo a renderizzare un tag LI all'interno di una lista presente nel nostro DOM.
Interpretazione dei tag HTML5
Il motore di rendering di Internet Explorer 10 ha fatto numerosi passi avanti rispetto alla precedente versione 9 anche nei confronti del parsing del codice HTML. L'analisi di eventuali tag malformati, non chiusi, sovrapposti o mal posizionati può ora contare su un'interpretazione molto più efficace e vicina al significato semantico effettivamente atteso.
Inoltre, attraverso gli Strumenti per gli Sviluppatori F12 (già introdotti ed analizzati nel precedente articolo [LINK all'altro articolo]), gli errori di parsing dell'HTML sono ora presentati allo sviluppatore insieme al report degli errori degli script Javascript, rendendo l'individuazione dei problemi estremamente più veloce ed efficacie.
Supporto a CSS3 di Internet Explorer 10
È probabilmente rispetto alle specifiche di Cascading StyleSheets Level 3 (più noto come CSS3), però, che il team di sviluppo di Internet Explorer 10 ha fatto il più grande salto di qualità. Rispetto al già buon lavoro fatto per la versione 9, Internet Explorer 10 offre ora il supporto dei layout multi colonne, il layout Flexible Box, e il Grid Layout.
Inoltre, è migliorato il supporto nativo per i Gradients, e le Transizioni, Animazioni e Trasformazioni 3D non hanno più bisogno del prefisso vendor specific, quindi ad esempio invece di:
ms-animation: /* ... */
è possibile scrivere semplicemente:
animation: /* ... */
andando incontro ad una convergenza di compatibilità fra tutti i maggiori browser.
In questo contesto, le migliorie sono state apportate tanto alla quantità di funzionalità che è ora supportata, quanto alle performance raggiunte nel rendering delle pagine Web.
Una delle cose più complesse da realizzare con il CSS fino a questo momento è stato il layout a griglia che si adattasse a qualsiasi risoluzione o dimensione della finestra. Con l'aggiunta del supporto per il Grid Layout in Internet Explorer 10, è ora possibile ottenere layout complessi e adattivi in modo molto semplice.
Realizziamo il seguente layout:
È sufficiente utilizzare un codice HTML semplice come il seguente:
<div id="layout">
<div id="layout">LOGO</div>
<div id="login">Accedi o registrati</div>
<div id="main">Contenuto principale...</div>
<div id="leftsidebar">Sidebar di sinistra</div>
<div id="rightsidebar">Sidebar di destra</div>
</div>
E impostare il layout utilizzando solo pochi stili CSS:
#layout {
display: -ms-grid;
-ms-grid-columns: auto 1fr auto;
-ms-grid-rows: auto 1fr;
}
#titolo { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column-span: 2; }
#login { -ms-grid-row: 1; -ms-grid-column: 3; }
#leftsidebar { -ms-grid-row: 2; -ms-grid-column: 1; }
#main { -ms-grid-row: 2; -ms-grid-column: 2; }
#rightsidebar { -ms-grid-row: 2; -ms-grid-column: 3; }
Nello stile dell'elemento "layout" specifichiamo di volere 3 colonne e 2 righe; "auto" specifica che lo spazio deve adattarsi al contenuto, mentre con 1fr, 2 fr, ... possiamo indicare quante "frazioni" di pagina vogliamo occupare con quella determinata riga o colonna.
A questo punto, per ognuno degli elementi del layout basta specificare riga o colonna in cui inserirlo, ed eventualmente per quante righe/colonne deve estendersi.
Integrazione con il sistema operativo
Approfittando del grande supporto per gli standard HTML5 e CSS3 offerto da Internet Explorer 10, è anche possibile integrare maggiormente il proprio sito o applicazione Web con il sistema operativo.
Ad esempio, infatti, grazie alle Media Query di CSS3 è molto semplice realizzare efficaci layout adattivi che permettano alla pagina di scalare ed adattarsi a qualsiasi dimensione della finestra del browser. Questa tecnica, particolarmente interessante per rendere i propri contenuti fruibili su tutti i device, eventualmente con schermi molto piccoli, diventa un'interessante arma nelle mani degli sviluppatori anche per integrare il proprio sito Web con Windows 8. Prevedere delle modalità di layout adattivo per supportare lo Snapped Mode di Internet Explorer 10 in versione Modern UI Style fa apparire il proprio sito o Web application come molto più simile ad una app nativa per Windows 8.
Compatibility Cookbook
Ovviamente, diventando ogni volta più aderente agli standard, di versione in versione Internet Explorer ha dovuto rinunciare ad alcune delle feature vendor-specific che in passato aveva offerto. Il grande salto verso la compatibilità con HTML5 e CSS3 che la versione 10 del browser Microsoft ha fatto rappresenta senza dubbio una rottura col passato senza precedenti.
Per questo, la software house di Redmond ha deciso di mettere a disposizione di tutti gli sviluppatori un Compatibility Cookbook, un "libro delle ricette" che spiega come far sì che i propri siti ed applicazioni Web realizzati per le versioni precedenti di Internet Explorer e che facevano uso di funzionalità particolari e specifiche del browser possano continuare a funzionare anche con Internet Explorer 10 migrando verso codice maggiormente aderente agli standard.
Ad esempio, i Commenti Condizionali sono particolari tag HTML che utilizzano la sintassi di un normale commento HTML in modo da essere ignorati dagli altri browser, ma vengono renderizzati come contenuto in Internet Explorer, come mostrato nel seguente snippet di codice:
<html>
<!--[if IE]>
Contenuto ignorato negli altri browser ma mostrato nella pagina su Internet Explorer.
<![endif]-->
</html>
Nell'ultima versione del browser Microsoft, il supporto per i commenti condizionali è stato completamente rimosso sia nelle modalità standard che nei "quirks modes" (le modalità di rendering delle pagine che permettono di supportare codice non standard-compliant). Questo significa che da questa versione di Internet Explorer in poi, i commenti condizionali sono trattati come normali commenti e quindi ignorati come nel resto dei browser. Nel Compatibility Cookbook, Microsoft offre agli sviluppatori le linee guida ed i workaround necessari per mantenere le funzionalità desiderate anche in Internet Explorer 10.
Insieme a queste "ricette pronte" di aggiornamento del proprio codice, Microsoft mette a disposizione anche molte linee guida per realizzare siti ed applicazioni Web moderni e che siano pronti per l'era del Web attuale. Ad esempio, un'intera sezione è dedicata a come progettare sin dall'inizio siti Web pensati principalmente per un interazione touch, allo scopo di essere pronti per tutti i device che stanno rapidamente conquistando incredibili numeri di utenti, come tablet e smartphone di ultima generazione.