Hopp til innholdet

cjohansen.no

Scripting med tabeller

Julekalenderens siste tabell-innlegg kikker litt på måter å scripte med tabeller for økt brukerglede.

Sortering av tabeller

Tabeller er spennende fordi de er komplekse innholdselementer som vi kan gjøre mye rart med for å øke bruksverdien av. Et eksempel på dette er sortering. Å kunne enkelt sortere tabeller ved å klikke på headingene er en meget hendig funksjon, ikke minst også fordi brukerne dine sannsynligvis er vant til det (tenk filutforskeren osv). Noen vil kanskje tilogmed forvente det.

Et smart hode ved navn Stuart Langrige har laget en elegant løsning på sortering. Å bruke dette scriptet er så enkelt som å lenke det inn til dokumentet og så sette class="sortable" på tabellene som skal være sortérbare. Det kan være en idé og også stile headingene på en måte som gir brukerne et hint om at disse faktisk er klikkbare. Piler opp og ned er vanlige symboler for sortering.

Sortering rett ut av boksen

Eksempel på sortering slik det kommer rett ut av boksen kan sees i mitt modifiserte tabell-eksempel. Den relevante endringen, i tillegg til at selve scriptet er lastet ned på min server og lenket inn med <script> er:

<table class="sortable"
       summary="Oversikt over personer som har spilt poker og
                blackjack, samt deres innsats, antall spill og gevinst">
    ...
</table>

Resultatet er rett så bra, men noen "hickups" er det da enda: Før brukeren første gang trykker på headingen for å sortere er det ingen synlig indikasjon på at tabellen kan sorteres. Zebra-stripene mine blir bare rot etter sortering, og i tillegg er dato-sorteringen noe merkelig.

Synlig indikasjon på sortering

Denne er relativt lett å få til. Vi kan bruke klassenavnet sammen med den rike konteksten tabellen vår faktisk har, og sette pilen som bakgrunnsbilde på heading-cellene. Siden vi allerede har brukt disse til den grå gradienten må vi først flytte gradienten over i <thead>-elementet:

thead, tfoot {
    background: url(thbg.gif) top left repeat-x #bbb;
}

Deretter er thead th-bakgrunnen "ledig":

.sortable thead th {
    padding-right: 18px;
    background: url(arrow_down.gif) 91% 60% no-repeat;
    cursor: pointer;
}

Resultatet kan sees her.

Et problem vedvarer: når jeg klikker på headingene får jeg to piler, og den opprinnelige pilen flytter seg ikke. Dette kommer av at det opprinnelige scriptet setter inn et spesialtegn i en <span> i headingen når den sorterer. Heldigvis setter scriptet også en klasse på headingen. Dermed kan vi bruke heading-klassen til å modifisere utseendet på headingen, og så bare skjule span-elementet som settes inn av scriptet.

thead th.sorttable_sorted, thead th.sorttable_sorted_reverse {
    background: url(blue_arrow_down.gif) top right repeat-x #7d93b2;
}

thead th.sorttable_sorted_reverse {
    background-image: url(blue_arrow_up.gif);
}

#sorttable_sortfwdind, #sorttable_sortrevind { display: none; }

I samme slengen kan vi fikse sorteringen av dato-kolonnen. I de tilfellene der sorttable.js ikke sorterer tabellen riktig på egenhånd kan vi hjelpe den med å fortelle hvilken datatype kolonnen skal sorteres som. sorttable.js shipper med følgende innebygde typer: numeric, alpha, ddmm, and mmdd.

Disse kan bentyttes ved å sette class="sorttable_<type>" på heading-cellen til kolonnen. Jeg oppdaterer dermed tabellen som følger:

<table class="sortable" summary="...">
    <caption>Gambling blant personer</caption>
    <thead>
        <tr>
            <th scope="col">Person</th>
            <th scope="col" class="sorttable_ddmm">Dato</th>
            <th scope="col">Innsats</th>
            <th abbr="Spill" scope="col">Antall spill</th>
            <th scope="col">Gevinst</th>
        </tr>
    </thead>
    ...
</table>

Resultatet kan sees her.

Zebra-striper etter sortering

Når tabellen er ferdig sortert er Zebra-stripene bare rot. Dette må fikses. Scriptet til mr. Langrige har desverre ikke noen kroker for å behandle tabellen etter at den er sortert, så vi må bygge det inn selv. Tanken er at når tabellen er sortert kjører den vår opprinnelige Zebra-kode på nytt for å re-stripe tabellen.

Først noen små endringer på det opprinnelige scriptet. Det opprinnelige scriptet satte annenhver rad med klassenavn "alt". Vi må justere scriptet så det også på annenhver rad fjerner dette klassenavnet, slik at scriptet fungerer også andre gangen det kjøres (så ikke alle radene blir "alt"). Deretter setter vi scriptet til en navngitt funksjon som vi kan bruke flere enn ett sted:

function zebraTable(e) {
    if (!document.getElementById || !document.createElement)
        return;

    for (var i = 0, table = null; (table = document.getElementsByTagName('table')[i]); i++) {
        var tbodies = table.getElementsByTagName('tbody');
        var tbody = tbodies.length > 0 ? tbodies[0] : table;

        for (var j = 0, row = null; (row = tbody.getElementsByTagName('tr')[j]); j++) {
            row.className = j % 2 == 0 ? 'alt' : '';
        }
    }
}

window.onload = zebraTable;

Neste skritt er å legge inn en krok i sorttable.js som kaller scriptet vårt. Siden det kan være ønskelig med en litt mer generell krok, så legger vi inn en sjekk på om det finnes en sorttable-callback, og kaller den dersom den finnes. Denne må inn på tre steder i sorttable.js: linje 105, 119 og 163 (dette er linjenummerne scriptet returnerer fra når tabellen er sortert):

if (window.onSorttableSorted) onSorttableSorted.call();

Deretter legger vi i vårt script inn følgende (denne må settes før sorttable.js inkluderes, ellers vil den ikke bli kalt):

var onSorttableSorted = zebraTable;

Voila! Resultatet kan sees her.

Der har du en tabell med relativt pen styling og god sorterings-funksjonalitet samtidig som den underliggende HTML-en er full av nyttig struktur og validerer. Hva mer kan man ønske seg fra en tabell?

Muligens relatert

2006 - 2012 Christian Johansen Creative Commons Lisens