Tradotto dall’originale Improving link display for print di Aaron Gustafson pubblicato su www.alistapart.com
La pagina stampata di Eric Meyer
Diversi mesi fa, Eric Meyer scrisse un articolo fondamentale per A List Apart, in cui offriva una chicca di CSS2:
a:link:after,
a:visited:after {
content: " (" attr(href) ") ";
font-size: 90%;
}
Se usiamo questa sintassi in un foglio di stile per la stampa, tutti i browser che interpretano il CSS2 (Mozilla & Netscape, tranne IE al momento, sebbene la prossima versione IE7 lo supporti) visualizzeranno il valore dell’attributo href associato a un’ancora, in sequenza, dopo il testo, appena più piccolo e tra parentesi:


Questo è incredibilmente utile per chi stampa la pagina, perché lo avverte della destinazione del link. Tuttavia, se abbiamo un paragrafo con molti collegamenti (specialmente quelli lunghi), questa tecnica danneggia la leggibilità:

Il piano
Le note a piè di pagina e a fine pagina sono una convenzione nella stampa percui sembra naturale andare in questa direzione. Seguendo questo ragionamento, i nostri obiettivi saranno:
- Raggruppare tutti i link presenti (href e citazioni) in un contenitore specifico all’interno della pagina,
- Inserire questi link (escluse le duplicazioni) in un elenco puntato che può essere collocato in un selettore id a nostra scelta e
- Associare a ogni link un numero di nota a piè pagina con un apice.
Fortunatamente, tutto ciò è nelle nostre possibilità grazie al DOM e a JavaScript.
Il codice javascript
Prima di iniziare la compilazione, evidenziamo gli elementi essenziali del codice:
function footnoteLinks() {
// individuo ed etichetto il contenitore
// creo un titolo per le note
// creo un elenco numerato per le note
// creo un array per depositare i link usati così da controllare
// i duplicati
// creo una variabile per tenere traccia del numero di ciascun
// link, così da usarlo come riferimento per le note
// raggruppo tutti gli elementi nel contenitore
// all’interno di un array
// creo un ciclo degli elementi all’interno dell’array, individuando gli href
// e le citazioni
// se trovo un duplicato
// prendo il numero del link usato dall’array
// altrimenti
// creo il tag <li> all’interno di <ol>
// deposito il link nell’array
// incremento la variabile numero
// creo il tag <sup> e lo inserisco dopo il link
// inserisco il titolo e il tag <ol> nel contenitore }
Questo ci fornisce una solida base per incominciare. Eseguiremo ogni compito separatamente, a cominciare dalla funzione stessa. Dobbiamo passarle due variabili: una per l’id del contenitore in cui raggruppiamo gli URI (containerID) e una per l’id del contenitore in cui inseriamo le nostre note (targetID):
function footnoteLinks(containerID,targetID) {
Una volta inseriti questi argomenti, possiamo facilmente identificare questi contenitori nel nostro script:
// individuo ed etichetto il contenitore
var container = document.getElementById(containerID); var target = document.getElementById(targetID);
Questo renderà le cose più facili in seguito.
Il prossimo passo è la titolazione del contenitore. Dal momento che vogliamo visualizzarlo solo nella versione stampata (come tutto il resto) gli daremo la classe “solo per la stampa” (scriveremo in seguito il selettore CSS):
// creo un titolo per le note
var h2 = document.createElement('h2');
addClass.apply(h2,['printOnly']);
var h2_txt = document.createTextNode('Links'); h2.appendChild(h2_txt);
[Nota: applichiamo la funzione addClass() ricavata da jsUtilities package per attribuire una classe ai nostri elementi.]
Ora possiamo creare il nostro elenco puntato e le variabili:
// creo un elenco <ol> per le note
var ol = document.createElement('ol');
addClass.apply(ol,['printOnly']);
// creo un array per i link
// e controllo le duplicazioni
var myArr = []; var thisLink; var num = 1;
Ora le modiche principali. Passiamo in rassegna tutti gli elementi del contenitore, alla ricerca degli attributi href e cite. Da notare che nell’XHTML 2.0 possiamo rendere in un link ogni elemento e attribuire il tag cite, non solo <blockquote> e <q>, percui non limitiamoci solo ad ancore, blocchi di testo e citazioni:
// raggruppo gli elementi in un contenitore
// all’interno di un array
var coll = container.getElementsByTagName('*');
Ora facciamo un ciclo tra gli elementi cercando gli attributi href e cite:
for (var i=0; i<coll.length; i++) {
// check for our attributes
if ( coll[i].getAttribute('href') || coll[i].getAttribute('cite') ) {
// grab the reference
thisLink = coll[i].getAttribute('href') ? coll[i].href : coll[i].cite;
Sin qui va bene, ora creiamo gli apici:
var note = document.createElement('sup');
addClass.apply(note,['printOnly']);
Assumiamo che ogni riferimento URI sia unico, in seguito cercheremo i duplicati:
var note_txt = document.createTextNode(num);
note.appendChild(note_txt);
Assumiamo anche di escludere i testi tra virgolette per ora, e passiamo ad associare i link in sequenza:
coll[i].parentNode.insertBefore(note, coll[i].nextSibling);
Associamo a ciascun elemento in elenco il corrispondente URI e inseriamo quest’ultimo nell’array (ci servirà per i duplicati):
var li = document.createElement('li');
var li_txt = document.createTextNode(thisLink);
li.appendChild(li_txt); ol.appendChild(li);
// store the link in the array myArr.push(thisLink);
[Nota: non tutti i browser supportano in modo nativo il push method, ma possiamo ovviare con un piccolo script. Vedi jsUtilities package.]
Incrementiamo il numero per il prossimo link e chiudiamo il ciclo:
num++;
}
Per finire, titoliamo e creiamo l’elenco numerato:
target.appendChild(h2);
target.appendChild(ol); }
Prima di inserire lo script dobbiamo fare un pò di pulizia. Eliminiamo gli URI duplicati. Cerchiamo nell’array (myArr) i riferimenti URI usati. Per farlo ci serviamo della funzione PHP inArray function (disponibile nel jsUtilities package). inArray cerca un valore e genera “true” se lo trova e “false” in caso contrario.
for (var i=0; i<coll.length; i++) {
if ( coll[i].getAttribute('href') || coll[i].getAttribute('cite') )
{ thisLink = coll[i].getAttribute('href') ? coll[i].href : coll[i].cite;
var note = document.createElement('sup'); addClass.apply(note,['printOnly']);
var note_txt; var j = inArray.apply(myArr,[thisLink]);
if ( j || j===0 )
{
// if a duplicate
// get the corresponding number from the array of // used links
note_txt = document.createTextNode(j+1);
}
else { // if not a duplicate
// build the <li> and append to the <ol>
var li = document.createElement('li');
var li_txt = document.createTextNode(thisLink);
li.appendChild(li_txt); ol.appendChild(li);
// store the link in the array myArr.push(thisLink);
note_txt = document.createTextNode(num);
// increment the number variable num++; }
note.appendChild(note_txt); … } }
Nel codice qui sopra cerchiamo thisLink all’interno di myArr e associamo l’apice di conseguenza. Se thisLink esiste (j è “true”), creiamo l’apice j+1. Se thisLink non esiste (j è “false”), creiamo l’elemento nell’elenco, lo inseriamo all’interno di <ol>, ricerchiamo thisLink in myArr e inseriamo l’apice incrementando i numeri. Da notare che poiché inArray genera l’array index, il valore di j può essere 0 se è il primo elemento dell’array. JavaScript interpreta ciò come false se abbiamo usato l’operatore “is equal to” (j==0), percui usiamo “is identical to” (j===0) per individuare i duplicati.
Il prossimo passo è aggiungere gli apici agli elementi del blocco di testo. Generalmente questo coincide col tag <blockquote>. Il nostro <blockquote> può contenere paragrafi (<p>) ed elenchi (<ul>, <ol>, <dl>). Vogliamo che gli apici appaiano alla fine del testo per cui cerchiamo l’ultima istanza di <blockquote>. Per fare ciò usiamo la funzione lastChildContainingText (sempre in jsUtilities):
function footnoteLinks(containerID,targetID)
{ … if (coll[i].tagName.toLowerCase() == 'blockquote')
{
var lastChild = lastChildContainingText.apply(coll[i]);
lastChild.appendChild(note);
} else
{
coll[i].parentNode.insertBefore(note, coll[i].nextSibling);
}
…
}
Per finire, facciamo in modo che lo script siano ben interpretato da tutti i browser, compresi quelli che non supportano questa funzione…
function footnoteLinks(containerID,targetID)
{ if (!document.getElementById ||
!document.getElementsByTagName ||
!document.createElement) return false;
…
}
…e nelle pagine in cui sono assenti gli elementi del contenitore:
function footnoteLinks(containerID,targetID) {
if (!document.getElementById ||
!document.getElementsByTagName ||
!document.createElement) return false;
if (!document.getElementById(containerID) ||
!document.getElementById(targetID)) return false;
…
}
Quindi eseguiamo la funzione nella pagina.
window.onload = function() {
footnoteLinks('container','container');
}
E creiamo la classe di stile .printOnly…
.printOnly {
display: none;
}
…ecco il nostro prodotto finito.
All’occorrenza…
Tutto ciò assume che JavaScript sia attivato, ma se non è così? Basta tornare al foglio di stile iniziale di Eric e rimuoverlo quando non ci occorre.
Quindi recuperiamo la dichiarazione iniziale nel CSS per gli elementi href e quando eseguiamo lo script attribuiamo al tag <html> la classe “noted.” Quindi facciamo in modo che il foglio di stile per la stampa disabiliti il contenuto se il link in questione deriva da html.noted:
html.noted a:link:after,
html.noted a:visited:after {
content: "";
}
Raccogliamo il tutto
Così otteniamo un documento stampabile, pulito e bello da vedere con tutti i link e le citazioni raccolti nelle note di pagina. Possiamo anche personalizzarlo, ad esempio ignorando determinati collegamenti ipertestuali.
E’ possible prelevare l’ultima versione di footnoteLinks da questa homepage o da questo articolo. Tutti i JavaScript si trovano nel pacchetto jsUtilities 2.1, disponibile in formato compresso a questo indirizzo.