DOM JavaScript billedgalleri

Et moderne billedgalleri.

Billedgalleriet med sommerhuset (Billedgallerier) konstruerede jeg for en halv snes år siden. Det er senest moderniseret for to-tre år siden, da jeg ændrede en tabelopsætning af siden til et CSS-layout.

Tiden er løbet fra denne måde at gøre det på. Moderne JavaScript gør det muligt for os at undgå at vise de store billeder i hver deres vindue. De bør i stedet vises på samme side som småbillederne er på.

I moderne JavaScript bør vi også undgå at bruge inline event handlers, vi bør sikre, at applikationen også fungerer for dem, der hellere bruger tastaturet end en mus, og vi bør sikre, at funktionaliteten er til stede også i browsere med manglende eller mangelfuld implementering af JavaScript fortolkeren.

Det moderne billedgalleri

Et sådant finder du i eksemplet Up, up in the Sky, hvis udgangspunkt er præsentationen af intet mindre luftfartens historie. Præsentationen består af 4 småbilleder af forskellige luftfartsmuligheder. Klikkes der på ét af disse, vises billedet i en større udgave i ruden til venstre for småbillederne.

En konstruktionsopgave af denne karakter omfatter 3 delopgaver:

  1. Sidens opbygning i html
  2. Sidens stylesheet-formatering
  3. Et eksternt script, der håndterer klik-events og sørger for at vise de store billeder.

Hvis du vil have alle detaljer omkring netop denne eksempelside, må du bruge browserens Vis-kilde-funktion. JavaScript og CSS-kode er indlejret i eksempelsiden, kun billederne er eksterne i forhold kildekoden. Her gennemgår jeg kun de dele, der er relevante i forhold til siden set som et billedgalleri.

Den grundlæggende kode, der alene omfatter HTML-kode, stylesheet og JavaScript til dette eksempel har jeg pakket ned i en zip-fil, du kan downloade her: DOM JavaScipt billedgalleri.

Html-delen

Udgangspunktet for et billedgalleri er altid en serie småbilleder. I det her omtalte eksempel rummes hvert småbillede i et listepunkt og udgør et klikbart link:

<div id="links">
<ul id="pixgalleri">
<li>
<a href="/galleri/eksempler/res/00010002.jpg" 
title="Dragefly">
<img src="res/00010002small.jpg" width="65" height="96" 
alt="Dragefly" /></a>
</li>
...
</div>

Det synes klart, at dersom der ikke var et JavaScript, der reagerede på et klik på et af småbillederne, ville et sådant klik føre til, at en ny webside, indeholdende det store billede, ville blive vist. Det vil sige, at funktionaliteten er bevaret selv for JavaScript-lamme browsere.

Småbilledet er her en reduceret udgave af det større billede. Jeg kan ikke nok advare imod blot at genbruge det større billede og reducere det ved at sætte en passende mindre width og height på småbilledet. Det øger overførselstiden betragteligt.

Du kan også per rygmarv være fristet til at lave den mindre udgave som en gif-fil, men det vil også oftest være forkert, når det drejer sig om fotos. I dette tilfælde fylder en jpg-udgave af småbilledet typisk under det halve af en gif-udgave.

Stylesheet'et

CSS-filen, der formaterer billederne, er følgende:

#links ul {
  list-style:none;}
#links li {
  line-height:120%;
  display:inline;
  margin-left:5px;}
#pix  {
  width:185px;
  height:300px;
  float:left;
  position:relative;}
#pix img {
  width:185px;
  height:274px;}

Det store billede til venstre udgør en såkaldt pladsholder. Billedet rummes i en div med samme mål som billederne, og der er nu scriptets opgave at udskifte indholdet af img src-attributtens værdi ved et klik på et af småbillederne.

Småbillederne er indsat som listeelementer, der har fået display-værdien inline. Det betyder, at elementerne stille sig op på en række ved siden af hinanden, indtil der ikke er plads til flere. Er der flere småbilleder end der er plads til i første række, startes blot på en ny række. Det betyder, at du kan have ganske mange småbilleder – en 15-18 stykker alene på den begrænsede plads jeg har afsat i mit eksempel.

Scriptet

Alle events skal håndteres af det eksterne JavaScript. Der er ingen eventhandlere på siden, så vi benytter os af DOM event-fangst.

Da vi ikke kan manipulere med elementerne, før siden er indlæst, initieres elementerne ved hjælp af onload evenhandleren.

addLoadEvent(prepareGallery);

Ved hjælp af addLoadEvent() kan vi føje et vilkårligt antal initieringsprocedurer til siden. Denne funktion tager også vare på de forskelle, der er på Internet Explorers event-model og W3C's eventmodel:

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

Nu resterer at oprette prepareGallery-funktionen, der skal identificere applikationens forskellige elementer og knytte event handlere til disse:

function prepareGallery() {
  if (!document.getElementsByTagName) return false;
  if (!document.getElementById) return false;
  if (!document.getElementById("pixgalleri")) return false;
  var galleri = document.getElementById("pixgalleri");
  var links = galleri.getElementsByTagName("a");
  for ( var i=0; i < links.length; i++) {
    links[i].onclick = function() {
      return showPic(this);
	}
  }
}

De første tre linjer standser scriptet, hvis de tre betingelser ikke er opfyldt: Browseren skal kunne gennemtrawle DOM træet og finde elementer (noder) som de er beskrevet i W3C's dokumentobjektmodel og elementet pixgalleri skal findes på siden.

Den variable links er en slags Array af alle a-elementer i elementet pixgalleri. Løkken gennemløber dette Array og knytter onclick event handleren til hvert enkelt element i Array'et via en anonym funktion, der udløser showPic()-funktionen for det element, der aktuelt klikkes på.

“Vis billede”-funktionen

Denne funktion er selvfølgelig nøglefunktionen i et billedvisningsprogram, og er grundlæggende meget ligetil:

function showPic(whichpic) {
  var source = whichpic.getAttribute("href");
  var placeholder = document.getElementById("pladsholder");
  placeholder.setAttribute("src",source);

Som vi så i prepareGallery-funktionen udløser et klik på et småbillede showPic-funktionen med this nøgleordet, der udgør en konkret reference til det aktuelle objekt. Den variable source henter værdien af dette objekts href-attribut – det vil sige linket til det store billede. Denne værdi sættes i sidste linje ind som src-værdi for pladsholder-billedelementet.

Kigger du på kildekoden til eksemplet vil du se, at der foregår en hel del mere.

  1. Første linje er
    if (!document.getElementById("pladsholder")) return true;
    
    Denne linje sørger for, at linket fungerer, selvom der ikke er noget pladsholder-element. I så fald indlæses en ny side med det store billede som kilde.
  2. Yderligere et kig i kildekoden til eksemplet vil vise, at jeg har indsat et afsnitselement med en id="beskrivelse". Når siden indlæses er tekstindholdet af dette element “Vælg et billede”.
    if (!document.getElementById("beskrivelse")) return false;
    if (whichpic.getAttribute("title")) {
      var text = whichpic.getAttribute("title");
    } else {
      var text = "";
    }
    
    Denne del af scriptet konstaterer først om dette element findes. Dernæst undersøges om dette element har en title-attribut, og hvis det er tilfældet indsættes denne i den variable text. Sidste del af scriptet har til formål at indsætte denne variable i elementet #beskrivelse:
    var description = document.getElementById("beskrivelse");
    if (description.firstChild.nodeType == 3) {
      description.firstChild.nodeValue = text;
    }
    

Elegant og tilgængeligt

Jeg synes der er en betydelig elegance over denne applikation, i hvert fald hvis vi koncentrerer os om det konstruktionsmæssige: Du får et billedvisningsprogram, der fungerer selv om du kun laver HTML-koden. Det fungerer også ved tastaturnavigation. Tabuler frem til det ønskede småbillede og tast Enter, så dukker det store billede op på den ønskede plads. Er der fejl i scriptet, indlæses en ny side med det store billede, og browserens tilbageknap bringer læseren tilbage til galleriet.

Denne side er senest opdateret: 31. October, 2009