Usare Jquery per gestire tabelle e altri elementi con overflow su dispositivi mobili

Qualche tempo fa mi stavo occupando di rendere un sito web mobile-friendly e mi sono trovato di fronte alla necessità di gestire delle tabelle molto larghe. Purtroppo non era possibile pretendere che le tabelle fossero tutte quante di larghezza ridotta o con poche colonne, perciò era necessario usare l’overflow orizzontale con il CSS.

Oltre alle tabelle, ci sarebbero state anche delle formule visualizzate con Mathjax che — se molto lunghe — avrebbero “sfondato” la pagina. Ho avuto modo di accorgermi ben presto che la soluzione è leggermente meno semplice di quanto si possa pensare.

Nonostante le ultime versioni di Android e di iOS per iPhone/iPad supportino lo scorrimento di parti di pagina affette da overflow, le versioni vecchie di Android non permettono di scorrere correttamente con il dito, mentre quelle di iOS richiedono due dita e ciò è poco intuitivo.

Fortunatamente, ho trovato una soluzione interessante in Javascript sul blog di Chris Barr. Leggendo i commenti, ho anche scoperto con piacere che un lettore (Jeff) ne aveva fornito una versione Jquery, mentre un altro (Cormac) suggeriva l’utilizzo del metodo .live() per consentirne un corretto utilizzo anche su elementi caricati nel DOM in un momento successivo.

Ho deciso di unire i due approcci ed è venuto fuori il seguente risultato, che potete includere all’interno della pagina:


function isTouchDevice(){
	try {
		document.createEvent("TouchEvent");
			return true;
	}
	catch(e) {
		return false;
	}
}

function touchScroll(selector) {
    if (isTouchDevice()) {
        var scrollStartPosY=0;
        var scrollStartPosX=0;
        $("body").delegate(selector, 'touchstart', function(e) {
            scrollStartPosY=this.scrollTop+e.originalEvent.touches[0].pageY;
            scrollStartPosX=this.scrollLeft+e.originalEvent.touches[0].pageX;
        });
        $("body").delegate(selector, 'touchmove', function(e) {
            if ((this.scrollTop < this.scrollHeight-this.offsetHeight &&
                this.scrollTop+e.originalEvent.touches[0].pageY < scrollStartPosY-5) ||                  (this.scrollTop != 0 && this.scrollTop+e.originalEvent.touches[0].pageY > scrollStartPosY+5))
                    e.preventDefault();
            if ((this.scrollLeft < this.scrollWidth-this.offsetWidth &&
                this.scrollLeft+e.originalEvent.touches[0].pageX < scrollStartPosX-5) ||                  (this.scrollLeft != 0 && this.scrollLeft+e.originalEvent.touches[0].pageX > scrollStartPosX+5))
                    e.preventDefault();
            this.scrollTop=scrollStartPosY-e.originalEvent.touches[0].pageY;
            this.scrollLeft=scrollStartPosX-e.originalEvent.touches[0].pageX;
        });
    }
}

La cosa interessante della soluzione proposta da Jeff (e che ho riutilizzato) è quella di permettere il corretto funzionamento dei link contenuti nell’elemento che scorre.

Come potete intuire dal codice, la prima funzione controlla se il dispositivo è dotato di touchscreen oppure no, mentre la seconda accetta un selettore Jquery e associa un evento che viene azionato quando l’utente scorre con il dito sopra gli elementi corrispondenti.

Per applicare lo scorrimento alle tabelle, è necessario racchiuderle con un contenitore (in questo caso un <div>) in modo da applicare l’overflow, che con le tabelle non funziona in modo convenzionale.

La funzione deve essere richiamata dentro a $(document).ready(), e può essere utilizzata così, tenendo presente il trucco per le tabelle:


$(document).ready(function() {
    touchScroll(".MathJax_Display");
    $("table").wrap('<div class="table-scroll"></div>');
    $(".table-scroll").css('overflow', 'auto');
    touchScroll(".table-scroll");
});

La prima chiamata a touchScroll() si occupa delle formule prodotte da MathJax, i cui elementi compaiono nel DOM in un momento successivo ma sono catturati ugualmente grazie all’uso di .delegate(). Le seguenti righe si occupano invece di racchiudere le tabelle con un contenitore di classe table-scroll e applicano la funzionalità di scorrimento usando il selettore adeguato.

Questo è quanto! Come avete visto, una volta predisposta la funzione di Chris Barr modificata da Jeff, Cormac e me è sufficiente usare una chiamata per applicare l’overflow agli elementi desiderati. Nel caso delle tabelle, è necessario inserire un contenitore addizionale, ma questo si può fare con Jquery, in modo da evitare di introdurre modifiche al markup della pagina.

Utilizzare il nuovo Readability tramite bookmarklet anche su Android (2.2)

Per chi non lo conoscesse, Readability è uno strumento da utilizzare quando si naviga in internet e ci si imbatte in un sito web dal layout scomodo oppure infestato di banner colorati e lampeggianti da tutte le parti, oppure ancora con font piccolissimi. Una volta premuto un pulsante (o un segnalibro speciale, detto bookmarklet) inizia la “magia” e il contenuto principale della pagina viene portato in centro e reso comodo da leggere, mentre tutto il resto sparisce.

Vi faccio un esempio con un sito che ogni tanto leggo, il ScienceDaily. Le notizie sono interessanti, però il layout è orrendo! Più di metà pagina (in senso verticale) è dedicato a ben due barre laterali con un sacco di link ad altri articoli, e la colonnina da leggere è tutta compressa sulla sinistra (per di più inframezzata da un elenco di altri link). Ecco uno screenshot dell’articolo Mathematical Model for Moving Bottlenecks in Road Traffic:

Estrema scomodità di lettura

La stessa pagina processata da Readability si visualizza all’incirca così (c’è anche una barra laterale che ho ritagliato):

Layout semplice e leggibile

Quella che vedete è l’ultima versione, che è diventata attiva oggi (almeno per quello che ho potuto notare). Prima la funzionalità principale (cioè quella di leggere bene le pagine, appunto) era semplicemente attivata da un bookmarklet che si salvava nei segnalibri del browser (io per comodità lo tengo proprio nel menu segnalibri). Uno strumento che ha funzionalità analoghe è Notforest, il quale però elimina sempre tutte le immagini. A seconda dei casi uno può essere migliore dell’altro. 🙂

Ora hanno introdotto l’estensione per Firefox e altri browser, io però continuo a preferire il bookmarklet perché posso memorizzarlo nel menu assieme a quello di Notforest. Cercando un po’ nelle FAQ alla fine ho scoperto che l’hanno mantenuta aggiornata per chi vuole. Si trova disponibile qui.

Sul sito di Readability scrivono chiaramente che questo bookmarklet non funziona con Android e la funzionalità di lettura sul telefono è disponibile per chi paga la versione premium. Ciò è vero, ma è semplicemente perché hanno codificato il bookmarklet con un sacco di caratteri di escape! È sufficiente usare un purificatore di javascript togliendo i ritorni a capo e le tabulazioni per ottenere un bookmarklet utilizzabile con Android. Vi ricordo che avete bisogno almeno della versione 2.2, perché prima i segnalibri con codice javascript non erano supportati.

Per installarlo andate a questo indirizzo con il vostro telefono e tenete premuto sull’area di testo modificabile. A questo punto scegliete l’opzione “copia tutto” e create un nuovo segnalibro nel browser di Android. Nell’indirizzo incollate il codice che avete copiato prima. Ora non vi resta che visitare una pagina con un articolo e pubblicità varie intorno e provare a “visitare” il segnalibro di Readability. Attendete qualche istante e vedrete un risultato simile a questo:

Le eventuali immagini vengono automaticamente adattate: mai più scorrimento orizzontale!

Con i bookmarklet precedenti c’erano più possibilità di personalizzazione “permanente” nel senso che si poteva salvare uno specifico stile grafico da usare sempre, però in compenso non veniva generato un URL per la pagina ripulita, cosa che si rivela molto comoda per inviarlo ad altre persone. Il trucco di PasteBin è stato ripreso da ciò che ha suggerito Chivil sul proprio blog.