Finestre pop-up accessibili
Articolo a cura di: , pubblicato il 14.04.07
Tradotto dall’originale Accessible Po-up Links di Caio Chassot pubblicato su www.alistapart.com
A volte non possiamo fare a meno delle finestre a comparsa percui è bene usarle correttamente. Quest’articolo ci spiega come renderle accessibili, affidabili e semplici da usare.
Come premessa, le finestre a comparsa (o pop-up) solo collegamenti ipertestuali che si aprono in una nuova finestra attraverso l’uso di Javascript. Normalmente ricorreremmo all’attributo target="_blank”. Invece , le finestre a comparsa si usano o per impostare determinate caratteristiche alla finestra oppure perché il DOCTYPE usato (ad esempio l’XHTML) non permette l’uso dell’attributo target. [...]
Quello che non va
Mettiamo fine a un problema tipico delle finestre a comparsa: il codice HTML. Un esempio:
<a href="JavaScript:
raw_popup('http://example.com');
void(0)">pop me up</a>
Il problema è tutto qui. Ci sono due aspetti critici di usabilità altrimenti evitabili. Il primo è che gli utenti che disabilitano JavaScript non apriranno la finestra a comparsa.
La ragione è semplice e banale: il collegamento è associato a un’azione (una funzione JavaScript) piuttosto che alla sua reale destinazione. Ma scopo della funzione dovrebbe essere il caricamento del collegamento.
Quel che è peggio
Il secondo problema non è così ovvio ma si evince dall’ironia del caso: il collegamento sarà inutilizzabile proprio per gli utenti che avevano in mente di aprire una nuova finestra.
Quando apriamo un link in una nuova finestra o pannello avviene questo: il browser memorizza ciò che è specificato nell’attributo “href” e lo imposta come destinazione della nuova finestra o pannello.
Se JavaScript è disabilitato siamo al primo problema. Se invece è abilitato il browser richiamerà la funzione pop-up all’interno della nuova finestra ma senza risultato dal momento che la funzione Javascript si trova nella pagina iniziale. [...]
A ciascuno il suo…
Entrambi i problemi derivano dallo stesso errore: specificano come destinazione del collegamento ciò che in realtà non lo è affatto.
Sarebbe meglio allora specificare la destinazione nell’attributo “href” e usare un evento (dove collocare il codice JavaScript) per aprire la nuova finestra con le sue proprietà.
Ecco un approccio semplice:
<a href="http://example.com"
onclick="raw_popup('http://example.com');
return false">pop me up</a>
Potremmo semplificare passando l’elemento alla funzione e fare in modo che legga la URL dall’attributo “href”:
<a href="http://example.com"
onclick="link_popup(this);
return false">pop me up</a>
Quest’ultimo esempio è utile per fornire un collegamento separato agli utenti che hanno disabilitato JavaScript. Da considerare che l’URL che apriranno gli utenti che intervengono manualmente con una nuova finestra è quella presente nell’attributo “href” non quella passata da JavaScript. [...] Va bene per il momento ma possiamo fare di meglio.
Facciamolo con l’HTML
Una linea guida dovrebbe essere quella di usare solo codice supportato dall’HTML [...] Il Javascript dovrebbe essere solo il complemento.e:
[...] Ecco il codice HTML migliorato:
<a href="http://example.com"
target="_blank" onclick="link_popup(this);
return false">pop me up</a>
Aggiungendo l’attributo “target” facciamo in modo che il collegamento si apra in una nuova finestra, anche con Javascript disabilitato e senza definire gli attributi della finestra.
Per i patiti dell’accessibilità
L’evento “onclick” in realtà non si attiva solo con l’uso del mouse: lo stesso risultato si ottiene ad esempio premendo “Enter” sulla tastiera usando i più diffusi programmi di navigazione.[...]
Utilizzo
Una volta “ripulito” il codice HTML, sporchiamolo con un pò di Javascript. [...]:
var _POPUP_FEATURES = '
location=0,
statusbar=0,
menubar=0,
width=400,
height=300
';
function raw_popup(url, target, features) {
if (isUndefined(features)) {
features = _POPUP_FEATURES;
}
if (isUndefined(target)) {
target = '_blank';
}
var theWindow =
window.open(url, target, features);
theWindow.focus();
return theWindow;
}
function link_popup(src, features) {
return
raw_popup(src.getAttribute('href'),
src.getAttribute('target') || '_blank',
features);
}
Vediamo le cose un pò più da vicino:
raw_popup racchiude la funzione “window.open” assieme ad altri elementi per semplificarci la vita:
- se nessun attributo è definito, sarà di norma
_blank. E se nessuna proprietà è definita, sarà di norma_POPUP_FEATURES. - se la finestra a comparsa è già aperta, verrà portata in primo piano. Potrà tuttavia rimanere in secondo piano, se gli abbiamo dato un nome (specificando l’attributo
targetdiverso da_blank) e se alla finestra è destinato più di un collegamento. Un principio di usabilità vuole che si individui la finestra a comparsa altrimenti l’utente ha l’impressione di non ricevere risposta nel cliccare il link.
link_popup serve proprio ad aprire nuove finestre da un link. Recupera l’URL a partire dall’attributo href ed eventualmente la finestra di destinazione dall’attributo target. Se quest’ultimo non è definito, sarà di norma _blank. Ciò rende la funzione compatibile con il codice HTML più stringente (XHTML strict) senza compromettere l’uso dell’attributo target. Andrebbe sempre specificato un target se il codice HTMl è di tipo transitional DOCTYPE per gli utenti che disabilitano JavaScript. [...]
La funzione isUndefined in alto proviene dalla mia personale libreria e alla fine dell’articolo si trova una versione da prelevare. (Tutta la libreria è accessibile qui.) [...]
Se tutto quello che ti occorre è una o due finestre a comparsa allora ti basta questa funzione. Se invece devi farne ampio uso (come nel caso di gallerie di immagini o forse in un CMS) allora continua a leggere l’articolo.
Separare il contenuto dalla grafica
L’avrai sicuramente già sentito dire: bisogna separare il contenuto dalla grafica. Ed è vero. oltreché piacevole da vedere è anche facile da mantenere.
Torniamo allora al nostro codice HTML. C’è qualcosa di estraneo. Di cosa si tratta? JavaScript! Eliminiamo l’evento onclick:
<a id="my-popup-link"
href="http://example.com"
target="_blank">pop me up</a>
Ora dobbiamo associare gli eventi al tag “a” per aprire le finestre a comparsa. Per farlo col JavaScript inseriamo questo codice. Lo script va inserito nell’head del documento (così com’è oppure come collegamento esterno):
function event_popup(e) {
link_popup(e.currentTarget);
e.preventDefault();
}
listen('load', window, function() {
listen('click', 'my-popup-link', event_popup);
// ... other onload statements
}
);
[...] Listen è un’implementazione cross-browser dell’evento DOM’s addEventListener() e prende tre parametri : event, elem e func. Per determinare elem usa getElem, anch’esso presente nella mia libreria . getElem sta per document.getElementById con una particolarità: può prendere il selettore id. [...] Pertanto elem può essere sia una string o un Element.[...]
Sbizzariamoci con il DOM
Aggiungere un listener attraverso l’id può andar bene se abbiamo pochi link da aprire, ma diventa noioso ripeterlo quando i link sono tanti. Per questo usiamo mlisten.
mlisten funziona come listen, ma prende un elenco di elementi anziché i singoli elementi e vi associa a ciascuno il listener. L’elenco può essere un NodeList o un Array di stringhe id e/o oggetti Element.
Ecco un esempio dell’uso di mlisten:
mlisten(
'click',
document.getElementById('my-link-list').»
getElementsByTagName('a'),
event_popup
);
Se i nostri link non sono raggruppati, possiamo selezionarli per class usando la funzione getElementsByClass(className [, tagName [, parentNode]]):
mlisten(
'click',
getElementsByClass('popup','a'),
event_popup
);
[...]
Un piccolo inconveniente
Usando i listeners non possiamo fornire parametri alle funzioni. E quindi non possiamo attribuire i parametri features a ciascun link. Ecco come ovviare:
function event_popup_features(features) {
return function(e) {
link_popup(e.currentTarget, features);
e.preventDefault();
}
}
// onload...
listen(
'click',
'some-link',
event_popup_features('width=300,height=800')
);
Va fatta un’importante distinzione. Se fn è una funzion, tutte le volte che scriviamo fn ci riferiamo a fn. Se invece scriviamo fn() stiamo richiamando la funzione fn con tutto ciò che essa genera.
Qui usiamo una funzione che genera un’altra funzione. Non stiamo assegnando event_popup_features all’evento, ma lo stiamo richiamando assegnandogli la funzione in esso contenuta. [...]
articolo molto completo. Volevo segnalare solo che se si vuole essere conformi all’XMTML Strict, non è possibile usare l’attributo TARGET negli hyperlink