accesskey
Acquista il libro su Apogeonline
Google Memoria dello Spazio

Capitolo 11

Garantire la diretta accessibilità delle interfacce utente incorporate. Parte 1ª: JavaScript e AJAX

WCAG 1.0, linea guida 8. Garantire che l'interfaccia utente segua i principi della progettazione accessibile: accesso alle funzionalità indipendente dal dispositivo, possibilità di operare da tastiera, auto-lettura vocale ecc.

La linea guida 8 ha un solo punto di controllo, che ha priorità 1 o 2 a seconda dei casi.

Punto di controllo 8.1, priorità 1

Rendere gli elementi di programmazione come script e applet direttamente accessibili o compatibili con le tecnologie assistive.

Si rivolge a: sviluppatori (programmatori, tecnici del codice).

Applicare le specifiche dei produttori per l’accessibilità delle interfacce utente proprietarie

Chi vuole soddisfare il punto di controllo 8.1 deve affrontare e risolvere uno dei problemi più importanti e più difficili nell’ambito dell’accessibilità: rendere visibili alle tecnologie assistive i contenuti web generati da linguaggi di scripting e oggetti incorporati.

Come è noto, HTML e XHTML sono più che altro linguaggi di descrizione di contenuti statici. L’interattività è limitata ai collegamenti ipertestuali e ai moduli (form). Per compensare questa carenza e realizzare interfacce dinamiche e variamente interattive, fu necessario ricorrere ben presto alla potenza supplementare di linguaggi di script, supportati dagli stessi browser (JavaScript, Jscript, VBScript), e a oggetti incorporati, dotati di interfaccia utente e funzionalità proprie (Java, Flash, SMIL, SVG ecc.).

Alle interfacce incorporate non possono, però, essere applicate le stesse regole di accessibilità che valgono per HTML e CSS. Ai contenuti scritti in HTML è possibile, per esempio, applicare le raccomandazioni di marcare le tabelle di dati usando TH per le intestazioni e TD per i dati, di usare onkeypress insieme a onclick per rendere gli script attivabili in modo indipendente dal dispositivo di input, di eliminare dal codice di marcatura elementi e attributi di presentazione, delegando le modifiche grafiche ai CSS. Sono prescrizioni che non possono, però, valere alla lettera per oggetti scritti in linguaggi che hanno caratteristiche del tutto diverse da quelle di HTML e CSS.

La linea guida 8, pertanto, con il suo unico punto di controllo, si limita a prescrivere princìpi generali per l’accessibilità delle interfacce utente incorporate, qualsiasi sia il linguaggio, il plug-in o lo strumento autoriale che le produce o le riproduce. Riportiamo di seguito un estratto dalla sezione 8.2 Directly Accessible Applets collegamento esterno, delle Tecniche HTML per le WCAG 1.0:

Se un’applet (creata con OBJECT o con APPLET) richiede un’interazione da parte dell’utente (per esempio: la capacità di manipolare un esperimento di fisica) che non può essere duplicata in un formato alternativo, rendere l’applet direttamente accessibile.

Se un’applet crea movimento, gli sviluppatori dovrebbero fornire un meccanismo per congelare il movimento. (...)

Il brano continua fornendo riferimenti, in parte datati, a risorse per implementare caratteristiche di accessibilità direttamente all’interno delle interfacce realizzate in Java, che, negli anni in cui furono pubblicate le WCAG 1.0 e i documenti associati, era sicuramente molto più usato di oggi, come strumento per creare inserti dinamici e interattivi all’interno di documenti HTML.

Il concetto principale sotteso dal punto di controllo 8.1 è che la diretta accessibilità delle interfacce utente incorporate deve essere garantita da apposite funzioni per l’accessibilità, disponibili all’interno dei linguaggi e degli strumenti utilizzati per realizzare tali oggetti.

Se questi sono implementati con tecnologie del W3C, come SMIL e SVG, le caratteristiche di accessibilità sono assicurate e standardizzate dallo stesso Consorzio. Se, invece, gli oggetti sono realizzati con tecnologie proprietarie, bisogna ricorrere alla documentazione e al supporto per l’accessibilità forniti dal produttore. Ciò vale per Java, linguaggio che l’americana Sun ha finalmente deciso, a partire da novembre 2006, di rendere pubblico, aperto e gratuito, distribuendone il codice sorgente sotto una licenza GPL. Vale per il formato PDF, sigla di Portable Document Format, inventato da Adobe nel 1993 e da allora più volte rielaborato, con recenti che ne migliorano grandemente il supporto per l’accessibilità. Vale, ancora, per il formato SWF (ShockWave File), usato come implementazione degli oggetti realizzati con Adobe Flash. Vale, infine, per i formati DOC e RTF (usati per pubblicare sul Web documenti di testo complessi, solitamente destinati alla stampa), stante la capacità di molti browser di riprodurre tali documenti all’interno di un’interfaccia utente incorporata, grazie ad appositi plug-in.

In sostanza, il punto di controllo 8.1 rappresenta un richiamo agli sviluppatori, affinché realizzino oggetti di programmazione conformi agli stessi principi generali di accessibilità che valgono per le comuni pagine HTML e XHTML: i contenuti incorporati dovrebbero, cioè, essere resi compatibili con gli screen reader, comandabili indifferentemente dalla tastiera e dal mouse, forniti di testi alternativi e privi di lampeggiamenti e sfarfallamenti se sono di tipo grafico, dotati di comandi per interrompere il movimento ecc.

È chiaro che l’implementazione di simili caratteristiche non dipende esclusivamente dagli sviluppatori, ma in buona parte dal supporto fornito dai produttori. Se, per esempio, un oggetto realizzato in Flash risulta utilizzabile solo con alcuni screen reader e solo attraverso Internet Explorer avremo un’accessibilità parziale, perché limitata a un certo tipo di browser e di piattaforma: un limite che gli sviluppatori non possono oltrepassare, perché dipende dal fatto che Adobe Flash dispone di integrazione con le librerie per l’accessibilità MSAA di Microsoft piuttosto che con quelle di altri produttori.

A complicare ulteriormente le cose, nella riproduzione dei contenuti incorporati entrano in gioco anche le attrezzature e le conoscenze informatiche degli utenti. Infatti, un documento PDF o Flash, anche se realizzato seguendo scrupolosamente le specifiche di accessibilità del produttore, può risultare difficile o impossibile da riprodurre, se l’utente usa sistemi non compatibili con quei formati o se non dispone delle conoscenze informatiche necessarie per installare nel proprio browser i plug-in, senza i quali non è possibile riprodurre file PDF o SWF.

[Inizio approfondimento] Sovrapposizione di scopo del punto di controllo 8.1 con UAAG e ATAG

Lo scopo del punto di controllo 8.1, nel richiedere l’accessibilità delle interfacce utente incorporate, si sovrappone in parte a quello delle linee guida sull’accessibilità dei programmi utente (UAAG, User Agent Accessibility Guidelines collegamento esterno) e a quello delle linee guida per l’accessibilità degli strumenti autoriali (ATAG, Authoring Tool Accessibility Guidelines collegamento esterno). Lo conferma una nota che le WCAG 1.0 fanno seguire al testo del punto di controllo collegamento esterno, che consiglia agli sviluppatori di far riferimento proprio alle Raccomandazioni ATAG e UAAG, per acquisire informazioni sulla progettazione di interfacce accessibili. [Fine approfondimento]

[Inizio approfondimento] Le API per l’accessibilità

La sigla API sta per Application Programming Interface, che possiamo rendere in italiano con “interfaccia per la programmazione di applicazioni”. Nell’accezione più comune, le API sono librerie di codice preconfezionate, che gli sviluppatori possono riutilizzare ogni volta che hanno bisogno di integrare nelle loro applicazioni delle funzioni di base, come per esempio l’aspetto e i comportamenti delle finestre di dialogo in un sistema operativo, che sarebbe troppo lungo e dispendioso riscrivere ogni volta da zero. Le API svolgono un ruolo di collegamento essenziale tra il livello fisico dei dispositivi e quello astratto del software. Nel campo dell’accessibilità, per esempio, una tecnologia assistiva come uno screen reader può “dialogare” efficamente con le applicazioni e con l’hardware collegato al computer, se sono presenti nel sistema operativo apposite API per l’accessibilità.

Il funzionamento di tali API è basato sul criterio di rendere visibili alle tecnologie assistive e ordinare gerarchicamente ruoli, stati e proprietà degli oggetti dell’interfaccia, in modo che l’utente possa conoscerli e modificarli. È molto importante che chi sviluppa applicazioni accessibili e tecnologie assistive conosca e utilizzi le informazioni che le API per l’accessibilità sono in grado di veicolare. Non sarebbe possibile, per esempio, rendere direttamente accessibile un oggetto Java incorporato, come richiede il punto di controllo 8.1 delle WCAG 1.0, senza usare le apposite classi per l’accessibilità disponibili in Java.

Purtroppo non esiste un unico pacchetto di API per l’accessibilità, ma ne esistono diversi, a seconda del sistema operativo e dell’infrastruttura software di riferimento; ciò complica non poco il lavoro di chi intende sviluppare applicazioni accessibili multipiattaforma.

Le API per l’accessibilità più note e utilizzate sono MSAA (Microsoft Active Accessibility) per sistemi operativi Windows. La documentazione del pacchetto di Microsoft per l’accessibilità collegamento esterno, giunto alla versione 2.0, è disponibile online (si veda anche la sezione del portale Microsoft dedicata all’accessibilità collegamento esterno.

Per quanto riguarda i sistemi operativi Mac OS X di Apple, esistono due diverse infrastrutture software, Carbon e Cocoa, che richiedono API per l’accessibilità differenti. Varie guide su come rendere accessibili applicazioni sviluppate per sistemi operativi Mac OS X sono disponibili sul portale degli sviluppatori di Apple collegamento esterno.

Esistono API per l’accessibilità anche per i sistemi operativi Linux. Per la piattaforma GNOME esistono tre librerie di API per l’accessibilità: ATK, AT-SPI e GAIL. Tutta la documentazione tecnica necessaria per utilizzare tali librerie è disponibile a partire dall’indice http://developer.gnome.org/doc/API/ collegamento esterno.

Per gli sviluppatori che lavorano con Java, esiste una dettagliata guida all’uso delle API per l’accessibilità di questo linguaggio, intitolata IBM Guidelines for Writing Accessible Applications Using 100% Pure Java. La documentazione tecnica del pacchetto di API per l’accessibilità contenute nella versione 6 di Java è presente sul sito Sun, a partire dall’indice http://java.sun.com/javase/6/docs/api/javax/accessibility/package-summary.html collegamento esterno.

Un’interessante tabella, che mette in relazione con riferimenti incrociati le varie API per l’accessibilità fin qui elencate, è stata realizzata dal gruppo di sviluppatori che fa parte del progetto Mozilla. È contenuta in un documento intitolato Accessibility API cross-reference collegamento esterno. [Fine approfondimento]

Inizio pagina

Salta inserzione pubblicitaria

JavaScript e accessibilità

Il rapporto tra JavaScript e accessibilità è difficile e complesso.

In primo luogo, l’utilizzo di JavaScript richiede un browser dotato di adeguato supporto: ciò produce un fattore di discriminazione, perché rende dipendente dal dispositivo la possibilità di accedere ai contenuti generati o modificati con JavaScript.

In secondo luogo, l’accessibilità intrinseca delle interfacce modificate con JavaScript, anche in browser e tecnologie assistive dotati di adeguato supporto, non è per nulla scontata. Essa dipende, infatti, da vari fattori:

Nei paragrafi successivi analizzeremo i vari modi in cui JavaScript può rendere inaccessibile o, al contrario, accessibile un’interfaccia utente. Ci occuperemo, in particolare, di DHTML, di JavaScript non invasivo (unobtrusive JavaScript), di AJAX e rich applications e, infine, delle bozze di Specifiche W3C che vanno sotto il nome di WAI-ARIA e che definiscono le regole per rendere accessibili le applicazioni dinamiche basate su AJAX e sull’uso di JavaScript in generale. È questa, al momento, la frontiera più avanzata con cui l’accessibilità si sta confrontando.

Inizio pagina

Origini e standardizzazione di JavaScript

JavaScript comparve per la prima volta nella versione 2.0B3 di Netscape Navigator, nel dicembre del 1995, inventato dal programmatore Brendan Eich. È un linguaggio cosiddetto “di scripting”, che viene interpretato dal browser, applicando senza bisogno di compilazione preliminare istruzioni “ad alto livello”, scritte cioè in una forma più vicina al linguaggio degli umani che a quello dei computer. La serie ordinata delle istruzioni forma lo script (da cui scripting), parola inglese che significa “copione”. Il browser legge le “battute” del copione (cioè le istruzioni dello script) e le “interpreta”, eseguendo le azioni che esso descrive.

È interessante leggere, dall’annuncio congiunto di Netscape e Sun Microsystems, che contiene il lancio ufficiale di JavaScript collegamento esterno, datato 4 dicembre 1995, un brano che spiega cos’è e a cosa sarebbe dovuto servire, nelle intenzioni dei produttori, questo nuovo linguaggio:

JavaScript è un linguaggio di scripting a oggetti di facile uso, progettato per creare applicazioni online in tempo reale che mettono in relazione oggetti e risorse sia sui client che sui server. Mentre Java è usato dai programmatori per creare nuovi oggetti e applet, JavaScript è progettato per essere usato dagli autori di pagine HTML e dagli sviluppatori di applicazioni per le imprese, per definire dinamicamente il comportamento di oggetti in esecuzione sia sul client sia sul server.

JavaScript - continua il testo dell’annuncio - è un linguaggio complementare a e integrato con Java; complementare a e integrato con HTML; aperto e multipiattaforma.

Con JavaScript, una pagina HTML potrebbe contenere un modulo intelligente che esegue, direttamente sul client, calcoli per il rimborso di prestiti o il tasso di cambio in risposta a un input dell’utente. Un’applet multimediale scritta in Java per le previsioni del tempo può essere guidata da JavaScript a visualizzare immagini e suoni appropriati, basati sulle effettive rilevazioni del tempo in una regione. [...]

Programmi Java e script JavaScript sono progettati per essere eseguiti sia sui client che sui server, con JavaScript usato per modificare le proprietà e i comportamenti degli oggetti Java, così che la gamma di applicazioni online in tempo reale, che presentano dinamicamente informazioni all’utente e interagiscono con esso su reti locali o su Internet, è virtualmente illuminata.

Questi estratti del 1995 ci dicono che la vocazione iniziale di JavaScript, almeno per quello che riguarda l’uso su un computer client, era quella di “modificatore” di oggetti Java: una sorta di anello di congiunzione tra l’HTML, statico e per lo più testuale, e gli inserti realizzati in Java, dinamici e interattivi. Una vocazione confermata anche dal nome, JavaScript, che richiama una parentela con Java, che è in realtà meno stretta di quanto il nome lasci presumere.

Durante i numerosi anni passati da quell’annuncio, si è andata sempre più allargando - nell’uso e negli interessi degli sviluppatori - la distanza tra Java e JavaScript, anche in concomitanza della progressiva diminuzione dell’uso di interfacce utente Java incorporate all’interno di pagine web, coincidente con la parallela (ed esponenziale) crescita delle interfacce incorporate realizzate in Flash.

In virtù di questa progressiva separazione da Java, JavaScript ha finito per essere usato soprattutto come complemento per HTML e XHTML, cioè come strumento per l’aggiunta di funzioni dinamiche e interattive alle pagine web, ormai senza più alcun richiamo a un’integrazione con Java.

Formalizzato nello standard ECMA-262 (Ecmascript Language Specification, 3ª edizione del dicembre 1999), il linguaggio inventato da Brendan Eich, si è arricchito col tempo di estensioni e di contributi di altre implementazioni, come il JScript sviluppato da Microsoft e utilizzato a partire da Internet Explorer 3.0.

È interessante leggere, a pag. 14 della terza edizione delle Specifiche ECMA-262 collegamento esterno, quale deve essere il supporto fornito da un browser conforme al linguaggio di scripting che esse descrivono:

Un browser web fornisce un ambiente ospite per ECMAScript, per l’esecuzione di calcoli lato client, comprendenti, per esempio, oggetti che rappresentano finestre, menu, pop-up, finestre di dialogo, campi d’immissione testo, ancore, frame, cronologia, cookie e input/output. Inoltre, l’ambiente ospite fornisce strumenti per attaccare codice di scripting a eventi quali cambiamento di focus, caricamento di pagina e immagini, scaricamento, errore e interruzione, selezione, invio di moduli e azioni del mouse. Il codice di scripting appare all’interno dell’HTML e la pagina visualizzata è una combinazione di elementi dell’interfaccia utente e di testo e immagini fissi e calcolati. Il codice di scripting reagisce all’interazione dell’utente e non è necessario un programma principale [di gestione].

[Inizio approfondimento] JavaScript 1.7

La versione più recente di JavaScript è la 1.7, supportata da Firefox 2.0. Le caratteristiche introdotte con l’ultimo aggiornamento sono spiegate in un’apposita sezione del Mozilla Developer Center collegamento esterno). [Fine approfondimento]

Inizio pagina

DHTML

Gli anni a cavallo del 2000 videro la diffusione sempre crescente di contenuti web realizzati in DHTML. Con questa sigla s’intende un HTML reso dinamico - la “D” iniziale sta appunto per “Dynamic” - grazie all’uso combinato di JavaScript, CSS e DOM. In DHTML vengono generati blocchi di contenuti che possono essere nascosti e fatti ricomparire a piacimento, finestre pop-up, avvisi per segnalare la presenza di errori nella compilazione di moduli, menu che si riempiono di sottomenu al passaggio del mouse, sistemi interattivi basati sul drag & drop, roll-over su link e immagini (cioè il cambiamento dell’aspetto di un link o del contenuto di un’immagine al passaggio del mouse), giochi e ogni sorta di effetti grafici, come le scie di stelline che seguono gli spostamenti del puntatore, molto popolari qualche anno fa.

DHTML era, ed è, uno strumento molto potente, in grado di trasformare l’interfaccia utente in qualcosa di completamente diverso da ciò che si ricava dall’esame del solo codice HTML statico. Ma che rapporto c’è tra DHTML e accessibilità, per ritornare all’argomento del nostro libro? Pessimo, purtroppo.

Sono numerosi i motivi che rendono gli script DHTML poco “amici” dell’accessibilità. Il primo motivo è che vincolano quasi sempre l’accesso ai contenuti alla disponibilità di JavaScript. L’esempio tipico è quello delle finestre pop-up che sono fatte aprire per mezzo di script, come nel Listato 11.1.

Listato 11.1 Un collegamento ipertestuale, per l’apertura di una finestra pop-up, basato su JavaScript.

<a href="javascript:window.open('privacy.html','','width=350,height=250,left=600,top=600,

toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no');">Informazioni

sulla privacy</a>

Chi naviga senza supporto per JavaScript non può seguire il collegamento. E non si tratta di un problema marginale. L’uso invasivo di finestre pop-up pubblicitarie, con grossi danni anche per la sicurezza, a causa del comportamento malizioso di script che inoculano virus e cavalli di troia nei computer altrui, rende una possibilità non remota quella di trovare una discreta percentuale di utenti che usa browser di ultima generazione, ma preferisce navigare con JavaScript disabilitato o, comunque, con filtri che limitano più o meno pesantemente l’esecuzione di script all’interno del browser (Figura 11.1).

Figura 11.1. Le impostazioni avanzate di Firefox 2.0 permettono di definire che cosa il browser consente agli script e che cosa impedisce.

Un secondo problema è rappresentato dall’uso di script DHTML datati, basati su tecniche di sniffing che sono causa quasi certa di errori nei browser contemporanei. Se la mancata o non corretta esecuzione degli script porta all’impossibilità di accedere ai contenuti, ne discende una nuova causa di inaccessibilità, legata all’uso di DHTML.

Per chi non ha dimestichezza con JavaScript, lo sniffing (parola inglese che vuol dire “fiutare”) è un metodo per recuperare l’identità del browser che richiede lo script, allo scopo di fornirgli un codice adatto alle sue capacità di esecuzione, e diverso da quello fornito ad altri browser.

Si tratta di un metodo assolutamente non pratico, perché lo script fallisce se il browser collegato non ricade in nessuna delle alternative previste dallo sviluppatore, cosa che può accadere facilmente quando si utilizzano script vecchi di qualche anno. E tuttavia era un metodo necessario, in un’epoca in cui il DOM (Document Object Model, “Modello a oggetti del documento”) standard definito dalle specifiche del W3C non era ancora supportato e i browser avevano ciascuno un proprio modello di DOM. Identificando tramite sniffing il modello di DOM supportato da un browser, era possibile fornirgli i comandi giusti per manipolare oggetti e proprietà all’interno del suo albero del documento, ottenendo le trasformazioni dinamiche definite dallo script.

Il Listato 11.2 mostra un esempio di script che svolge funzioni di sniffing.

Listato 11.2 Un JavaScript che cambia le istruzioni a seconda del browser.

if (document.all) {

// qui va il codice per Internet Explorer 4

}

else if (document.layers) {

// qui va il codice per Netscape 4

}

Un browser che non riconosce né document.alldocument.layers come metodi per accedere ai contenuti dell’albero del documento non può eseguire le istruzioni inserite sotto nessuna delle due condizioni.

Una terza ragione d’inaccessibilità è la possibile interferenza tra script, e quindi il non funzionamento di uno o più di essi, determinata per esempio dall’uso di variabili globali, dichiarate cioè esternamente alle funzioni. L’interferenza tra script dipende da una codifica non professionale, concepita come se ogni script dovesse essere l’unico associato a un determinato documento HTML. Ciò può capitare quando si associano a uno stesso documento script di provenienza eterogenea, magari copiati da siti che mettono a disposizione materiale gratuito: non è raro che tali script usino casualmente i medesimi nomi di variabile o di funzione (per esempio init, scelto spesso dai programmatori per denominare la funzione che dà inizio a un processo).

Listato 11.3 Interferenza tra variabili globali e locali in JavaScript.

function funzione_1()

{

var x = 3; // variabile locale

document.write ("All'interno di funzione_1, x=" + x + ";<br>");

funzione_2();

document.write ("All'interno di funzione_1, x=" + x + ";<br>");

}

function funzione_2()

{

document.write ("All'interno di funzione_2, x=" + x + ";<br>");

}

x = 1; // variabile globale

document.write ("All'esterno, x=" + x + ";<br>");

funzione_1();

document.write ("All'esterno, x=" + x);

L’esecuzione dello script contenuto nel Listato 11.3 produce il seguente risultato:

All’esterno, x=1;
All’interno di funzione_1, x=3;
All’interno di funzione_2, x=1;
All’interno di funzione_1, x=3;
All’esterno, x=1

Come si può vedere, funzione_2(), eseguita all’interno di funzione_1(), non ritiene il valore di x dichiarato da funzione_1(), che è 3, ma usa il valore 1, dichiarato dalla variabile globale, esterna a entrambe le funzioni. Quando si assemblano script di provenienza diversa, errori simili sono frequentissimi e la possibilità di identificarli e risolverli, effettuando il cosiddetto debugging, non è molto alta, a meno di non avere buone doti di programmatore JavaScript (ma allora perché copiare script da terze parti?) e una grande disponibilità di tempo e di pazienza.

Una quarta causa di problemi è la generazione diretta di codice HTML per mezzo dell’istruzione document.write. Il listato seguente è un adattamento del codice realmente generato da uno script per la gestione della pubblicità, utilizzato nelle pagine web di un’importante azienda pubblica italiana.

Listato 11.4 Generazione di codice HTML per mezzo di document.write.

function carica_banner(){

document.write("<!-- Inizio banner -->");

document.write("<SCRIPT LANGUAGE=\"JavaScript1.1\" ");

document.write("SRC=\"http://www.banner.it/js/genera.js\"></SCRIPT>");

document.write("<NOSCRIPT>");

document.write("<A HREF=\"http://www.banner.it/pubblicita.htm"><IMG ");

document.write("SRC=\"http://www.banner.it/image/banner.jpg\"></A>");

document.write("</NOSCRIPT>");

document.write("<!-- Fine banner -->");

}

Nel caso meno pericoloso, il codice HTML generato in questo modo può essere non conforme alla DTD dichiarata. Il codice del Listato 11.4, per esempio, non sarebbe valido, se generato all’interno di una DTD strict, a causa dell’uso dell’attributo deprecato language. Nel peggiore dei casi, può bloccare l’esecuzione dello script, in situazioni in cui document.write non è supportato. Se per esempio un documento è servito sia come text/html che come application/xhtml+xml, sarà necessario codificare uno script parallelo che non usi document.write, non permesso quando un documento viene servito con il secondo MIME type (sulle differenze tra HTML e XHTML, si veda il Capitolo 16).

L’inclusione in un documento di codice JavaScript che genera codice HTML tramite document.write porta, poi, con sé un altro rischio: quello di ricreare da un’altra fonte la mescolanza tra contenuti, struttura e presentazione, che uno sviluppo conforme agli standard dovrebbe tendere a eliminare (sulla separazione tra struttura e presentazione si veda il commento al punto di controllo 3.3 delle WCAG 1.0, nel Capitolo 6).

Tra i potenziali problemi collegati all’uso di script DHTML, merita di essere ricordata anche la confusione tra ciò che appartiene a JavaScript, cioè influire sui comportamenti del browser, e ciò che appartiene ai CSS, cioè determinare gli stili di presentazione del documento. È tipico, infatti, di una gran quantità di script modificare direttamente gli stili, come mostra l’esempio nel Listato 11.5.

Listato 11.5 Script che modifica direttamente gli stili del documento.

if (document.cookie.indexOf("artistat") == -1) {

supstat.style.background='transparent';

supstat.style.margin='0 0 5px 0';

padstat.style.border='none';

padstat.style.textAlign='right';

apstat.style.color='#000';

apstat.style.textDecoration='none';

apstat.style.borderBottom='2px solid #00f';

apstat.style.cursor='pointer';

accessori.style.backgroundImage='url(img/esempio.gif)';

accessori.style.backgroundPosition='0 75px';

accessori.style.backgroundRepeat='no-repeat';

}

In questo caso il problema è soprattutto di manutenzione del codice più che di accessibilità in senso stretto. Se a uno stesso sito lavorano, come è normale che sia, più sviluppatori in momenti e situazioni diverse, sarà più difficile - dovendo modificare gli stili del documento - identificare cosa va modificato e dove. È lecito, infatti, attendersi di trovare solo nei CSS le istruzioni che definiscono gli stili.

[Inizio approfondimento] Non sempre è possibile separare stili e comportamenti

Il problema per la verità non è sempre evitabile, perché vi sono casi, come quelli delle interfacce modificabili con il drag & drop, in cui la posizione di un elemento viene modificata in tempo reale per mezzo degli attributi di stile, a seconda degli spostamenti del puntatore: uno script è l’unico modo per governare dinamicamente tali relazioni. In molte altre situazioni, però, è possibile tenere separati stili e comportamenti, usando come riferimenti comuni per script e CSS nomi di classe e id. Ne riparleremo nel paragrafo successivo. [Fine approfondimento]

Abbiamo elencato finora problemi derivanti da come è scritto il codice JavaScript. Ma c’è qualcosa di più determinante, dal punto di vista dell’accessibilità, nelle soluzioni che vanno sotto il nome generico di DHTML: è il tipo di interazione che richiedono all’utente per accedere ai contenuti.

Poniamo, per esempio, che l’interfaccia utente di un CMS consenta di spostare dei file archiviati sul server da una cartella a un’altra cartella, o di eliminarli, solo per mezzo di un’azione di drag & drop gestita da una serie di script: sarebbe una soluzione inaccessibile per chiunque sia nell’impossibilità di usare il mouse, o di usarlo eseguendo un movimento continuo mentre un tasto rimane premuto.

Un altro caso tipico di uso potenzialmente inaccessibile di JavaScript è la generazione di finestre pop-up. L’accessibilità qui entra in gioco non solo a causa del vincolo che permette l’accesso ai contenuti solo a chi ha JavaScript attivo, ma anche a causa di ulteriori vincoli, sulla dimensione e la ridimensionabilità della finestra pop-up, posti dallo sviluppatore.

I comandi che possono essere utilizzati per creare simili vincoli sono mostrati nel Listato 11.1. Esaminiamoli: le variabili width e height impostano la larghezza della finestra generata rispettivamente a 350 e a 250 pixel; il valore 600 per le variabili left e top indica che l’angolo superiore sinistro della finestra generata sarà a 600 pixel di distanza, in orizzontale e in verticale, dall’angolo superiore sinistro dell’area utile del monitor (ciò vuol dire che la finestra resterà ben visibile su un monitor ad alta risoluzione, ma sarà del tutto fuori schermo alla risoluzione di 800×600); il valore no per le variabili toolbar, location, status, menubar, scrollbars e resizable indica che resteranno nascosti tutti gli elementi d’interfaccia del browser, e cioè, nell’ordine, la barra dei pulsanti, la casella per digitare gli indirizzi dei siti, la barra di stato, la barra dei menu, le barre di scorrimento. Da ultimo, la finestra non sarà ridimensionabile manualmente (Figura 11.2).

Figura 11.2. La finestra pop-up di 350×250 pixel, priva di qualsiasi strumento d’interfaccia del browser, generata dal codice nel Listato 11.1.

L’esempio presentato nel Listato 11.1 è un caso limite, fatto per evidenziare gli aspetti negativi del metodo, ma non è difficile capire che un simile blocco delle funzioni del browser rischia di essere deleterio per tutti gli utenti che hanno esigenze particolari e usano impostazioni dello schermo non considerate dallo sviluppatore, a cominciare dai caratteri ingranditi.

Altre forme d’interazione non accessibili, tipiche di soluzioni DHTML, sono i controlli di modulo che aprono finestre con messaggi di errore mentre l’utente sta ancora cercando di completare la compilazione dei campi. Per un normovedente si tratta solo di una piccola seccatura, ma per un non vedente può essere una grande seccatura, perché deve capire in quale punto esatto la sua digitazione è stata interrotta dall’apparire della finestra d’avviso per poter ripristinare la posizione esatta del cursore all’interno del testo che stava scrivendo o modificando (ulteriori digitazioni potrebbero aver infatti spostato il cursore dalla sua posizione originaria).

Molte ancora sono le soluzioni di poca o nulla accessibilità che sono state prodotte negli anni con DHTML e che sono tuttora usate in molti siti: dai menu dinamici i cui sottolivelli sono attivabili solo col mouse ai campi di selezione che generano direttamente l’inoltro del modulo a cui appartengono, senza che vi sia un pulsante di invio da usare come alternativa a JavaScript.

Da non dimenticare, per la loro a volte totale inaccessibilità, sono le complesse applicazioni JavaScript che simulano le funzioni di un programma di videoscrittura, con pulsanti di formattazione e stili, usate in molti CMS come sostituti della spartana finestra di testo prodotta dall’elemento textarea di un comune modulo HTML.

Inizio pagina

JavaScript non invasivo (unobtrusive JavaScript)

L’espressione unobtrusive JavaScript, come sintesi di una serie di buone pratiche di sviluppo, ha cominciato a diffondersi solo nel 2005, ma può considerarsi già oggi uno sorta di standard di fatto, adottato da sviluppatori professionisti che fanno del rispetto delle Raccomandazioni W3C e delle regole di accessibilità il fondamento del proprio lavoro.

Il passaggio da DHTML a JavaScript non invasivo è più che una moda passeggera. È piuttosto una necessità. La recente, notevole diffusione della banda larga, almeno nei paesi a più alto tenore di vita, ha provocato una rapidissima proliferazione di siti web dinamici e interattivi, il cui motore è costituito da complesse applicazioni, come quelle basate sull’insieme di tecnologie chiamato AJAX, le cui funzionalità riposano per larga parte sull’uso di JavaScript.

Insomma, non è più il tempo di usare JavaScript per creare effetti appariscenti ma tutto sommato inutili, come la scia di stelline dietro il puntatore del mouse. Oggi JavaScript è una cosa seria: è il motore dell’interattività dei migliori siti contemporanei e, come tale, deve garantire funzionalità accessibili a una larga massa di utenti, che comprende non solo l’immancabile ragazzino smanettone, ma anche adulti, anziani, persone di ogni livello di abilità fisica e competenza informatica.

Quello che, pur senza sapere ancora precisamente cosa sia, viene da qualche tempo chiamato Web 2.0 è un Web fatto di siti altamente dinamici e interattivi, funzionali, intuitivi, robusti. Perché tali siti possano funzionare in modo ottimale, il JavaScript che essi utilizzano deve essere qualcosa di ben diverso da quella serie sterminata di script eterogenei e inaffidabili, che costituiscono il mondo di DHTML. Deve essere un JavaScript scientifico, solido, perfettamente organizzato, in grado di integrarsi armoniosamente con i livelli sottostanti del contenuto, della struttura e della presentazione, affidati ai linguaggi di marcatura e ai fogli di stile.

Christian Heilmann, uno dei principali teorizzatori del JavaScript non invasivo, scrive a pag. 292 del già citato Web Accessibility: Web Standards and Regulatory Compliance collegamento esterno:

... progettare con l’accessibilità in mente significa che non diamo per scontato che i visitatori abbiano lo scripting attivo. Essi potrebbero essere legati a vecchie tecnologie che non hanno supporto per gli script e potrebbero non essere in condizione di aggiornarle. O potrebbe essere la politica della loro società a non consentire gli script per ragioni di sicurezza. Ciò vuol dire che non dobbiamo fare affidamento su JavaScript, ma che dobbiamo usarlo, invece, per migliorare l’esperienza quando e se JavaScript è attivo. Il termine comune per questo è unobtrusive JavaScript: JavaScript che aiuta, invece di bloccare la strada ai visitatori.

Come si riconosce un “Javascript che aiuta” da uno che danneggia? Dall’applicazione di una serie di principi di sviluppo, che sono l’esatto opposto dei criteri solitamente usati nella realizzazione di documenti DHTML.

Il primo e fondamentale principio è l’utilizzo di script al solo scopo di potenziare l’usabilità e l’interattività di un’applicazione web, senza che in alcun modo l’accesso alle funzionalità di base sia reso dipendente da JavaScript. Un’applicazione - per esempio un CMS - deve essere cioè completamente autosufficiente e utilizzabile, anche se l’utente usa un browser senza supporto per Javascript.

Un simile risultato si ottiene concependo l’attività di progettazione di un sito come un lavoro a strati, nel quale contenuti, struttura, presentazione e comportamenti formano una sorta di piramide, nella quale gli elementi superiori non possono esistere senza quelli inferiori, ma quelli inferiori sono invece autosufficienti: possono esistere e funzionare senza il livello o i livelli superiori (Figura 11.3).

Ciò ci porta al secondo principio, strettamente collegato al primo, che consiste nella totale separazione tra gli strati che compongono un documento.

Figura 11.3. La piramide che rappresenta la separazione dei livelli in un documento basato sulle regole di unobtrusive Javascript. I comportamenti arrivano fino al livello dei contenuti, agendo sui nodi del DOM, che è il filo di Arianna che lega insieme tutti i componenti del documento.

I contenuti sono la base della piramide: senza testi, immagini, suoni, animazioni, grafici ecc. un documento non esiste.

Su questa base, deve innestarsi un primo livello autosufficiente, quello della struttura. A esso corrisponde un documento scritto in un linguaggio di marcatura strutturale, che “imprigiona” i contenuti in una gabbia di marcatori adeguata a rappresentare il loro significato. Così come non si può mangiare un piatto di brodo con la forchetta, ma col cucchiaio sì, analogamente marcare dei contenuti con elementi strutturali sbagliati vuol dire renderli “immangiabili”; marcarli con gli elementi giusti li rende invece “digeribili”, nel senso di ben organizzati, coerenti e, in ultima analisi, chiaramente comprensibili. Marcare, per esempio, in HTML dei dati tabellari con un elemento P può far perdere al lettore le relazioni che esistono tra i dati; usare, invece, un elemento TABLE opportunamente strutturato consente di veicolare visivamente o acusticamente la reale struttura di quei dati, come una serie di relazioni tra righe e colonne.

Un documento fatto solo di contenuti e struttura è intrinsecamente accessibile e può essere utilizzato così com’è, sia pure privo di abbellimenti estetici e di funzionalità facilitatrici. Ne è un esempio il documento mostrato nel Listato 6.5 e nella Figura 6.7.

Lo strato successivo è quello della presentazione, che è di pertinenza dei fogli di stile CSS. Rimandiamo ancora una volta al commento al punto di controllo 3.3, nel Capitolo 6, per una dettagliata spiegazione di come applicare la presentazione, tramite i soli CSS, allo strato dei contenuti strutturati. Ciò che deve essere sottolineato in questa sede è che la presentazione realizzata con i fogli di stile non può esistere senza lo strato sottostante dei contenuti strutturati. Tolti dal codice di marcatura elementi e attributi di presentazione, gli stili CSS si applicano, infatti, con poche eccezioni, ai soli elementi strutturali, che costituiscono l’ossatura del codice di marcatura.

Ed eccoci all’ultimo strato, quello dei cosiddetti comportamenti (in inglese behavior). È lo strato di pertinenza del JavaScript non invasivo. C’è una profonda differenza tra questo nuovo paradigma e il vecchio DHTML. Mentre quello era basato sull’inserimento nel codice di marcatura di script e HTML generato, oltre che sulla manipolazione diretta degli stili, unobtrusive Javascript poggia invece sulla massima astrazione possibile dal codice di marcatura e dagli stili. Le trasformazioni dinamiche del documento vengono ottenute lavorando esclusivamente con il DOM definito dalle Specifiche W3C e intervenendo sugli stili indirettamente, per mezzo di modifiche dinamiche degli attributi class e id associati agli elementi; lasciando poi che gli stili siano definiti, così come deve essere, per mezzo dei CSS.

Un documento assemblato nel pieno rispetto di questo schema progettuale avrà un codice di marcatura sintetico e pulito, massimamente strutturale, a cui sono associati uno o più file CSS per gli stili e uno o più file JS per i comportamenti definiti con JavaScript.

L’applicazione dei primi due principi, cioè 1) l’uso di un JavaScript che potenzia ma non determina l’accesso ai contenuti e 2) la totale separazione del livello dei comportamenti da tutto il resto, richiede l’applicazione di una serie di altri principi di sviluppo, che sono del tutto compatibili con le richieste dell’accessibilità. Cominciamo con l’elencarli tutti insieme (alcuni sono già stati anticipati nelle righe precedenti); in seguito ne esamineremo le principali modalità di applicazione:

Il DOM è una rappresentazione ad albero, cioè gerarchica, del contenuto del codice di marcatura di un documento. È fatto di nodi, che corrispondono ai vari tipi di oggetti che può contenere, tra i quali: elementi, attributi, testo, commenti, e altro ancora. I nodi sono organizzati in parentele: vi sono genitori, figli e fratelli (non tutti i nodi, però, possono avere figli: testi e commenti, per esempio, non possono averne). La rappresentazione della struttura di nodi di un documento è il modello di riferimento per tutti i comportamenti generati da script che seguono le regole del JavaScript non invasivo.

Posto a base di ogni script l’uso del DOM, il passo successivo nella creazione di script non invasivi è fare attenzione a non generare errori evitabili nel browser dell’utente che ha JavaScript attivo. Questo scopo si raggiunge - lo abbiamo detto - testando preliminarmente il supporto del browser per gli oggetti e i metodi che si intendono utilizzare.

Il primo e più generale dei test da eseguire è quello che attesta la capacità del browser di manipolare il DOM in modo standard, cioè nel modo definito dalle Specifiche W3C collegamento esterno, disponibili online. Se il test fallisce, è inutile passare il resto dello script al browser: nel migliore dei casi si consuma tempo di elaborazione, nel peggiore si causano errori. Il metodo proposto da Christian Heilmann per eseguire questo test preliminare, con uscita dallo script in caso di mancato supporto, è mostrato nel Listato 11.6.

Listato 11.6 Metodo per testare la disponibilità di supporto standard per il DOM.

if(!document.getElementById || !document.createTextNode){return;}

// altro codice JavaScript

La condizione if verifica che il browser sia incapace di recuperare un elemento per mezzo del valore del suo attributo id (!document.getElementById) e/o che sia incapace di creare del contenuto testuale in un punto qualsiasi dell’albero del documento (!document.createTextNode). Se il browser è effettivamente incapace, viene eseguita l’istruzione return, che cessa semplicemente l’esecuzione dello script, senza consumare tempo di elaborazione e, soprattutto, senza generare errori. Se, invece, la condizione risulta falsa, cioè il browser possiede entrambe le capacità, allora vuol dire che è in grado di manipolare il DOM in modo standard. Passa a questo punto a esaminare le istruzioni successive dello script.

Vale la pena di sottolineare che il metodo nel Listato 11.6 ottiene lo stesso risultato del metodo nel Listato 11.2, cioè fornire a diversi browser solo il codice che ciascuno è in grado di eseguire, ma lo fa in un modo molto più pratico per lo sviluppatore e più al riparo da errori per l’utente. Lo script nel Listato 11.2 adatta il codice alle particolarità proprietarie dei singoli browser, moltiplicando il lavoro per lo sviluppatore; lo script nel Listato 11.6, invece, produce un unico codice, standard, e si assicura preliminarmente della capacità dei vari browser di eseguirlo. Tra i due metodi, il secondo è di gran lunga preferibile, soprattutto oggi che i principali browser grafici supportano in modo accettabile il DOM delle Specifiche W3C.

Una volta accertato che tale supporto è presente nel browser, si tratta di usare il DOM per ottenere le modifiche desiderate ai contenuti o alla struttura dell’albero del documento. I due metodi più utilizzati per agire sui nodi sono getElementById ('idElemento') e getElementsByTagName('nomeElemento'). Il primo restituisce l’elemento che ha idElemento come valore dell’attributo id, mentre il secondo crea una matrice, o array, che contiene tutti gli elementi che nel codice di marcatura si chiamano nomeElemento. Vi sono numerosi modi per raggiungere, partendo da un nodo, i suoi genitori figli e fratelli, ma la sintassi per creare trasformazioni nel DOM va al di là degli scopi di questa introduzione al JavaScript non invasivo. I due listati successivi mostrano solo un piccolo assaggio della potenza e della precisione delle manipolazioni possibili agendo sui nodi del DOM.

Listato 11.7 JavaScript non invasivo per l’apertura di una finestra pop-up.

// Script salvato nel file apri_popup.js

function apriPopup() {

if(!document.getElementById || !document.createTextNode){return;}

var scorrilink = document.getElementsByTagName("a");

var avvisa = " [nuova finestra]";

for (var i=0; i < scorrilink.length; i++) {

if (scorrilink[i].getAttribute("rel") == "popup") {

scorrilink[i].appendChild(document.createTextNode(avvisa));

scorrilink[i].onclick = function() {

window.open(this.href);

return false;

}

}

}

}

window.onload = apriPopup;

Listato 11.8 Il documento HTML che richiama il file apri_popup.js.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"

"http://www.w3.org/TR/html4/strict.dtd">

<html lang="it">

<head>

<meta http-equiv="content-type" content="text/html; charset=utf-8">

<title>Apertura di finestre pop-up con JavaScript</title>

<script type="text/javascript" src="apri_popup.js"></script>

</head>

<body>

<p>

Prima di dare la tua adesione, leggi le

<a href="note_legali.html" rel="popup">

<strong>note legali del contratto</strong></a> e prendi visione

delle nostre <a href="privacy.html" rel="popup">

<strong>regole sulla privacy</strong></a>.

</p>

<form action="..." method="post">

... I campi da riempire per sottoscrivere il contratto ...

</form>

</body>

</html>

Lo script nel Listato 11.7, che ha lo scopo di aprire dei collegamenti in una nuova finestra agendo sul codice di marcatura nel Listato 11.8, è un breve compendio di tutti i principi del JavaScript non invasivo.

Osserviamo, in primo luogo, la struttura dei due elementi A nel codice di marcatura: entrambi hanno un attributo href che collega comuni file HTML. Ciò vuol dire che, se l’utente usa un browser testuale o comunque privo di supporto per JavaScript, può aprire ugualmente i due documenti collegati, che saranno caricati nella finestra corrente e non in una nuova. In tal modo è rispettato il primo principio del JavaScript non invasivo, che è quello di non vincolare l’accesso ai contenuti alla possibilità di eseguire gli script (si confronti con il metodo DHTML, inaccessibile per chi ha gli script inattivi, usato nel Listato 11.1: href="javascript:window.open...").

Il secondo accorgimento è l’uso dell’attributo rel con valore popup, come riferimento per l’esecuzione dello script. Tale attributo serve per dichiarare un tipo di rapporto tra il documento corrente e un altro documento: è dunque semanticamente corretto adoperarlo come indicatore di una relazione con i documenti che si apriranno nella finestra pop-up.

Inoltre, il valore dell’attributo rel non è codice JavaScript: viene così rispettato un altro principio del JavaScript non invasivo, che è la totale separazione dei comportamenti dal resto del documento. Diverso sarebbe stato il caso, se avessimo inserito, come pure si poteva fare, l’attributo onclick nell’elemento A e l’attributo onload nell’elemento BODY. Quella sarebbe stata, secondo i puristi di unobtrusive JavaScript, una forma di confusione tra i livelli della struttura e dei comportamenti. Invece, i due eventi sono stati inseriti nel file esterno apri_popup.js, collegato al file HTML per mezzo dell’elemento SCRIPT posto nella sezione HEAD del documento.

Passiamo a esaminare la funzione apriPopup(), che determina l’apertura di nuove finestre.

La prima operazione che essa svolge è testare il supporto al DOM standard da parte del browser. Corrisponde al codice utilizzato nel Listato 11.6 e soddisfa il principio di seguire gli standard invece che le caratteristiche proprietarie dei singoli browser.

Successivamente, viene dichiarata la variabile scorrilink, il cui valore è una matrice contenente tutti gli elementi A presenti nel codice di marcatura (nel Listato 11.8 ve ne sono due), recuperati attraverso l’istruzione getElementsByTagName associata all’oggetto document. Si rispetta così il principio di selezionare per mezzo del DOM le parti del codice di marcatura su cui serve intervenire.

Viene poi dichiarata la variabile avvisa, il cui valore è la stringa [nuova finestra], preceduta da uno spazio vuoto. A questo punto comincia un ciclo for, che scorre tutti gli elementi A nella matrice scorrilink. All’interno del ciclo vengono svolte alcune operazioni.

La prima è controllare se il valore dell’attributo rel dell’elemento A corrente sia popup. In caso affermativo, viene eseguita su quell’elemento, sempre tramite DOM, l’istruzione appendChild(document.createTextNode(avvisa)), che aggiunge al testo del collegamento la stringa “[nuova finestra]”, memorizzata nella variabile avvisa. Ciò ha lo scopo di avvertire l’utente del fatto che quel collegamento si aprirà in una nuova finestra, così come richiede il punto di controllo 10.1 delle WCAG 1.0. Da notare che l’avviso sarà visualizzato - come è giusto che sia - solo da coloro che hanno JavaScript attivo (Figura 11.4).

Figura 11.4. In alto, il documento nel Listato 11.8 riprodotto in un browser con JavaScript attivo e, in basso, lo stesso documento riprodotto in un browser senza supporto per JavaScript. L’avviso “[nuova finestra]” è visibile solo nel primo caso.

La seconda operazione lega all’evento onclick l’apertura di una nuova finestra, generata con l’istruzione window.open. Il suo contenuto sarà il documento referenziato dal valore di href dell’elemento A corrente (this.href, cioè, detto in linguaggio umano, “il valore di href di questo elemento”). La successiva istruzione return false ha lo scopo di impedire che la pagina caricata nella nuova finestra sia caricata anche, contemporaneamente, nella finestra di partenza del browser.

Chiude lo script l’istruzione window.onload, che ha lo scopo di eseguire la funzione apriPopup() al caricamento del documento HTML.

Si noti che la nuova finestra, aperta in seguito all’esecuzione dello script, non ha nessuna delle limitazioni imposte dallo script DHTML nel Listato 11.1: tutti i componenti dell’interfaccia utente del browser restano visibili, non sono imposte alla finestra né una dimensione né una posizione prestabilite e, soprattutto, rimane liberamente ridimensionabile dall’utente.

Infine, l’uso dell’evento onclick senza un corrispettivo onkeypress potrebbe dare l’idea di un sistema dipendente dal dispositivo di input (il mouse), ma non è così in realtà: come è stato già spiegato nel Capitolo 9, i browser attuali consentono l’attivazione anche da tastiera degli script associati a onclick, il che rende sostanzialmente inutile pareggiare ogni evento onclick con un corrispondente evento onkeypress. Se, però, si desidera inserire anche onkeypress, occorrerà usare uno script per filtrare i tasti premuti dall’utente, in modo da evitare che lo script attivato dall’evento interferisca con la navigazione da tastiera: i Listati 9.4 e 11.11 offrono esempi di funzioni filtro.

[Inizio approfondimento] A proposito dell’apertura di finestre pop-up

A proposito dell’apertura di finestre pop-up, va ricordato che si tratta di una pratica fortemente sconsigliata dal punto di vista dell’accessibilità. Per un’analisi dei problemi di accessibilità legati all’apertura di finestre multiple, si veda il commento al punto di controllo 10.1, nel Capitolo 15. [Fine approfondimento]

Inizio pagina

Salta inserzione pubblicitaria

AJAX: cos’è e come funziona

Nel corso del 2005, con la velocità tipica delle cose che accadono sul Web, ha cominciato a diffondersi l’uso della sigla AJAX, in associazione con numerose e importanti applicazioni dinamiche e interattive (Google Gmail e Google Maps, per dirne due), rese possibili dall’uso combinato di una serie di tecnologie già note, tra le quali HTML, XHTML, CSS, XML, JavaScript, Java.

Così, quasi d’improvviso, AJAX non è stato più soltanto il nome di un detersivo e di un’importante squadra di calcio olandese, ma - come acronimo di Asynchronous JavaScript and XML - è diventata la parola d’ordine di legioni di sviluppatori, impegnati a realizzare piccole o grandi applicazioni interattive, chiamate a loro volta con una sigla, RIA, che sta per Rich Internet Applications.

Le applicazioni per il Web realizzate con AJAX sono “ricche” (rich), perché dispongono di funzionalità complesse e sono in grado di rispondere in modo più o meno immediato ai comandi degli utenti: ciò le rende per molti versi simili alle più comuni e antiche applicazioni cosiddette “desktop”. Mentre, però, le vere applicazioni desktop, come per esempio Word e PowerPoint di Microsoft, possono essere “ricche” e allo stesso tempo immediate nella risposta per il fatto di risiedere direttamente sul computer dell’utente, le Rich Internet Applications risiedono in parte sul computer client, cioè nelle pagine web caricate nel browser dell’utente, e in parte sul web server che le ospita, dove si trovano tipicamente i database e le procedure che elaborano i dati che saranno poi inviati ai client collegati.

Qual è, allora, il meccanismo che permette un’interazione così ricca tra l’utente e l’applicazione, nonostante la necessità d’interrogare di continuo un web server e aspettare le sue risposte, con i possibili ritardi che il traffico di rete normalmente produce? Il meccanismo è appunto AJAX, o meglio l’uso asincrono di JavaScript, a cui fanno riferimento le prime due lettere della sigla. Tutto si basa sull’azione, nascosta all’utente, di un oggetto JavaScript chiamato XMLHttpRequest. Tramite quest’oggetto, uno script lato client (eseguito cioè dal browser) può interrogare il server, richiedendo e ricevendo contenuti per mezzo del protocollo HTTP, lo stesso protocollo che usiamo normalmente per collegarci a una qualsiasi risorsa web, dopo averne digitato l’indirizzo nell’apposita barra del browser. JavaScript si occupa, poi, di organizzare secondo le esigenze dell’applicazione i dati ricevuti dal server e di renderli disponibili all’utente nell’interfaccia dello stesso documento già caricato.

La grande differenza rispetto a una normale interazione client-server determinata dalle azioni dell’utente è che il processo di scambio dati, che avviene grazie agli script che usano l’oggetto XMLHttpRequest, si svolge sullo sfondo, dietro le quinte, indipendentemente dalla volontà e dall’attenzione dell’utente, che può essere impegnato nel frattempo in una qualsiasi altra operazione (Figura 11.5). Chiunque abbia usato qualche volta il servizio di posta elettronica Google Gmail avrà notato che la verifica di nuovi messaggi in arrivo viene svolta periodicamente dall’applicazione, anche se l’utente non fa assolutamente nulla. I contenuti vengono così aggiornati sotto gli occhi dell’utente, ma è solo la parte dell’interfaccia interessata dall’aggiornamento che risulta modificata. Tutto il resto del documento rimane uguale e immutato. Non viene, cioè, ricaricata l’intera pagina.

Figura 11.5. La relazione tra client e server in un processo tradizionale di aggiornamento dei contenuti, a confronto con la relazione tra client e server quando l’aggiornamento dei contenuti è governato da AJAX.

Si tratta di una differenza sostanziale rispetto al modo tradizionale d’interagire con un sito web. In un sito non-AJAX, la navigazione procede caricando in successione documenti differenti, e ogni scambio di dati tra client e server avviene per diretta richiesta dell’utente (tranne che nei casi - deprecati - di reindirizzamento automatico). In un sito AJAX, invece, l’interazione avviene soprattutto all’interno di un’interfaccia utente fatta di blocchi aggiornabili dinamicamente, così come lo sono i contenuti delle classiche applicazioni desktop. L’utente, naturalmente, può dettare i tempi dell’aggiornamento dei contenuti anche in un’applicazione AJAX (in Google Gmail, per esempio, può usare il link “Aggiorna” per verificare all’istante se vi sono nuovi messaggi di posta), ma lo scambio dati tra client e server avviene anche in modi e tempi che l’utente non governa direttamente.

Questa particolarità pone sviluppatori e tecnologie assistive nell’obbligo di risolvere un grande problema di accessibilità, che rischia di rendere le applicazioni AJAX poco fruibili dagli utenti di screen reader. Questi ultimi, infatti, non avendo la possibilità di esplorare l’interfaccia visivamente, sono nella condizione di non poter sapere direttamente se e dove il documento che stanno leggendo sia stato modificato tramite l’uso asincrono di JavaScript (Figura 11.6).

Non è un problema di poco conto. Se un utente di screen reader vuole sapere se è cambiata dinamicamente anche una sola parola, a meno che non venga avvertito da qualche meccanismo apposito, è costretto a rileggere tutto il documento dall’inizio, il che non rende di per sé inaccessibile un’applicazione AJAX non progettata per l’accessibilità, ma la rende piuttosto scomoda, se non scomodissima, per utilizzi non visuali.

Figura 11.6. In un’interazione classica tra client e server, l’utente decide se e quando ricevere dal server contenuti aggiornati; in una relazione client-server governata da AJAX, l’aggiornamento avviene indipendentemente dalla volontà e dall’attenzione dell’utente.

Inizio pagina

AJAX, scalabilità e potenziamento progressivo

Prima di approfondire la questione e di esaminare le possibili soluzioni, occorre considerare però un altro aspetto di grande importanza per l’accessibilità, e che sta più a monte del rapporto tra AJAX e screen reader: il fatto, cioè, che le applicazioni AJAX sono inevitabilmente dipendenti dal dispositivo, una caratteristica molto penalizzante dal punto di vista dell’accessibilità. AJAX, infatti, non esiste senza JavaScript (o senza un’altra tecnologia in grado di dialogare dietro le quinte con un web server). Un browser troppo datato o senza supporto attivo per JavaScript non può eseguire i processi client-server resi possibili dall’oggetto XMLHttpRequest né i conseguenti aggiornamenti dinamici dell’interfaccia utente.

Il primo requisito per l’accessibilità di un’applicazione AJAX deve essere dunque la scalabilità, che corrisponde in questo caso alla disponibilità di un’alternativa non-AJAX, che consenta all’utente di utilizzare le principali funzionalità e contenuti dell’applicazione, qualsiasi sia il browser adoperato e il tipo di supporto per JavaScript. È degno di nota, a tal proposito, che, Google Maps collegamento esterno abbia reso disponibile una modalità d’interazione client-server di tipo tradizionale, in alternativa alla consultazione interattiva basata su AJAX. Tramite l’alternativa statica, è possibile consultare ugualmente informazioni stradali e cartine, anche se si utilizza un browser senza supporto per l’oggetto XMLHttpRequest (Figura 11.7).

Figura 11.7. Usando un browser che non supporta AJAX, è possibile ugualmente interrogare Google Maps, usando una modalità d’interazione classica tra client e server (24/2/2007).

Anche il servizio Gmail prevede la possibilità di utilizzo in assenza di JavaScript, in una modalità con interazione client-server tradizionale, che viene definita “HTML di base” e che è molto più spartana della modalità dinamica.

I servizi di Google, con i loro milioni di utenti, non potevano fare a meno di applicare il principio della scalabilità. È però indispensabile per l’accessibilità che anche chi dispone di mezzi ben più limitati, se decide di realizzare applicazioni AJAX, abbia cura di fornire alternative a vantaggio degli utenti “non dinamici”.

Va aggiunto, tuttavia, che progettare di rendere scalabile un’applicazione AJAX fa sorgere un importante problema di metodo. Per ottenere, infatti, l’equivalente non dinamico di un’applicazione dinamica, esistono due strade esattamente opposte.

La prima è basata su un approccio che va dal complesso al semplice e che corrisponde a un modo ormai sorpassato di concepire l’accessibilità: si crea prima l’applicazione complessa, dinamica, basata su AJAX, progettata senza l’accessibilità in mente, e poi si ragiona su come realizzare un’applicazione gemella in tono minore, un po’ la sorella “sfigata” dell’altra, che faccia più o meno le stesse cose, ma senza usare JavaScript né interazioni dinamiche. Alla fine, il lavoro da fare sarà doppio: occorrerà, infatti, progettare due diverse applicazioni, una dinamica e una statica, di cui la seconda rischia di riuscire del tutto insoddisfacente per l’utente, come è di solito il destino delle copie economiche rispetto agli originali.

La seconda strada è quella del progressive enhancement, il potenziamento progressivo. Il concetto è lo stesso già visto per la separazione del livello della presentazione da quello dei contenuti strutturati e per la separazione del livello dei comportamenti dai due precedenti. Si tratta di progettare un’unica applicazione, di tipo piramidale (si veda il disegno in Figura 11.3), fatta in modo tale che i contenuti strutturati, cioè il livello del codice di marcatura, permetta già, indipendentemente dai due livelli successivi, un utilizzo completo delle funzionalità dell’applicazione che richiedono interazioni client-server: il risultato si raggiunge, tipicamente, per mezzo di collegamenti ipertestuali e moduli, che fanno il loro lavoro anche in browser privi di supporto per JavaScript.

Successivamente, si aggiunge il livello dei comportamenti, impostando le varie interazioni dinamiche basate su AJAX. L’aggiunta di AJAX viene fatta “dirottando” le azioni eseguite da collegamenti e moduli, per mezzo di script realizzati seguendo il modello di unobtrusive JavaScript: cioè tutto il codice dinamico in file esterni e uso del DOM standard.

Il risultato del “dirottamento” delle interazioni tradizionali da parte di AJAX sarà la possibilità di caricare nell’interfaccia utente solo gli elementi modificati e non l’intero documento. Ciò significa che l’applicazione deve essere progettata fin dall’inizio per essere modulare. Ogni blocco di contenuto soggetto a interazioni client-server deve, infatti, poter essere trattato dal server come un’entità separata. Sarà così possibile usare l’oggetto XMLHttpRequest per ottenere solo i dati strettamente necessari ad aggiornare dinamicamente un singolo blocco di contenuto.

In sostanza, l’approccio proposto da Jeremy Keith (si veda il box su HIJAX) può funzionare, solo se si progetta fin dall’inizio l’architettura lato server dell’applicazione in modo che sia in grado di gestire modularmente i contenuti dell’interfaccia. Ciò può avvenire, per esempio, separando le funzionalità del menu di navigazione da quelle che gestiscono l’accesso degli utenti registrati; quelle del catalogo prodotti da quelle della procedura d’acquisto, e così via. Come spiega lo stesso Keith, ci si trova a questo punto davanti a una sorta di paradosso, che però è solo apparente:

Da un lato, vi sto suggerendo che, se volete creare un’applicazione AJAX, dovreste cominciare realizzando un’applicazione non-AJAX. Dall’altro lato, vi sto suggerendo che, se volete creare un’applicazione AJAX che funzioni, dovete pensare alla vostra architettura lato server fin dall’inizio. Questo paradosso può essere risolto così: progettate per AJAX fin dal principio… implementate AJAX solo alla fine.

Sono possibili, in conclusione, due tipi di approccio alla scalabilità (o, per dirla all’inglese, alla graceful degradation): uno che parte da un’applicazione AJAX esistente e, agendo per sottrazione ed emulazione di funzioni, tenta di giungere a una copia statica dell’originale dinamico; e uno, opposto, basato sul concetto di potenziamento progressivo di un’interfaccia utente statica, già dotata in partenza di tutte le funzionalità necessarie. Tra i due approcci, il secondo è senza ombra di dubbio destinato a produrre i risultati migliori, sia dal punto di vista del beneficio per l’utente finale sia dal punto di vista del lavoro di sviluppo necessario.

[Inizio approfondimento] HIJAX

Jeremy Keith, il teorizzatore di quest’uso non invasivo di AJAX, lo ha definito HIJAX, una sigla che fonde AJAX con la radice del verbo inglese hijack, che significa appunto “dirottare”. Il metodo proposto da Jeremy Keith è spiegato in una sintetica ma chiarissima presentazione, intitolata Hijax: Progressive Enhancement with Ajax collegamento esterno. [Fine approfondimento]

[Inizio approfondimento] I vantaggi del potenziamento progressivo

Il metodo del progressive enhancement non riguarda solo le applicazioni AJAX, ma l’intero mondo dello sviluppo Web. Non è più possibile, oggi, pensare all’accessibilità come a una sorta di bonifica fatta a posteriori su applicazioni e siti già realizzati con criteri non accessibili. L’accessibilità va non solo pianificata fin dall’inizio, ma dipende in larga misura dal metodo di progettazione seguito.

Lo sviluppo per livelli, che parte dai contenuti e arriva ai comportamenti, eseguito in modo che i livelli superiori non condizionino l’accesso a quelli inferiori, rappresenta una rivoluzione ecologica nel modo di concepire il processo di realizzazione di un sito web. È un metodo di progettazione che produce risultati utili non solo per l’accessibilità in senso stretto, ma anche per la razionalità generale del prodotto web, che, costruito per livelli separati e nel rispetto degli standard, può godere di una vera modularità, che, a sua volta, favorisce gli interventi di manutenzione e di modifica. [Fine approfondimento]

Inizio pagina

AJAX e gli screen reader. La memoria virtuale

Torniamo ora alla questione accennata in precedenza: la difficoltà, per un utente di screen reader, di capire se qualcosa è cambiato dinamicamente nella pagina, e dove. Si tratta di due problemi distinti.

Partiamo dal primo, e cioè la difficoltà di capire se c’è stato un aggiornamento dinamico dei contenuti. Per comprendere come si manifesti precisamente il problema, dobbiamo però innanzitutto capire come funziona uno screen reader. A tal proposito, ci sembra illuminante l’introduzione fatta da Gez Lemon e Steve Faulkner, due tra i maggiori esperti di accessibilità, nel loro articolo Making AJAX Work with Screen Readers collegamento esterno, che riportiamo in traduzione italiana:

Per consentire agli utenti di screen reader di leggere i contenuti web e interagire con essi, gli screen reader catturano un’istantanea della pagina web e piazzano questo contenuto in una memoria virtuale [virtual buffer]. Lo screen reader usa la memoria virtuale per permettere all’utente di navigare il contenuto. Senza la memoria virtuale, lo screen reader ha accesso soltanto alle parti della pagina che possono ricevere il focus da programmi utente non assistivi, cioè ancore ed elementi d’interfaccia. Senza la memoria virtuale, l’utente non può interagire con altri elementi presenti nel contenuto e con i loro nodi figli, quali immagini, elenchi, tabelle, e così via. Ogni screen reader usa un nome specifico per la memoria virtuale, per esempio Virtual Focus mode in Supernova, ma fanno tutti essenzialmente lo stesso lavoro.

Nei due screen reader più diffusi, cioè JAWS e Window-Eyes, le aree di memoria virtuale, che contengono l’istantanea dello stato della pagina caricata, si chiamano rispettivamente Virtual PC Cursor mode e Browse Mode.

Quando JAWS è in Virtual PC Cursor mode, stato che può essere attivato e disattivato tramite la combinazione di tasti Insert + Z, registra nella memoria virtuale i cambiamenti dinamici generati da eventi classici, come onclick e onkeypress. Tali eventi però non sono direttamente collegati ai contenuti generati per mezzo di AJAX. Questi, invece, dipendono in genere da un altro evento, che è collegato all’oggetto XMLHttpRequest: l’evento onreadystatechange.

Con l’ultima versione di JAWS, la 8.0, è stato introdotto il supporto all’evento onreadystatechange anche con Internet Explorer (prima era già presente con Firefox). Tuttavia, una risposta diretta a questo evento si ha solo quando lo screen reader si trova in modalità non virtuale.

Il problema è che le modifiche dinamiche dell’interfaccia che avvengono quando JAWS si trova nella modalità non virtuale possono essere notificate all’utente solo se coinvolgono elementi che possono ricevere il focus, cioè ancore, link, aree sensibili di una mappa, elementi di modulo. Certo, è già qualcosa, ma non è la soluzione. Capita spesso, infatti, che i contenuti generati da AJAX non abbiano nulla a che fare con gli elementi che possono ricevere il focus in base alle specifiche HTML 4 e XHTML 1 (in XHTML 2, invece, tutti gli elementi potranno ricevere il focus). Se il contenuto generato è, per esempio, posto in un paragrafo, allora l’utente non ne saprà nulla, perché P non può ricevere il focus.

Per farla breve, se il contenuto generato da AJAX può ricevere il focus e uno script glielo passa, e JAWS si trova in PC Cursor mode, all’utente viene letto correttamente il nuovo contenuto. In tutti gli altri casi, l’utente non può sapere se nella pagina vi sono stati aggiornamenti dinamici. L’unica cosa che può fare è obbligare lo screen reader ad aggiornare la memoria virtuale agli ultimi cambiamenti, accendendo e spegnendo il Virtual PC Cursor mode o usando, in JAWS, la combinazione Insert + Esc. Poi gli toccherà rileggere l’intero documento, alla ricerca di ciò che è cambiato. Un metodo davvero poco pratico, che oltretutto priva l’applicazione AJAX della sua dinamica in tempo reale, perché i nuovi contenuti vengono letti non quando sono generati, ma quando l’utente si ricorda o ha voglia di controllare.

Del resto, anche quando il contenuto generato viene letto direttamente, perché ha il focus e l’utente si trova nella modalità non virtuale, possono sorgere problemi di comprensione per chi usa uno screen reader. Se, per esempio, viene dato dinamicamente il focus a una cella di una tabella che si trova all’interno di un elemento FORM, lo screen reader, se si trova in modalità non virtuale, legge correttamente il contenuto della cella modificato da AJAX, ma l’utente non può rendersi conto delle relazioni che quella cella ha con le altre finché non decide di passare alla modalità virtuale: solo allora, infatti, potrà ottenere la lettura delle intestazioni della tabella e capire, dunque, a cosa si riferiva l’aggiornamento dinamico appena letto.

[Inizio approfondimento] Articoli e ricerche in Rete su AJAX e accessibilità

Prima di entrare nel vivo delle soluzioni per rendere AJAX direttamente accessibile, segnaliamo ai lettori alcune risorse per approfondire. I contributi forse più importanti, in termini di documentazione dei problemi di accessibilità legati ad AJAX e di ricerca di soluzioni, sono stati forniti da Gez Lemon, in alcuni articoli pubblicati sul sito Juicy Studio collegamento esterno. Ai lettori interessati suggeriamo di leggerne tre in particolare, di cui i primi due scritti in collaborazione con Steve Faulkner: 1) Making AJAX Work with Screen Readers, 2) Improving AJAX Applications for Jaws Users (tradotto in italiano da Roberto Castaldo all’indirizzo http://www.webaccessibile.org/argomenti/argomento.asp?cat=634 collegamento esterno) e 3) WAI-ARIA Live Regions. Consigliamo poi la lettura di AJAX and Screenreaders: when can it Work? collegamento esterno, una ricerca di James Edwards pubblicata su Sitepoint. Sempre in tema di ricerche su AJAX, da segnalare Build half a Product: is AJAX accessible? At all? collegamento esterno di Joe Clark, in cui è presentata una tabella comparativa con i risultati di un test, nel corso del quale è stato chiesto a numerosi utenti di screen reader di eseguire una serie di operazioni basilari usando un’applicazione AJAX non progettata per l’accessibilità. Le spiegazioni presentate nei paragrafi successivi devono molto agli articoli e alle ricerche qui ricordati. [Fine approfondimento]

Inizio pagina

Avvertire l’utente che il contenuto è cambiato dinamicamente

Tirando le somme di tutto ciò che abbiamo detto fin qui, possiamo concludere che l’accessibilità di AJAX può essere migliorata sensibilmente in due modi:

  1. avvertendo l’utente di aggiornare la memoria virtuale dello screen reader ogni volta che sia necessario;
  2. facendo in modo che lo screen reader possa leggere direttamente i contenuti modificati, anche quando questi riguardano elementi che non possono ricevere il focus in base alle specifiche HTML 4 e XHTML 1.

Per quanto riguarda il primo punto, generare avvertimenti per consigliare all’utente di aggiornare la memoria virtuale (o di passare a essa) non è tra le operazioni più semplici. Il testo dell’avviso, per esempio, va progettato con molta attenzione. Non solo, infatti, ogni screen reader definisce a modo suo la modalità di memoria virtuale, ma non è affatto detto che un utente non informatico sappia cosa sia tale modalità, dal momento che si tratta di una nozione piuttosto tecnica. C’è il rischio, insomma, che l’avviso crei più confusione che utilità.

Comunque sia, il modo forse più sicuro di procedere è quello di creare una pagina di aiuto chiaramente collegata all’applicazione AJAX, nella quale si spiega, con le parole più semplici, cos’è la modalità virtuale e come attivarla nei principali screen reader.

Gez Lemon e Steve Faulkner propongono anche un’altra soluzione, molto ingegnosa, ma valida solo per i contenuti dinamici generati all’interno di un elemento FORM.

Si tratta di generare dinamicamente, tramite DOM, un attributo title contenente l’avviso di passare alla modalità virtuale. Infatti, gli screen reader leggono sempre - qualsiasi sia il livello di verbosità impostato - il contenuto di title, quando l’elemento che lo contiene si trova all’interno di un modulo e non sia associato esplicitamente con un’etichetta. L’attributo title va generato per l’elemento i cui contenuti sono modificati da AJAX e può essere poi rimosso, una volta che l’elemento abbia perduto il focus. Volendo, per esempio, aggiungere un title all’elemento TD di una tabella (modificata dinamicamente all’interno di un modulo), si potrebbe usare un codice come quello del Listato 11.9.

Listato 11.9 Generazione e rimozione mediante DOM di un attributo title.

// crea una cella di tabella

var oggDinamico = document.createElement('td');

// crea l'attributo title nel TD, aggiungendovi l'avviso per l'utente

oggDinamico.setAttribute('title', 'Passa alla memoria virtuale');

// elimina l'attributo, una volta che la cella perde il focus

oggDinamico.onblur = function(){this.removeAttribute('title');};

Inizio pagina

Uso di tabindex per ottenere la lettura dei contenuti modificati

Avvisare l’utente di dover passare alla modalità virtuale è solo una parte del problema. L’altra parte, come abbiamo accennato più sopra, è fare in modo che lo screen reader legga i contenuti modificati da AJAX.

Per avviare a una soluzione standardizzata questo e altri problemi di accessibilità delle applicazioni dinamiche, il W3C ha pubblicato la bozza, aggiornata al 5 aprile 2006, di un documento intitolato Dynamic Accessible Web Content Roadmap collegamento esterno, cioè “Tabella di marcia per i contenuti web dinamici accessibili”.

Il paragrafo 4.1.3 di questo documento del W3C definisce un utilizzo particolare dell’attributo tabindex: quello di impostare il suo valore a -1. Lo scopo è di disporre in tal modo di uno strumento convenzionale, per segnalare ai browser conformi di non inserire l’elemento con tale valore di tabindex all’interno dell’ordine di tabulazione del documento, permettendogli però di ricevere allo stesso tempo il focus tramite il metodo JavaScript focus.

Il funzionamento e l’uso accessibile dell’attributo tabindex saranno spiegati in dettaglio nel commento al punto di controllo 9.4 delle WCAG 1.0, nel Capitolo 14 di questo libro. Per ora, basti sapere che escludere gli elementi con tabindex="-1" dall’ordine di tabulazione è un modo per non confondere gli utenti che usano pressioni successive del tasto Tab per scorrere gli elementi attivi della pagina (link e campi modulo).

Al momento, Internet Explorer e Firefox supportano già l’uso di tabindex="-1". Altri browser no, e questo impedisce per ora di avere un comportamento accessibile uniforme nel trattamento delle applicazioni dinamiche. Ecco, comunque, cosa succede, quando uno screen reader è usato in coppia con un browser che supporta il meccanismo (la descrizione è di Gez Lemon e Steve Faulkner):

Quando il focus viene passato a un elemento che ha un valore negativo di tabindex e che normalmente non potrebbe ricevere il focus, come un elemento paragrafo, il comportamento cambia a seconda della modalità: in modalità memoria virtuale, lo screen reader focalizza l’elemento, ma non ne annuncia automaticamente il contenuto; se la modalità virtuale è spenta, lo screen reader annuncia il contenuto dell’elemento. In modalità virtuale, l’utente deve richiedere allo screen reader di leggere la riga corrente dopo che un elemento ha ricevuto il focus (Insert + Freccia giù in JAWS e Freccia giù in Window-Eyes e Supernova). Se il focus è passato a un’ancora in modalità virtuale, allora il contenuto dell’ancora viene annunciato automaticamente.

Insomma, inserendo tabindex="-1" sugli elementi modificati dinamicamente, e avendo cura di creare script che passino il focus a tali elementi dopo averli modificati, gli sviluppatori hanno la possibilità di far leggere a JAWS e Window-Eyes tutto il contenuto modificato tramite AJAX. Purtroppo l’accorgimento non ha alcun effetto con Home Page Reader, il browser vocale di IBM, perché questa tecnologia assistiva non supporta il metodo JavaScript focus.

Va sottolineato, infine, che l’uso dell’attributo tabindex con valori negativi e/o in associazione con elementi per i quali non è previsto dalle Specifiche HTML e XHTML, produrrà inevitabili errori di validazione del codice di marcatura. Da segnalare, però, che la DTD di XHTML 1.1 è stata estesa in modo da rendere legale l’uso dell’attributo tabindex anche in associazione agli elementi DIV, SPAN, P, TH, TD e LI. L’estensione della DTD è all’indirizzo http://www.w3.org/TR/aria-state/#xhtml_elements_dtd collegamento esterno.

Inizio pagina

ARIA, Accessible Rich Internet Applications

È chiaro che l’accessibilità di AJAX, un sistema dinamico sempre più spesso utilizzato in una moltitudine di siti di nuova concezione, non può rimanere affidata a pezze poco convincenti come l’uso di tabindex="-1". Ci vuole qualcosa di più organizzato e potente, uno standard vero e proprio, che definisca e uniformi caratteristiche e comportamenti delle applicazioni dinamiche, affinché possano essere intrinsecamente accessibili.

Il W3C ha in effetti recepito con sollecitudine la tendenza in atto da un paio d’anni sul Web e ha prodotto due bozze di raccomandazione, che contengono un impianto molto articolato, che, una volta assimilato dai produttori di browser e tecnologie assistive, potrebbe risolvere completamente i problemi di accessibilità legati all’uso di AJAX. I due documenti sono:

A queste due bozze di raccomandazione, si aggiunge un documento che elenca i problemi di accessibilità delle applicazioni dinamiche attualmente irrisolti e definisce i passi necessari per giungere a soluzioni standardizzate; fornisce inoltre un percorso temporale con le scadenze previste per la pubblicazione delle specifiche, tra cui le due precedenti, in cui saranno fornite le soluzioni. Il titolo di questo terzo documento è Roadmap for Accessible Rich Internet Applications (cioè “Tabella di marcia per applicazioni Internet ricche accessibili”), in breve WAI-ARIA Roadmap collegamento esterno. La bozza più recente è datata 20 dicembre 2006.

Per capire il senso delle soluzioni proposte dai documenti W3C appena ricordati, bisogna prima capire il tipo di problemi che esse devono affrontare e risolvere. Dal punto di vista dell’utente di tecnologie assistive, la questione principale è - l’abbiamo detto più volte - essere informati dei cambiamenti dinamici che avvengono nell’interfaccia dell’applicazione caricata nel browser.

A ciò va aggiunto che è molto importante anche il modo in cui si viene informati. Se, per esempio, l’utente sta scrivendo un’e-mail in un’applicazione AJAX, potrebbe essere un guaio peggiore del beneficio, se lo screen reader decidesse di propria iniziativa di dirottare il focus - mentre l’utente è ancora impegnato a digitare - verso il pannello dei messaggi in arrivo, per notificargli che in quel preciso istante è arrivata della nuova posta.

Quel che serve, insomma, è un comportamento intelligente delle tecnologie assistive, che devono essere in grado, nel trattare i dati provenienti da un’applicazione dinamica, di fare scelte complesse, basate sulla semantica e sul livello di priorità dei contenuti aggiornati.

Attualmente, questo comportamento intelligente non è realizzabile se non in minima misura, perché gli strumenti per comunicare a una tecnologia assistiva il valore semantico di un oggetto modificato dinamicamente o non esistono o sono molto rudimentali. Pensiamo per esempio a un menu di navigazione in un documento HTML, inserito all’interno di un DIV e reso alternativamente visibile e invisibile tramite JavaScript. Il fatto che il blocco nel DIV sia un menu di navigazione e che sia in un certo momento visibile o invisibile sono informazioni semanticamente rilevanti, che dovrebbero poter essere comunicate all’utente.

Quali informazioni può ricavare oggi una tecnologia assistiva, sapendo soltanto che un certo contenuto si trova in un DIV? Nessuna purtroppo, perché DIV è un elemento generico, che può essere usato per marcare qualsiasi tipo di contenuto. E anche se il menu fosse marcato con UL o P, invece che con DIV, non cambierebbe nulla: cosa lo potrebbe distinguere semanticamente da un qualsiasi altro blocco di contenuto marcato con UL o con P? Certo, si potrebbero usare classi e id dai nomi appropriati. Ma occorre non dimenticare che questi attributi sono tra i principali agganci per i fogli di stile. Usandoli per definire in un modo standardizzato anche il valore semantico dei contenuti, si finirebbe per mischiare impropriamente i livelli della struttura e della presentazione: potremmo avere, per esempio, un elemento DIV con le classi menu e rosso, la prima usata per indicare alle tecnologie assistive il ruolo semantico del contenuto, la seconda per fornire un aggancio a uno stile che definisce il colore del blocco. Non sarebbe un sistema pulito.

Abbiamo bisogno, insomma, di un modo per standardizzare la funzione svolta da un oggetto all’interno di un’applicazione che sia privo di ambiguità, indipendente perciò da altri sistemi di notazione. Questo compito tocca alla prima delle due specifiche W3C in lavorazione, cioè WAI-ARIA Roles, che definisce in maniera comprensibile dalle tecnologie assistive che cos’è un oggetto, ovvero il ruolo che esso svolge all’interno di un’applicazione. Ma lasciamo che sia lo stesso documento W3C a chiarire il concetto:

(...) se un paragrafo è semanticamente identificato come tale, una tecnologia assistiva può interagire con esso come una unità separabile dal resto del contenuto, conoscendo gli esatti confini di quel paragrafo. Un controllo a cursore o ad albero è un esempio più complesso, in cui ciascuna delle varie parti di un widget ha una semantica che deve essere correttamente identificata affinché il computer possa supportare un'interazione efficace.

Insomma, se un elemento dell’interfaccia utente è definito da un ruolo, diventa utilizzabile, anche nelle sue modifiche dinamiche, da una tecnologia assistiva come uno screen reader. Tramite la definizione dei ruoli si potranno realizzare elementi d’interfaccia interattivi e dinamici accessibili. I ruoli definiti dallo sviluppatore per ciascun elemento d’interfaccia saranno passati alle API per l’accessibilità del sistema operativo dell’utente: per esempio MSAA di Microsoft, Cocoa di Apple ecc. Le API, a loro volta, passeranno l’informazione semantica alle tecnologie assistive conformi, che la useranno a beneficio dell’utente.

Leggendo i numerosi ruoli già definiti nella bozza delle specifiche, è facile intuire quale importanza potranno avere per l’accessibilità, una volta che il sistema sarà stato implementato a dovere. A titolo esemplificativo, elenchiamo di seguito alcuni ruoli, che definiscono elementi d’interfaccia per i quali HTML e XHTML non possiedono specifici marcatori strutturali:

I ruoli sono un po’ la carta d’identità di un elemento d’interfaccia. Però l’identità, per quanto importante, è un’informazione che in certi casi può non essere sufficiente. Ogni elemento, a seconda del suo ruolo, può trovarsi in una serie di stati differenti e avere differenti proprietà. Stati e proprietà possono essere modificati dinamicamente da un linguaggio di scripting ed è di fondamentale importanza che una tecnologia assistiva possa sapere in quale stato si trova un dato elemento d’interfaccia, così da poter comunicare l’informazione all’utente.

La bozza di raccomandazione WAI-ARIA States and Properties si occupa proprio di standardizzare gli stati e le proprietà di un elemento.

Citiamo dall’introduzione:

Stati e Proprietà sono usati per dichiarare importanti proprietà di un elemento, che influenzano e descrivono l’interazione. Queste proprietà abilitano il programma utente o il sistema operativo a gestire l’elemento in modo appropriato, anche quando tali proprietà sono alterate dinamicamente per mezzo di script. Per esempio, tecnologie per l’input e l’output alternativi, come screen reader, software per la dettatura vocale e tastiere a schermo, devono riconoscere lo stato di un elemento (per esempio, se un oggetto è disabilitato, selezionato, focalizzato, collassato, nascosto ecc.).

Benché sia possibile per le tecnologie assistive accedere a queste proprietà attraverso il Document Object Model (DOM), il meccanismo preferito è, per il programma utente, mappare gli stati e le proprietà presso le API per l’accessibilità del sistema operativo.

Nella Tabella 11.1 riportiamo alcuni stati e i relativi valori, così come appaiono nella bozza di raccomandazione del 1 giugno 2007. Leggendoli, ci si potrà rendere conto di quale progresso rappresenterà la loro implementazione, al fine di permettere a un utente di tecnologie assistive di interagire compiutamente con i comportamenti di un’applicazione dinamica.

Tabella 11.1 Alcune delle proprietà inserite nelle specifiche WAI-ARIA States and Properties
Stato Valori Descrizione
live off | polite | assertive | rude È probabilmente lo stato più importante per l’accessibilità, perché dal suo valore dipende se e come l’utente viene avvertito del fatto che qualcosa è cambiato in una delle regioni dinamiche (live regions) definite all’interno dell’applicazione.
Il valore off indica che la regione è momentaneamente inattiva; polite indica che vi sono cambiamenti che avvengono sullo sfondo, per i quali non occorre interrompere l’attività dell’utente (è la modalità normale in un’applicazione dinamica); assertive definisce un’informazione di alta priorità, ma che non impone un’interruzione immediata per l’utente; rude, infine, indica il più alto livello di priorità, tale da dover interrompere l’attività dell’utente, anche a costo di creare un disorientamento.
Un esempio di live con valore assertive potrebbe essere un avviso che entro cinque minuti l’applicazione terminerà; un esempio di rude potrebbe essere un avviso che impone all’utente di salvare tutto immediatamente, pena la perdita dei dati.
atomic true | false È una proprietà facoltativa di una regione dinamica. Quando i contenuti della regione sono aggiornati, la proprietà atomic indica a una tecnologia assistiva se è il caso di leggere solo ciò che è cambiato (corrisponde al valore predefinito false) o se va letto l’intero contenuto della regione attiva (valore true).
relevant additions | removals | text | all È un’altra proprietà facoltativa di una regione dinamica. I valori possono essere usati in combinazione, separandoli con spazi. Il valore additions indica che sono stati aggiunti dei nodi al DOM all’interno della regione dinamica; removals indica che dei nodi sono stati rimossi; text indica che del testo è stato aggiunto o rimosso; all somma tutti e tre i casi precedenti. Se la proprietà relevant non è specificata, si deve assumere che vi sono stati cambiamenti dinamici nel testo e sono stati aggiunti dei nodi.
expanded true | false | undefined Il valore true indica che un gruppo di elementi collassabile si trova nello stato di espanso (tutti gli elementi sono visibili); false indica che il gruppo è collassato (tutti i suoi elementi sono nascosti); undefined indica che il gruppo non è espandibile/collassabile e che tutti i suoi elementi sono visibili.
required true | false Il valore true indica che un campo di input deve essere obbligatoriamente compilato prima di spedire il modulo; false indica che il campo non è obbligatorio.
Il supporto per una simile proprietà renderebbe enormemente più semplice e uniforme comunicare a un utente di tecnologie assistive quali campi di un modulo sono obbligatori e quali no, rispetto all’uso di asterischi, grassetto, colore ecc.
labelledby IDREFS Il valore della proprietà rimanda a un elemento che ha lo scopo di etichettare, cioè di descrivere in modo essenziale cosa fa l’oggetto a cui è associato labelledby.
describedby IDREFS È la proprietà compagna della precedente. Rimanda a un elemento che contiene una descrizione più circostanziata delle funzionalità dell’oggetto a cui è associato.

Inizio pagina

Salta inserzione pubblicitaria

Uso di ruoli, stati e proprietà ARIA in XHTML e JavaScript

Per concludere l’argomento, non ci resta che esaminare in che modo ruoli, stati e proprietà possono essere incorporati nel codice di marcatura. Riportiamo a tale scopo un esempio tratto dalla bozza WAI-ARIA Roles.

Listato 11.10 Uso di ruoli e stati in XHTML.

......

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:wairole="http://www.w3.org/2005/01/wai-rdf/GUIRoleTaxonomy#"

xmlns:aaa="http://www.w3.org/2005/07/aaa">

<head>...</head>

<body>

...

<span class="checkboxtristate"

id="chbox1"

role="wairole:checkboxtristate"

aaa:checked="mixed"

onkeydown="return checkBoxEvent(event);"

onclick="return checkBoxEvent(event);"

tabindex="0">

Un'etichetta per una casella di spunta

</span>

...

</body>

</html>

I ruoli definiti nelle specifiche WAI-ARIA Roles possono essere incorporati in un documento XHTML prefissandoli con il nome qualificato wairole (per esempio: wairole:checkboxtristate), purché si abbia cura di referenziare lo spazio dei nomi in cui i valori di role sono definiti, tramite xmlns:wairole="[URI]" nell’elemento HTML.

Gli stati e le proprietà possono essere incorporati in modo analogo. Gli attributi che li definiscono vanno prefissati con il nome qualificato aaa, che sta per “Accessible, Adaptable Applications” (per esempio: aaa:checked="mixed"). Nell’elemento HTML, il riferimento al relativo spazio dei nomi si ottiene tramite xmlns:aaa="[URI]".

Ovviamente i valori di stati e proprietà possono essere modificati dinamicamente per mezzo di script che accedono al DOM. La definizione di queste modalità è, forse, il beneficio principale che ci si attende dal lavoro di standardizzazione del gruppo WAI-ARIA, dal momento che le interazioni dinamiche sono sicuramente l’elemento centrale e caratteristico delle cosiddette rich applications.

A tal proposito, nel sito di Mozilla, nella sezione dedicata all’accessibilità, è già disponibile un esempio funzionante in Firefox di manipolazione dinamica degli stati collegamento esterno. Si tratta di caselle di spunta che sono rappresentate da due immagini GIF diverse, una con il segno di spunta e l’altra senza. A seconda dello stato della casella, indicato dall’attributo aaa:checked, viene caricata l’una o l’altra delle due immagini. Il Listato 11.11 riporta script, stili e una parte del codice di marcatura, con adattamento alla lingua italiana.

Listato 11.11 Modifica dinamica di stati definiti da WAI-ARIA States and Properties.

// LO SCRIPT:

// Gestore di eventi da mouse e da tastiera per i controlli 'aaa'.

function checkBoxEvent(event) {

if ((event.type == "click" && event.button == 0) ||

(event.type == "keydown" && event.keyCode == 32)) {

// Cambia lo stato della casella di spunta

var checkbox = event.target;

if (checkbox.getAttributeNS(

"http://www.w3.org/2005/07/aaa", "checked") == "true") {

checkbox.removeAttributeNS(

"http://www.w3.org/2005/07/aaa", "checked");

}

else {

checkbox.setAttributeNS(

"http://www.w3.org/2005/07/aaa", "checked", "true");

}

return false; // Termina la propagazione dell'evento

}

return true; // Il browser può ancora utilizzare l'evento

};

/* GLI STILI CSS */

/* Viene richiamato lo spazio dei nomi che permette

di qualificare gli attributi prefissati con 'aaa' */

@namespace aaa url("http://www.w3.org/2005/07/aaa");

.checkbox:before {

content: url('./unchecked.gif')

}

/* Se il valore di aaa:checked è true, viene caricata

l'immagine della casella con il segno di spunta */

.checkbox[aaa|checked="true"]:before {

content: url('./checked.gif')

}

<!-- IL CODICE DI MARCATURA -->

<div>

<span class="checkbox" id="chbox1"

role="role:checkbox" aaa:checked="true" tabindex="0"

onkeydown="return checkBoxEvent(event);"

onclick="return checkBoxEvent(event);" >

Includi un cestino di frutta decorativo

</span>

</div>

<div>

<span class="checkbox" id="chbox2"

role="role:checkbox" aaa:checked="true" tabindex="0"

aaa:required="true" onkeydown="return checkBoxEvent(event);"

onclick="return checkBoxEvent(event);" >

Casella obbligatoria

</span>

</div>

<div>

<span class="checkbox" id="chbox3"

role="role:checkbox" aaa:checked="true" tabindex="0"

aaa:invalid="true" onkeydown="return checkBoxEvent(event);"

onclick="return checkBoxEvent(event);" >

Casella non valida

</span>

</div>

Per quanto riguarda la manipolazione degli stati tramite JavaScript, questa avviene, nello script del Listato 11.11, per mezzo dei metodi getAttributeNS, removeAttributeNS e setAttributeNS, in cui il suffisso NS sta per “namespace” e fa riferimento allo spazio dei nomi associato alle cosiddette “Accessible, Adaptable Applications”. Il collegamento allo spazio dei nomi serve per istruire il programma utente sull’origine e i valori possibili dell’attributo aaa:checked, che non appartiene alle DTD predefinite di XHTML.

Si noti, infine, che una tecnologia assistiva non potrebbe in nessun modo sapere che quelle definite nel codice sono caselle d’opzione e che sono compilabili dall’utente, senza l’uso degli attributi prefissati da role e aaa, inseriti nell’elemento SPAN. Le caselle, infatti, sono generate tramite fogli di stile e non esistono nella navigazione a CSS disabilitati (Figura 11.8 B). Tuttavia, per una tecnologia assistiva conforme alle Specifiche WAI-ARIA, esse esistono e sono utilizzabili, qualsiasi sia la presentazione del documento, grazie alle informazioni semantiche fornite da ruoli, stati e proprietà.

Figura 11.8. Il codice di marcatura del Listato 11.11 riprodotto con i fogli di stile attivi (A); lo stesso codice riprodotto senza fogli di stile (B). Le caselle di spunta scompaiono.

Una nota conclusiva: per verificare sul campo le potenzialità di AJAX reso accessibile è possibile usare Fire Vox, un’estensione gratuita per Mozilla Firefox collegamento esterno, realizzata da Charles L. Chen.

[Inizio approfondimento] Dove trovare la definizione dell’attributo role

L’attributo role, usato per specificare i ruoli, viene definito in un apposito modulo aggiuntivo per XHTML, attualmente allo stato di bozza (XHTML Role Attribute Module collegamento esterno, ultimo aggiornamento del 13 novembre 2006). L’attributo role è anche definito nativamente in XHTML 2 (Capitolo 26) collegamento esterno, le cui Specifiche, però, sono e rimangono allo stato di bozza, soggette a un’elaborazione interminabile che va avanti almeno dal 2002. [Fine approfondimento]

Inizio pagina

Tasti di accesso rapido: Indice generale 0 | Capitolo precedente 1 | Capitolo successivo 2 | Glossario 3 | Indice analitico 4 | Torna a inizio pagina 5 | Diodati.org 6 | Forum accessibili 7 | Commenti dei lettori 8 | Recensioni e citazioni 9
Creative Commons License
Accessibilità Guida completa versione HTML by Michele Diodati is licensed under a Creative Commons Attribuzione-Non commerciale-Non opere derivate 2.5 Italia License.