Bygg ett eget fotoalbum med JavaScript och CSS
Att bygga ett fotoalbum till din hemsida är inte svårt. Med några enkla knep gör du snabbt ett snyggt och dynamiskt fotoalbum som fungerar i alla lägen.
Målen
Med rätt teknik är det inte svårt att bygga ett fotoalbum till din hemsida. För mig är det viktigt att fotoalbumet uppfyller dessa krav:
Det ska:
- se inbjudande ut
- vara enkelt att använda
- gå snabbt att visa bilder
- vara enkelt för mig att lägga till nya bilder
- fungera i alla webbläsare
Att det ska se inbjudande ut är givetvis i allra högsta grad en smaksak. Mina smaklökar gillar det enkla, rena och nästan övertydliga. Det hänger ihop med att det ska vara enkelt att förstå. När jag visar bilder på nätet är det ofta för familjemedlemmar. Mina föräldrar är inte speciellt datorvana, så det måste vara väldigt enkelt. Med CSS kan vi presentera albumet som vi vill.
Något som jag själv ogillar med fotoalbum är att behöva klicka på en bild, klicka Bakåt-knappen för att komma tillbaka till bildlistan, välja nästa bild och fortsätta så. Jag föredrar att när jag väljer en bild så uppdateras bara bildvisningen, men allt annat är kvar. Detta löser vi med JavaScript och lite DOM Scripting.
Det måste vara riktigt riktigt enkelt för mig att lägga till nya bilder. Annars kommer jag aldrig mig för att uppdatera det. Helst ska jag bara behöva lägga upp en bild, skapa en länk till den och skriva en beskrivning av bilden. Resten ska sköta sig själv.
Slutligen måste det fungera i alla webbläsare. Albumet måste fungera även om man inte har en webbläsare som stöder CSS eller JavaScript, eller om man av en eller annan anledning valt att stänga av dessa funktioner.
Så här kommer mitt färdiga album att se ut.
Till vänster är länkar till alla bilder som finns i mitt album. När jag klickar på en länk så visas bilden stort till höger och beskrivningstexten byts automatiskt ut utan att ladda om hela sidan.
Om användaren inte har JavaScript aktiverat fungerar länkarna ändå, men bilden visas på en egen sida. Det fungerar även att navigera med bara tangentbord.
För att lägga till nya bilder så lägger jag till en till länk. Resten sköter sig själv.
Förkunskaper
För att helt och fullt kunna ta till dig alla delar av den här artikeln behöver du ha grundläggande kunskaper om (X)HTML, CSS och lite JavaScript. Även om du inte kan speciellt mycket om detta kan du ändå ha nytta av artikeln och använda koden på dina egna sidor.
HTML-koden
HTML-koden i albumet är väldigt enkel. Den innehåller en rubrik, en instruktion, en punktlista med länkar och utrymme för storbild och bildbeskrivning.
<head>
<title>Mitt fotoalbum</title>
</head>
<h1>Mitt fotoalbum</h1>
Välkommen till mitt fotoalbum på nätet.
Klicka på länkarna för att se bilden.
</p>
- Humla</a></li>
- Rep</a></li>
- Stenar</a></li>
- Fjäril</a></li>
- Prästkragar</a></li>
</ul>
Välj en bild ovan</p>
</div>
</body>
</html>
I HTML-koden finns ingen kod som beskriver utseendet. Det finns heller inget JavaScript som bestämmer hur sidan ska fungera. I webbläsaren ser det nu ut så här:
Så här skulle sidan se ut om användaren inte hade stöd för CSS. Inte världens snyggaste kanske, men väldigt tydlig. Om användaren klickar på en länk laddas bilden in och denna sida försvinner. Kanske inte världens roligaste, men det fungerar trots att det inte är något JavaScript. Det skulle till och med fungera i en mobiltelefon.
Som du kan se i koden har vissa element id-attribut och class-attribut.
- Stenar
- Kör kod när sidan laddas. För att verkligen kunna göra nästa steg behöver vi veta när HTML-sidan laddats klart och då köra vår egen kod.
- Kidnappa bild-länkarna. Detta innebär att istället för att länken ska göra den normalt gör, dvs. ladda hela bilden i en ny sida, ska vårt JavaScript ta kontroll över bildvisningen. Detta gör att vi slipper lägga in onclick på varje enskild länk.
- Visa bilder utan att ladda om sidan. Istället för att hela sidan behöver laddas om ska endast img-elementet ändras samt elementet för bildbeskrivningen. Detta är i princip exakt samma som funktionen showImage vi redan gjort.
- Humla</a></li>
- Rep</a></li>
- Stenar</a></li>
- Fjäril</a></li>
- Prästkragar</a></li>
</ul>
Det första JavaScriptet behöver göra är att hitta ul-elementet. Tack vare att vi gett det ett unikt id kan vi göra det med funktionen document.getElementById(id).När vi väl har ul-elementet kan vi hämta en lista på alla a-element som ligger under ul-elementet. Med funktionen parentElement.getElementsByTagName(”a”) får vi alla a-element som är barn till det element som parentElement hänvisar till.
När vi har en lista med länkar ska vi loopa igenom länk för länk och skapa en händelsehanterare för onclick-händelsen. Denna händelsehanterare kommer visa bilden och beskrivningen samt förhindra att länken öppnar bilden i en ny sida som den skulle gjort med href-attributet.
JavaScriptet för detta ser ut så här:
function hookupGallery()
{
if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
var gallery = document.getElementById("FotoAlbum")
if(!gallery) return false;
var links = gallery.getElementsByTagName("a");
if(!links) return false;
for(var i = 0; i < links.length; i++)
{
links[i].onclick = function() {
showImage(this);
return false;
};
}
}
För tydlighetens skull går vi igenom varje del för sig.if(!document.getElementById) return false;
if(!document.getElementsByTagName) return false;
Precis som förut vill vi försäkra oss om att användaren har en webbläsare som stöder getElementById och getElementsByClassName. Om inte så avslutar vi funktionen direkt.var gallery = document.getElementById("FotoAlbum")
if(!gallery) return false;
Denna kod hämtar en referens till ul-elementet med id FotoAlbum och sparar det i en variabel som heter gallery. Den andra raden försäkrar oss om att det verkligen fanns. Gjorde det inte det så avslutar vi funktionen direkt.
var links = gallery.getElementsByTagName("a");
if(!links) return false;
Denna kod hämtar ut alla a-element som ligger under elementet vi har en referens till I variabeln gallery. Även här avslutar vi funktionen om det inte gick bra.
for(var i = 0; i < links.length; i++)
{
links[i].onclick = function() {
showImage(this);
return false;
};
}
Detta är den kod som verkligen gör jobbet. För varje länk som getElementsByTagName hittade lägger vi till onclick-händelser. Detta är vår nya motsvarighet till att lägga ett onclick-attribut på varje a-element.function() {
showImage(this);
return false;
};
Det mesta från detta känner du kanske igen från vårt onclick-attribut. Det gör exakt samma sak. Det vi gjort mer här är att kapsla in det i en funktion som körs när man klickar på länkarna. Funktioner utan namn kallas anonyma funktioner och är väldigt användbart, men lite överkurs just nu.Knyta ihop säcken
Nu återstår bara att se till att funktion hookupGallery verkligen körs när sidan laddats klart. Därefter ska vi även länka in JavaScript-filen i HTML-sidan.
Lägg till denna kod sista i JavaScript-filen:
addLoadEvent(hookupGallery);
Den ser till att lägga till vår funktion körs när sidan laddas, men utan att förstöra andra eventuella script som behöver göra samma sak.I HTML-sidan lägger du till nedanstående mellan
och - Rep</a></li>
</ul>
Välj en bild ovan</p>
</div>
Class-attributen är för att kunna formge sidan med CSS. ID-attributen är för att vi ska kunna haka på JavaScript och ändra funktionaliteten om man har JavaScript. Med hjälp av ID-attributen kan vi påverka ett enskilt element med JavaScript-kod.>> Ladda ned Version 1 av Fotoalbumet
JavaScript and the Temple of DOM
Att ändra delar av sidan med JavaScript kallas för DOM Scripting. ”DOM” står för Document Object Modell och en beskriver hela sidan som en trädstruktur och gör att man kan programmera mot den.
På DOM:en finns olika objekt för att till exempel komma åt fönstret (window), med objektet document kommer man åt allt innehåll och det går även att jobba mot varje enskilt element i sidan.
Alla objekt har olika egenskaper som kan hämtas ut eller ändras. Egenskaperna matchar alla attribut som ett HTML-element kan ha, t ex href på en länk eller src på en bild. Med DOM:en kan du även ändra annat, som t ex ett elements innehåll som kan ändras med egenskapen innerHTML.
För att hjälp till att jobba med DOM:en finns det även metoder, vilket är som funktioner kan gör olika saker. Två metoder som används väldigt mycket är getElementById och getElementsByTagName. Metoden getElementById hämtar ett element med ett visst id så att det går att programmera mot det, t ex för att ändra texten i bildbeskrivningen. Metoden getElementsByTagName hämtar en lista med element av en viss typ, t ex alla länkar.
DOM:en har också olika händelser. Händelser kan vara t ex när sidan har laddats klart, när användaren klickar på en länk, när fönstret ändrar storlek, när man trycker en tangent och många fler händelser. Detta kallas events på programmeringsspråk och är ett mycket viktigt koncept inte minst för webbsidor.
För att lära dig mer om DOM Scripting rekommenderar jag mycket varmt Jeremy Kieths bok DOM Scripting – Web Design with JavaScript and the Document Object Model.
Klicka på mig!
För att snabbt få fotoalbumet att fungera kan vi lägga på JavaScript direkt på HTML-koden. Vi ska fånga upp när användaren klickar på en länk och köra ett JavaScript som byter ut bilden.
I sidhuvudet i HTML-filen, mellan
och kan du lägga in denna kod:function showImage(selectedImage)
{
document.getElementById("StorBild").src = selectedImage.href;
document.getElementById("StorBild").alt = selectedImage.title;
document.getElementById("BildBeskrivning").innerHTML = selectedImage.title;
}
</script>
På varje a-element kan du lägga in denna kod:
Onclick-attributet bestämmer vilken kod som ska köras när användaren klickar på länken. Detta är händelsehanteraren för denna länk. Koden showImage(this) hänvisar till funktionen vi lade in iNågot som är bra med detta är att om man inte har JavaScript aktiverat så fungerar href-länken precis som vanligt. JavaScriptet nedgraderar sig själv på ett snyggt sätt. (För mer avancerade läsare: detta är bättre än href=”javascript:void showImage(this)” just därför att man inte förstör sidan för användare som inte har JavaScript aktiverat.)
Nu ska vi titta lite extra på funktionen vi lade in i
-elementet.</script>
Denna kod påbörjar ett helt nytt avsnitt med JavaScript-kod. Attributet type bestämmer vilken typ av script det är vi använder.function showImage(selectedImage)
{
}
Detta är funktionens namn och argument. Namnet showImage kan vara precis vad vi vill. Jag hade lika gärna kunna döpt funktionen till ”apa”, men det bästa är givetvis med namn som känns relevanta. Namngivningen i JavaScript kallas kamelnotation, och innebär att namn som består av flera ord inleds med liten bokstav, men varje nytt ord får stor begynnelsebokstav, t ex dettaÄrEttJättelångtNamn.Inom parantes står argument till funktionen, dvs. information som funktioner behöver för att göra sitt jobb. För varje onclick på länkarna skickade vi in argumentet this, vilket hänvisade till själva länken. När användaren klickar på länken kommer argumentet selectedImage innehålla hänvisningen till this, vilket i sin tur hänvisar till länk-elementet.
document.getElementById("StorBild").src = selectedImage.href;
Denna kod hämtar ut det vi angett som filnamn på länken, dvs. href-attributet, och sätter det som filnamn på den stora bilden. Den stora bilden gav vi id StorBild. Med document.getElementById(”StorBild”) hämtar vi en referens till denna bild.
document.getElementById("StorBild").alt = selectedImage.title;
Denna kod gör nästan samma sak som den föregående. Enda skillnaden är att den hämtar bildbeskrivningen och sätter den som beskrivning på den stora bilden.
document.getElementById("BildBeskrivning").innerHTML = selectedImage.title;
Slutligen så sätts även bildens beskrivning som innehåll i p-elementet för bildbeskrivning. Även här har elementet för bildbeskrivning ett unikt id som vi kan utnyttja här. Egenskapen innerHTML sätter den HTML-kod som ska finnas mellan start- och slut-element, dvs. innehållet mellanoch
.
>> Ladda ned Version 2 av Fotoalbumet
Var inte så påträngande!
Det finns dock ett problem med ovanstående kod. Den förutsätter en massa saker som man inte kan förutsätta. Dessutom så blandar den innehåll och funktion, vilket inte är att rekommendera. Och att behöva lägga in koden för onclick på varje länk känns rätt enformigt och kladdar ned HTML-koden.
Det är rekommenderat att lägga all JavaScript i en helt egen fil på precis samma sätt som det är rekommenderat att göra med CSS-filer.
Att hålla HTML-koden helt ren från JavaScript och i efterhand haka på kod kallas för ”unobtrusive JavaScript”. Det betyder att den inte lägger sig i sidans innehåll. Vi vill ju kunna skilja på innehåll, utseende och funktion så gott det bara går. Det garanterar också att sidan fungerar korrekt för användare som inte har JavaScript aktiverat eller stöd för JavaScript.
All JavaScript-kod lägger vi i en helt egen fil. Denna fil får heta Galleri.js. Filändelsen js bör du alltid ha på JavaScript-filer. Denna fil ska vi sedan länka in i HTML-sidan.
Jag vill att koden ska:
Funktionen för att visa bilder
Börja med att flytta in funktionen showImage i den nya JavaScript-filen. Vi kommer göra några små ändringar i den, men den går ändå bra att återanvända. I HTML-filen ska det inte finnas något JavaScript alls.
För att undvika att få tråkiga felmeddelanden så ska vi försäkra oss om att HTML-koden innehåller de element vi behöver. Detta kan vi göra med två enkla villkorssatser. När funktionen är klar ska den se ut så här:
function showImage(selectedImage)
{
if(!document.getElementById) return true;
if(document.getElementById("StorBild"))
{
document.getElementById("StorBild").src = selectedImage.href;
document.getElementById("StorBild").alt = selectedImage.title;
}
if(document.getElementById("BildBeskrivning"))
{
document.getElementById("BildBeskrivning").innerHTML = selectedImage.title;
}
return false;
}
Det som är nytt är fetmarkerat.if(!document.getElementById) return false;
Denna kod försäkrar oss om att webbläsaren har en version av JavaScript som faktiskt stöder metoden getElementById. Om den inte har det returnerar vi true, vilket gör att länkens vanliga beteende ändå körs.
if(document.getElementById("StorBild"))
Denna kod kontrollerar att det verkligen finns ett element med id StorBild innan vi försöker förändra det på något sätt. Det samma gäller för kontrollen om elementet med id BildBeskrivning finns.return false;
Slutligen returnerar vi false vilket gör att länkens normala beteende inte körs, dvs. vi länkas inte iväg till en ny sida där bilden laddas.Köra kod när sidan laddas
För att verkligen kunna haka på vår egen funktionalitet på HTML-koden behöver vi vänta tills hela sidan laddats klart. Först då kan vi vara säkra på att alla bildlänkar finns. Att fånga upp när sidan laddats klart går att göra med händelsen (eventet) window.onload.
En nackdel med onload-händelsen är dock att den endast kan köra en enda funktion. Det går inte att ha flera händelsehanterare (eventhandlers) för samma händelse.
Vi behöver visserligen bara köra en händelsehanterare, men du vill att andra JavaScript också ska kunna fungera trots att vi bygger ett fotoalbum. Därför kan du inte bara sno åt dig onload-händelsen. Detta är ganska lätt att fixa med ett enkelt script.
function addLoadEvent(handler)
{
var oldonload = window.onload;
if(typeof window.onload != "function")
{
window.onload = handler;
}
else
{
window.onload = function() {
oldonload();
handler();
};
}
}
Den här funktionen kontrollerar först om det redan finns någon händelsehanterare för window.onload. Om det inte finns så läggs vår funktion till som händelsehanterare. Om den redan finns skapas en ny händelsehanterare som först kör den gamla funktionen och sedan vår nya. Det fina är att den fungerar oavsett hur många gånger den anropas.För att använda funktionen skriver man så här:
addLoadEvent(minEgenOnloadHanterare);
Där ”minEgenOnloadHanterare” är namnet på en JavaScript-funktion. Du kan dock vänta med att lägga in detta en liten stund.Kidnappa alla bildlänkar
Nästa steg är att hitta alla länkar med bilder och istället för att de ska visa bilden på en ny sida ska JavaScript köras som visar bilden direkt.
HTML-koden för bildlänkarna bestod av en punktlista med länk-element. (Observera att jag tagit bort alla onclick igen.)
- Rep</a></li>