Lær å gjøre nettsider interaktive med klikk, tastatur og skjemahendelser.
Hendingshandtering og brukarinteraksjon
I førre kapittel lærte vi å endre nettsida med JavaScript. Men endringane skjedde berre når koden køyrde ved sidelasting. For å skape verkeleg interaktive nettsider treng vi å reagere på handlingane til brukaren – klikk, tastetrykk, muserørsler og skjemainnsending. Dette vert kalla hendingshandtering (event handling).
Hendingssystemet i JavaScript fungerer etter eit enkelt prinsipp: du fortel nettlesaren «når denne hendinga skjer på dette elementet, køyr denne koden». Nettlesaren ventar tolmodig og køyrer koden din berre når hendinga faktisk inntreff. Dette er ein asynkron programmeringsmodell – koden køyrer ikkje i rekkjefølgje frå topp til botn, men som respons på hendingar.
Ei hending er ei handling eller hending som skjer i nettlesaren og som JavaScript kan reagere på. Døme er museklikk (click), tastetrykk (keydown), muserørsle (mouseover), siderulling (scroll), lasting av sida (load) og innsending av skjema (submit). Hendingar er grunnlaget for all brukarinteraksjon på webben.
Den tilrådde måten å handtere hendingar på er med addEventListener():
const knapp = document.querySelector("#minKnapp");
knapp.addEventListener("click", function () {
console.log("Knappen ble klikket!");
});addEventListener tek to argument:
1. Hendingsnamnet som ein streng (f.eks. "click")
2. Ein funksjon som vert køyrd når hendinga inntreff (vert kalla ein callback-funksjon)
Du kan òg bruke pilfunksjonar:
knapp.addEventListener("click", () => {
console.log("Klikk registrert!");
});Eller referere til ein namngitt funksjon:
function handterKlikk() {
console.log("Funksjon ble kalt!");
}
knapp.addEventListener("click", handterKlikk);Vanlege hendingstypar
| Hending | Skildring |
|---|---|
click | Museklikk på elementet |
dblclick | Dobbeltklikk |
mouseover | Musa vert flytta over elementet |
mouseout | Musa forlèt elementet |
keydown | Ein tast vert trykt ned |
keyup | Ein tast vert sleppt |
input | Verdien i eit inputfelt vert endra |
submit | Eit skjema vert sendt inn |
change | Eit skjemaelement endrar verdi |
scroll | Sida eller eit element vert rulla |
load | Sida eller ein ressurs er ferdig lasta |
Når ei hending inntreff, sender nettlesaren automatisk eit event-objekt til callback-funksjonen. Dette objektet inneheld nyttig informasjon om hendinga:
const knapp = document.querySelector("#minKnapp");
knapp.addEventListener("click", function (event) {
console.log("Type:", event.type); // "click"
console.log("Mål:", event.target); // Elementet som ble klikket
console.log("X-posisjon:", event.clientX); // Musens x-koordinat
console.log("Y-posisjon:", event.clientY); // Musens y-koordinat
});Event-objektet for tastehendingar
document.addEventListener("keydown", function (event) {
console.log("Tast:", event.key); // F.eks. "Enter", "a", "Escape"
console.log("Kode:", event.code); // F.eks. "Enter", "KeyA", "Escape"
console.log("Shift holdt:", event.shiftKey); // true/false
console.log("Ctrl holdt:", event.ctrlKey); // true/false
});event.target – identifiser kjelde-elementet
event.target refererer til det elementet som faktisk utløyste hendinga. Dette er spesielt nyttig når du har mange like element:
const knapper = document.querySelectorAll(".farge-knapp");
knapper.forEach(knapp => {
knapp.addEventListener("click", function (event) {
const valgtFarge = event.target.dataset.farge;
document.body.style.backgroundColor = valgtFarge;
});
});Med tilhøyrande HTML:
<button class="farge-knapp" data-farge="lightblue">Blå</button>
<button class="farge-knapp" data-farge="lightgreen">Grønn</button>
<button class="farge-knapp" data-farge="lightyellow">Gul</button>Eit av dei viktigaste bruksområda for hendingshandtering er skjemavalidering – å sjekke at brukaren har fylt inn gyldige data før dei vert sende til tenaren.
Hindre standard åtferd
Når eit skjema vert sendt inn, lastar nettlesaren normalt sida på nytt. For å handtere innsendinga med JavaScript må vi stoppe denne åtferda:
const skjema = document.querySelector("#registrering");
skjema.addEventListener("submit", function (event) {
event.preventDefault(); // Stopp sidelasting!
// Hent verdier fra skjemaet
const navn = document.querySelector("#navn").value;
const epost = document.querySelector("#epost").value;
console.log("Navn:", navn);
console.log("E-post:", epost);
});Komplett skjemavalidering
<form id="pamelding">
<label>Navn: <input type="text" id="navn"></label>
<label>E-post: <input type="email" id="epost"></label>
<label>Alder: <input type="number" id="alder"></label>
<button type="submit">Send inn</button>
<div id="feilmeldinger"></div>
</form>const skjema = document.querySelector("#pamelding");
skjema.addEventListener("submit", function (event) {
event.preventDefault();
const navn = document.querySelector("#navn").value.trim();
const epost = document.querySelector("#epost").value.trim();
const alder = Number(document.querySelector("#alder").value);
const feilDiv = document.querySelector("#feilmeldinger");
const feil = [];
// Valider navn
if (navn === "") {
feil.push("Navn er obligatorisk.");
} else if (navn.length < 2) {
feil.push("Navnet må ha minst 2 tegn.");
}
// Valider e-post (enkel sjekk)
if (!epost.includes("@") || !epost.includes(".")) {
feil.push("Ugyldig e-postadresse.");
}
// Valider alder
if (isNaN(alder) || alder < 13 || alder > 120) {
feil.push("Alder må være mellom 13 og 120.");
}
// Vis resultat
if (feil.length > 0) {
feilDiv.innerHTML = feil.map(f => "<p style='color:red'>" + f + "</p>").join("");
} else {
feilDiv.innerHTML = "<p style='color:green'>Påmelding mottatt!</p>";
}
});Når du har mange element som skal reagere på klikk (til dømes ei liste med hundre element), er det ineffektivt å leggje til ein hendingslyttar på kvart einskild element. I staden kan du bruke event delegation – éin lyttar på forelder-elementet:
// I stedet for dette (ineffektivt):
document.querySelectorAll("li").forEach(li => {
li.addEventListener("click", function () {
console.log(this.textContent);
});
});
// Bruk event delegation (effektivt):
document.querySelector("ul").addEventListener("click", function (event) {
if (event.target.tagName === "LI") {
console.log(event.target.textContent);
}
});Hendinga boblar opp (event bubbling) frå barneelementet til forelderen. Lyttaren på <ul> fangar opp klikk på alle <li>-element, og event.target fortel oss kva element som vart klikka.
Event delegation har to store fordelar:
1. Yting: Berre éin lyttar i staden for mange
2. Dynamisk innhald: Fungerer òg for element som vert lagde til seinare med JavaScript
Her er eit døme som kombinerer hendingshandtering og DOM-manipulering til ein liten quiz:
<div id="quiz">
<h2>Quiz: JavaScript</h2>
<p id="sporsmal">Hva brukes JavaScript til?</p>
<div id="alternativer">
<button class="alt" data-korrekt="false">Å strukturere nettsider</button>
<button class="alt" data-korrekt="true">Å gjøre nettsider interaktive</button>
<button class="alt" data-korrekt="false">Å style nettsider</button>
</div>
<p id="resultat"></p>
</div>const alternativer = document.querySelector("#alternativer");
const resultat = document.querySelector("#resultat");
alternativer.addEventListener("click", function (event) {
// Sjekk at et alternativ-knapp ble klikket
if (!event.target.classList.contains("alt")) {
return;
}
const erKorrekt = event.target.dataset.korrekt === "true";
// Deaktiver alle knapper
document.querySelectorAll(".alt").forEach(knapp => {
knapp.disabled = true;
if (knapp.dataset.korrekt === "true") {
knapp.style.backgroundColor = "lightgreen";
}
});
// Vis tilbakemelding
if (erKorrekt) {
resultat.textContent = "Riktig! JavaScript gjør nettsider interaktive.";
resultat.style.color = "green";
event.target.style.backgroundColor = "lightgreen";
} else {
resultat.textContent = "Feil! Prøv igjen neste gang.";
resultat.style.color = "red";
event.target.style.backgroundColor = "lightcoral";
}
});Dømet brukar event delegation på #alternativer-elementet i staden for individuelle lyttarar på kvar knapp. dataset-eigenskapen les data-*-attributt frå HTML, og vi brukar DOM-manipulering for visuell tilbakemelding.
input-hendinga vert utløyst kvar gong brukaren endrar verdien i eit tekstfelt – for kvart einaste tastetrykk. Dette gir sanntids-tilbakemelding:const sokefeld = document.querySelector("#sok");
const resultatDiv = document.querySelector("#resultater");
sokefeld.addEventListener("input", function (event) {
const sokeTekst = event.target.value.toLowerCase();
if (sokeTekst.length === 0) {
resultatDiv.textContent = "";
return;
}
// Enkel filtrering av en liste
const elementer = ["JavaScript", "HTML", "CSS", "Python", "Java"];
const treff = elementer.filter(e => e.toLowerCase().includes(sokeTekst));
resultatDiv.textContent = treff.length > 0
? "Treff: " + treff.join(", ")
: "Ingen treff.";
});Dette mønsteret vert brukt for sanntidssøk, passordstyrke-indikatorar, teikngrenser og liknande funksjonar.
Kva metode vert brukt for å lytte etter hendingar i JavaScript?
Kva gjer event.preventDefault()?
Kva er event.target i denne koden?
document.querySelector("ul").addEventListener("click", function(event) {
console.log(event.target);
});Når brukaren klikkar på eit <li>-element inne i lista.
Kva er fordelen med event delegation?
Skriv JavaScript-kode for ein knapp med id="morsknapp". Når knappen vert klikka for første gong, skal teksten i eit <p>-element med id="morsmelding" endrast til "Du er fantastisk!". Ved neste klikk skal teksten endrast til "Og det vet du!". Knappen skal veksle mellom desse to meldingane.
Lag ei komplett skjemavalidering med JavaScript. Skjemaet har felta "brukernavn" (minst 3 teikn), "epost" (må innehalde @ og .), og "passord" (minst 8 teikn). Vis feilmeldingar i ein <div> med id="feil". Bruk preventDefault() for å stoppe innsending ved feil.
Kva er skilnaden mellom "input"-hendinga og "change"-hendinga på eit tekstfelt?
Lag ein interaktiv teljar med JavaScript. Sida har tre knappar: "+1", "-1" og "Nullstill", og eit <span> med id="teller" som viser gjeldande verdi (startar på 0). Teljaren skal ikkje kunne gå under 0. Bruk éin hendingslyttar med event delegation på ein felles forelder-container.
Oppsummering
I dette kapittelet har du lært:
- Hending (event): ei handling i nettlesaren JavaScript kan reagere på.
- addEventListener: koblar ein funksjon til ei hending.
- Hendingstypar: click, keydown, submit m.fl.
- event.target: identifiserer kjelde-elementet.
- preventDefault og skjemavalidering: kontrollerer standard åtferd.
Nøkkelomgrep
| Omgrep | Forklaring |
|---|---|
| Hending | Handling i nettlesaren JavaScript kan reagere på |
| addEventListener | Koblar funksjon til ei hending |
| event.target | Elementet som utløyste hendinga |
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.