Hopp til innholdet

cjohansen.no

Vis/skjul-definisjoner med Javascript

Lørdag denne helgen så jeg litt på forskjellige måter å kode definisjoner i HTML på. Idag tar jeg for meg definisjonslister spesifikt og legger til litt Javascript for å lage en kollaps/ekspander-liste med definisjoner.

Aktuelle elementer

Dagens innlegg befatter seg med <dl>, <dt> og <dd>.

Resultatet

Funksjonaliteten som skal bygges med Javascript her idag er å gjøre en definisjonsliste om til en liste med klikkbare termer som ved klikk åpner den tilhørende forklaringen. Et nytt klikk lukker så forklaringen igjen. Dette som kan være nyttig for eksempelvis ordforklaringer og lignende der listen i utgangspunktet er veldig lang. Effekten kan sees her.

Scriptet

window.onload = function() {
    if (!document.getElementById || !document.createElement) return;

    for (var i = 0, dl = null; (dl = document.getElementsByTagName('dl')[i]); i++) {
        var dd = dl.getElementsByTagName('dd');
        var dt = dl.getElementsByTagName('dt');

        for (var j = 0; j < dt.length; j++) {
            hideDef(dt[j], dd[j]);
        }
    }
}

function showDef(dt, dd) {
    dt.className = 'open';
    dt.onclick = function(e) { hideDef(dt, dd); };
    dd.className = '';
}

function hideDef(dt, dd) {
    dt.className = 'closed';
    dt.onclick = function(e) { showDef(dt, dd); };
    dd.className = 'hidden';
}

Antagelser

Før vi går igang med gjennomgangen bør det nevnes at jeg her ikke har tatt høyde for definisjoner der det er flere termer og/eller definisjoner. Scriptet slik det står her er forsøkt holdt enkelt og fungerer dermed kun på "én dt per én dd"-lister.

Forbedringspotensiale

Som med forleden dags definisjonsscript er det her rom for forbedringer. Vi er igjen utfor den noe uheldige bruken av window.onload. I tillegg kunne denne snutten med hell ha vært skrevet noe mer elegant som et Javascript-objekt.

Skritt for skritt

Den første delen av scriptet legger inn funksjonen vår for kjøring når siden laster og sjekker at nettleseren støtter DOM.

for (var i = 0, dl = null; (dl = document.getElementsByTagName('dl')[i]); i++) {
   var dd = dl.getElementsByTagName('dd');
   var dt = dl.getElementsByTagName('dt');

   for (var j = 0; j < dt.length; j++) {
       hideDef(dt[j], dd[j]);
   }
}

Denne snutten henter alle <dl>-elementer på siden, og kjører så gjennom alle <dt>/ <dd>-par i listen og gjemmer definisjonen (gjennom hideDef-kallet). Slik koden nå fungerer kunne man ha klart seg med en løkke som hentet alle parene direkte, uten å gå via selve liste-elementene.

function hideDef(dt, dd) {
    dt.className = 'closed';
    dt.onclick = function(e) { showDef(dt, dd); };
    dd.className = 'hidden';
}

Selve funksjonaliteten i scriptet er løst via klassenavn. Via CSS gis disse klassene riktig stil slik at koden fungerer slik vi ønsker. Dette er et eksempel på hvordan man koder med lagene (struktur, presentasjon og interaksjon) godt adskilt. Jeg kunne også ha kodet stiler direkte i scriptet, men presentasjon er CSS sin oppgave, ikke Javascript.

Vi ser også at hideDef-funksjonen setter klikk-eventen på termen til å være shofDef. Tilsvarende setter showDef klikk-eventen til hideDef, og slik har vi det gående:

function showDef(dt, dd) {
    dt.className = 'open';
    dt.onclick = function(e) { hideDef(dt, dd); };
    dd.className = '';
}

Funksjonene er altså rett og slett det motsatte av hverandre; de "toggler" klassene av og på samt bytter klikk-event på termen.

CSS

Følgende er den relevante CSS-en for å få dette til å fungere:

dt.closed, dt.open {
    color: #00c;
    cursor: pointer;
    text-decoration: underline;
}

dt.closed:hover, dt.open:hover {
    text-decoration: none;
}

dt.closed:before { content: "+ "; }
dt.open:before { content: "- "; }
.hidden { display: none; }

Som noen kanskje vil se direkte ut av dette så vil ikke Internet Explorer støtte dette fullt ut (nei, ikke sjuern heller). Grunnen er bruken av content-egenskapen som ikke støttes. Denne brukes til å vise en + foran lukkede termer (for å indikere at et klikk vil åpne forklaringen) og en - foran åpne termer (som indikerer at forklaringen kan lukkes).

I den virkelige verdenen

Scriptet over er veldig simpelt og fungerer godt til å illustrere hva som skjer. Skulle jeg ha brukt dette i den virkelige verden ville jeg nok ha gjort noen endringer. For det første er det forskjell på å sette klikk-event og stile noe med blå tekst og understrek mot det å faktisk lage en lenke. Dette vil du oppdage dersom du går til eksempelsiden min og prøver å bruke tab-tasten gjennom siden. Du vil ikke tabbe forbi definisjonene fordi disse ikke er skikkelige lenker.

Så skulle jeg bruke dette ville jeg (i scriptet, ikke rett i kilden):

Dette har jeg implementert i versjon 2 av scriptet: http://www.cjohansen.no/dl/vis_skjul2.html, enjoy!

Kommentarer

Grunnet mye spam og mangel på god nok spam-beskyttelse har jeg sett meg nødt til å midlertidig stenge tilbakemeldinger på dette innlegget. Dine innspill er hjertelig velkomne på de fleste andre innlegg, eller på christian (a) cjohansen.no

Muligens relatert

2006 - 2012 Christian Johansen Creative Commons Lisens