di Christian Heilmann
Traduzione da A List Apart #200
http://www.alistapart.com/articles/complexdynamiclists
Sostituiamo le liste di selezione dinamiche con una alternativa più accessibile.
Nella nostra lotta per ridurre il numero di passaggi che i visitatori di un sito devono compiere per raggiungere i loro obiettivi, ci tocca affrontare un buon numero di sfide. Una di queste è quella di offrire un buon modo agli utenti per scegliere all’interno di una lista di elementi gerarchici. Per esempio, una lista che sia come il menù di un ristorante, che offra una selezione di bevande, piatti principali, contorni e dolci.Possono essere usate due tecniche per risolvere questo tipo di problema:
- Il tradizionale approccio passo - passo, che ricarica a ogni cambio pagina. E’ il metodo più sicuro e comunemente usato, ma aumenta il traffico del server e richiede pazienza dal lato utente.
- Liste di selezione dinamiche
La soluzione complessa
Le liste di selezione dinamiche, nelle quali scegliere un elemento nella prima lista cambia il contenuto della seconda, evita all’utente un reload, nel caso abbia JavaScript a disposizione. In caso contrario, è necessario ricaricare la pagina e riempire la seconda lista di selezione via server. Entrambe le opzioni hanno ugualmente problemi:
- A meno che si generi la seconda lista tramite il DOM, o dopo il primo invio della pagina al server, i visitatori senza JavaScript avranno un elemento di pagina interattivo che non funziona: una lista di selezione vuota.
- A meno che si generino le array dello script via server (settando un header text/javasscript in uno script PHP, per esempio) o vengano scritte nella pagina in qualche modo, dobbiamo mantenere dati in due posti differenti.
- Più livelli sono necessari, più complesso sarà il nostro JavaScript (array annidate o complesse potrebbero non essere semplici da mantenere per altri sviluppatori che implementeranno il codice dopo di noi).
- In caso non sia possibile avere gli stessi valori come testo visibile (per esempio in un sito multilingua) le array diventeranno ancora più grosse e più complesse.
La soluzione semplice
Analizziamo il problema alla radice. Noi vogliamo:
- Mostrare una lista gerarchica di opzioni nel dettaglio e con molti elementi.
- Offrire ai visitatori un livello di opzione per volta e nascondere gli altri.
Noi non vogliamo:
- Manutenzione macchinosa o ridondante;
- Markup “morto”;
- Dipendenza dallo scripting che debba essere mitigata duplicando gli sforzi lato server.
Il nostro arsenale HTML ci offre uno strumento perfetto per questo lavoro: le liste. Con una lista non ordinata, possiamo facilmente mostrare una struttura gerarchica di una complessità difficile da gestire con le liste di selezione dinamiche. L’abbiamo già fatto per le navigazioni dei siti, quindi perchè non qui? L’unica differenza è che non tutti gli elementi di lista sono collegamenti, solo le opzioni finali puntano a uno script backend.Ci sono diversi modi per trasformare questa lista in un sistema di navigazione più semplice da usare. Possiamo trasformarlo in un menù drop-down per la navigazione, o in qualcosa che assomigli all’albero dell’Explorer di Windows. Per il nostro esempio, lavoreremo con i seguenti assunti:
- Vogliamo che il risultato sia completamente accessibile;
- Dato che quasi tutti gli schermi sono più larghi che alti, vogliamo che il nostro sistema di navigazione sia orientato orizzontalmente.
Il primo assunto ci porta ad escludere soluzioni esclusivamente CSS come il Suckerfish Dropdowns, dato che non è possibile espandere e comprimere elementi tramite tastiera usando queste tecniche. (Pochi browsers supportano la proprietà :focus propriamente.) Useremo il Finder di Macintosh OS X come esempio di interfaccia. Nella modalità a colonne (mostrata sotto), questa applicazione mostra il contenuto del vostro disco fisso, sorprendentemente, in colonne; selezionare l’icona di una cartella ne apre una successiva.

Creare il menu
Il nostro HTML è decisamente semplice. Usiamo una lista annidata, e le abbiniamo l’ID “finder”, successivamente la inseriamo in un DIV per controllare le sue dimensioni e posizionare la lista:
[…]
Il nostro script dovrebbe seguire i principi del JavaScript non intrusivo e applicare se stesso solo nel caso in cui il browser possa gestirlo e sia disponibile il corretto HTML. Aggiungiamo e rimuoviamo classi dinamicamente per permetterci di mantenere il completo look and feel nel CSS.Lo script esegue questi compiti:
- Controlla che il browser possa usare il DOM correttamente;
- Cerca di trovare la lista con ID “finder”;
- Applica la classe “domenabled” al corpo del documento, che ci permette di definire viste differenti nel caso in cui JavaScript sia disponibile o meno;
- Applica la classe “hidden” alle liste annidate all’interno della lista finder;
- Esegue un ciclo attraverso ogni elemento di lista all’interno della lista finder e aggiunge collegamenti con classe “parent” a ognuno di questi che contenga una lista annidata al suo interno;
- Applica la classe “open” ai collegamenti quando sono selezionati e la classe “shown” alla lista annidata conseguente.
Per mostrare il nostro menu finder, dovremo definire il seguente CSS:
.domenabled #finderparent
{
position:relative;
height:150px;
}
.domenabled #finder
{
position:absolute;
top:1em;
left:1em;
}
.domenabled ul#finder,
.domenabled ul#finder li,
.domenabled ul#finder ul
{
width:200px;
list-style-type:none;
margin:0;
padding:0;
}
Diamo in questo caso all’elemento parent un’altezza per contenere il finder e lo posizioniamo relativamente per renderlo l’elemento di posizionamento relativo del finder. Quindi posizioniamo la lista finder al suo interno ed eliminiamo ogni margin e padding. Definiamo ogni lista annidata larga 200px.Successivamente dobbiamo definire le due classi per mostrare e nascondere le liste annidate. Per questo, useremo una tecnica “off left”, basata sul lavoro di Mike Rundle:
.domenabled ul#finder ul.hidden
{
top:0px;
left:-2000px;
position:absolute;
}
.domenabled ul#finder ul.shown
{
top:0px;
left:200px;
position:absolute;
}
L’ultima cosa che dobbiamo definire è l’aspetto dei differenti stati dei collegamenti, il link “parent” indica che contiene un ulteriore sotto menù, il link “open” viene mostrato quando il menù contenuto è visibile ed è una opzione finale.
.domenabled ul#finder li a
{
color:#000;
background:url(normal.gif) no-repeat #fff 0 50% ;
padding-left:16px;
text-decoration:none;
}
domenabled #finder a.open
{
background:url(arrowon.gif) no-repeat 90% 50% #eee;
padding-right:16px;
padding-left:0px;
display:block;
}
.domenabled #finder a.parent
{
background:url(arrow.gif) no-repeat #fff 100% 50%;
padding-right:16px;
padding-left:0px;
}
Questo è tutto. Il nostro finder-style menu è pronto. Se selezioniamo i collegamenti delle opzioni finali puntando a un backend script possiamo aggiungere gli elementi selezionati a un ordine.
Potremmo anche migliorare lo script permettendo al visitatore di riassemblare l’intero ordine senza ricaricare la pagina. Il problema con questo è che non possiamo offrire la stessa esperienza a un visitatore che un vero reload potrebbe dare. Per esempio, rendiamo il pulsante back dei browser inutile. (Questo è noto come il Problema Ajax - o presto lo sarà.)
Per favore non prendete questo esempio abilitato all’ordine troppo alla lettera; questo articolo è inteso per dimostrare come usare il DOM per sostituire le liste di selezione dinamica con liste più accessibili. Un vero sistema di ordinazione prodotti, ovviamente, dovrebbe avere opzioni di rimozione oggetti e una lista prezzi. Sentitevi liberi di scaricare gli esempi e modificarli secondo i vostri gusti.
Christian Heilmann was born in Germany, survived dot-com crashes in the States, and currently works as a lead developer of Agilisys in London. More of his articles and works can be found at icant.co.uk.
