← Område 6 Guide · Interaktivitet med moduler Felsökning

Webbutveckling 1 · område 6 · guide

JavaScript: läsa, koppla in, anpassa

Guiden är områdets uppslagsbok. Den ska fungera för den som var borta, och den ska gå att slå i mitt under ett arbetspass. Alla exempel är hämtade ur referensprojekt/ – Vikstadssajten med sex moduler inbyggda – så att koden i guiden och koden i förlagan är samma kod.

Målet i den här kursen är inte att du ska kunna programmera från grunden. Det är att du ska kunna läsa färdig kod, förstå vad den gör, koppla in den och anpassa den. Det är så det mesta av webbutveckling ser ut i verkligheten, och det är det Projekt 5 kräver.

Vad du kan efter guiden

1. Vad JavaScript gör

Du kan redan två språk, och de gör var sin sak:

SpråkSvarar på frågan
HTMLVad är det här? En rubrik, en länk, ett formulärfält
CSSHur ser det ut? Grönt, 16 pixlar, i en spalt
JavaScriptVad händer när någon gör något?

Den tredje frågan är den nya. HTML och CSS beskriver en sida som den är. JavaScript låter sidan ändra sig medan besökaren är kvar på den: en meny öppnas, ett filter gömmer hälften av innehållet, ett formulär säger vad som är fel innan det skickas.

Vad det inte gör

JavaScript i den här kursen körs i besökarens webbläsare. Det betyder tre saker:

Var koden bor

I en egen fil med ändelsen .js, som du kopplar in i HTML:en med en script-tagg. Aldrig inuti HTML-elementen: en sajt där onclick="…" står utspritt i markupen är en sajt där ingen hittar felet. Samma princip som när stilarna flyttade ut ur style-attributen i område 3.

<script src="js/meny.js" defer></script>

Prova själv

Öppna referensprojekt/index.html i webbläsaren, tryck F12 och gå till fliken Console. Skriv document.title och tryck Enter. Webbläsaren svarar med sidans titel. Du har just läst av sidan med JavaScript.

2. De fem byggstenarna

Nästan all kod du kommer att läsa i den här kursen är byggd av fem saker. Kan du känna igen dem kan du läsa en modul.

ByggstenVad den ärSer ut så här
VariabelEtt namn på ett värdeconst knapp = …
FunktionEtt namn på några rader kod som ska köras ihopfunction oppna() { … }
HändelseNågot besökaren gör, och koden som ska svaraknapp.addEventListener("click", …)
VillkorKör det här bara om något stämmerif (arOppen) { … }
ListaFlera värden i en, som går att gå igenombilder.forEach(…)

Variabler: const och let

En variabel är ett namn på ett värde, så att du slipper skriva om värdet varje gång.

const KNAPP = ".menyknapp";
let aktuell = 0;

Skillnaden: const betyder att namnet aldrig ska peka på något annat. let betyder att värdet kommer att ändras. I karusell.js är aktuell en let för att den räknar upp när man bläddrar; allt annat är const.

var finns också – använd den inte

Du kommer att se var i äldre kod och i äldre guider på nätet. Den fungerar, men den har regler som överraskar. const som standard, let när värdet ska ändras.

Namnet spelar roll. const KNAPP i versaler betyder "det här är en inställning som inte ändras under körningen" – det är så modulerna märker sin ÄNDRA HÄR-zon. Vanliga variabler skrivs med små bokstäver: knapp, lista, aktuell.

Funktioner

En funktion är några rader kod som fått ett namn, så att de går att köra när man vill och flera gånger.

function stang() {
  knapp.setAttribute("aria-expanded", "false");
  knapp.textContent = TEXT_STANGD;
}

Raderna körs inte när funktionen skrivs. De körs när någon anropar den, genom att skriva namnet med parenteser: stang(). Parenteserna är det som säger "kör nu".

En funktion kan ta emot värden, som kallas parametrar:

function visa(index) {      // index är parametern
  aktuell = index;
  …
}

visa(0);                    // anrop med värdet 0

Prova själv

Öppna js/meny.js – i referensprojektet, eller på modulbibliotekets sida där hela koden står. Leta upp en const, en let om det finns någon, och två funktioner. Skriv ner vad varje funktion gör i en mening.

3. Hitta element på sidan

Innan koden kan ändra något på sidan måste den hitta det. Det kallas DOM-selektion – DOM är webbläsarens modell av sidan, och selektion är att välja ut en del av den.

const knapp = document.querySelector(".menyknapp");

document är hela sidan. querySelector letar upp det första elementet som matchar, och det som står inom parentesen är en CSS-selektor – exakt samma sorts selektor som du skriver i stilmallen.

Vad du vill haSå skriver du
Elementet med class="menyknapp"document.querySelector(".menyknapp")
Elementet med id="innehall"document.querySelector("#innehall")
Elementet med id="innehall", kortaredocument.getElementById("innehall")
Första button på sidandocument.querySelector("button")
Alla element med data-gruppdocument.querySelectorAll("[data-grupp]")

Skillnaden mellan de två sista är viktig: querySelector ger ett element, querySelectorAll ger alla som en lista. Ska du göra något med flera element behöver du den senare, och sedan en loop (avsnitt 7).

Hittar den inget?

Då får du null – ordet för "ingenting". Och försöker du använda null kraschar koden med felet Cannot read properties of null. Det är webbens vanligaste felmeddelande, och avsnitt 9 handlar om det.

Därför börjar varje modul i biblioteket med samma sorts rad:

const knapp = document.querySelector(KNAPP);
const lista = document.querySelector(LISTA);
if (!knapp || !lista) { return; }

Läs den högt: "om knappen inte finns, eller listan inte finns – avsluta." Utropstecknet betyder "inte". Två streck || betyder "eller". return avslutar funktionen direkt.

Det är den raden som gör att du kan lägga in meny.js på en sida som saknar meny utan att något går sönder.

Prova själv

Öppna referensprojektets startsida, tryck F12 → Console, och skriv:

document.querySelector(".menyknapp")

Webbläsaren svarar med elementet. Skriv sedan document.querySelector(".finns-inte") – svaret blir null.

4. Ändra sidan

När koden hittat ett element kan den ändra det. Fyra sätt räcker för hela modulbiblioteket.

Vad du vill ändraSå skriver duExempel ur biblioteket
Texten i ett elementelement.textContent = "…"knapp.textContent = TEXT_OPPEN;
En klass på elementetelement.classList.add("…")karusell.classList.add("karusell-igang");
Ett attributelement.setAttribute("namn", "värde")knapp.setAttribute("aria-expanded", "true");
Göm eller visaelement.hidden = true / falsedel.hidden = true;

textContent, inte innerHTML

Det finns ett annat sätt att sätta text: innerHTML. Det tolkar innehållet som HTML, vilket betyder att text som kommer utifrån – från ett formulär, från en adress – kan innehålla taggar och skript som körs. Det är webbens vanligaste säkerhetshål, och det heter XSS (säkerhetsguiden i område 5, avsnitt 7).

Regeln: är det text, använd textContent. Modulbiblioteket använder innerHTML noll gånger.

classList – fyra metoder

element.classList.add("klar");       // lägg till
element.classList.remove("klar");    // ta bort
element.classList.toggle("klar");    // finns den? ta bort. Annars lägg till
element.classList.contains("klar");  // frågar: finns den? svarar true eller false

toggle kan också ta ett andra värde som säger vad resultatet ska bli:

fraga.classList.toggle("quiz-ratt", arRatt);   // sätt klassen om arRatt är true

Det är den raden quiz.js använder för att märka varje fråga som rätt eller fel.

Attribut som betyder något

Tre attribut återkommer i modulerna, och de gör dubbel nytta:

AttributSäger till skärmläsarenAnvänds av CSS:en
aria-expandedom menyn är öppenvisar eller gömmer listan
aria-pressedom knappen är valdfärgar den valda filterknappen
aria-invalidatt fältet har ett felröd ram runt fältet

Det här är mönstret hela biblioteket bygger på: skriptet byter ett attribut, stilmallen reagerar på attributet. Ingen modul sätter färger eller storlekar direkt i koden. Det gör att du kan ändra utseendet i CSS:en utan att röra JavaScript.

Prova själv

I konsolen på referensprojektets startsida:

document.querySelector("h1").textContent = "Min rubrik"

Rubriken byts. Ladda om sidan – den är tillbaka. Allt du gör i konsolen gäller bara tills sidan laddas om, vilket gör konsolen ofarlig att experimentera i.

5. Händelser

En händelse är något som sker: ett klick, en tangenttryckning, ett formulär som skickas. Att lyssna på en händelse är att säga "när det här händer, kör den här funktionen".

knapp.addEventListener("click", function () {
  // det som ska hända
});

Tre delar: elementet som ska lyssna, vilken händelse, och funktionen som körs. Funktionen har inget namn här – den skrivs direkt på plats, och det är vanligt. Den kan också ha ett namn:

forra.addEventListener("click", bakat);

Här står bakat utan parenteser. Det är med avsikt: du ger funktionen som värde till lyssnaren, du anropar den inte. bakat() med parenteser hade kört funktionen direkt när raden lästes – ett vanligt fel.

De fem händelser du behöver

HändelseSker närVar i biblioteket
clicknågon klickar, eller trycker Enter på en knappmeny, galleri, karusell, mörkt läge
keydownen tangent trycks nermeny (Escape), karusell (pilar)
submitett formulär skickasvalidering, quiz
inputnågon skriver i ett fältvalidering
changeett fält får ett nytt värde och lämnas–

Händelseobjektet

Funktionen får ett värde: själva händelsen. I biblioteket heter den handelse.

document.addEventListener("keydown", function (handelse) {
  if (handelse.key === "Escape") { … }
});

handelse.key är vilken tangent det var. handelse.target är elementet händelsen kom från. Och handelse.preventDefault() stoppar det webbläsaren annars hade gjort – det är den som hindrar ett formulär från att skickas:

quiz.addEventListener("submit", function (handelse) {
  handelse.preventDefault();
  ratta();
});

En lyssnare i stället för många

galleri.js har en enda lyssnare på hela filterraden, inte en per knapp:

filterrad.addEventListener("click", function (handelse) {
  const knapp = handelse.target.closest("button");
  if (!knapp) { return; }
  filtrera(knapp.dataset.valj);
});

Klicket "bubblar" upp från knappen till raden, och closest("button") letar uppåt efter närmaste knapp. Det kallas händelsedelegering, och det behövs här för att knapparna skapas av skriptet – de fanns inte när lyssnaren sattes.

Prova själv

I konsolen, på vilken sida som helst:

document.querySelector("h1").addEventListener("click", function () { alert("Hej"); })

Klicka sedan på rubriken.

6. Villkor

Ett villkor kör kod bara när något stämmer.

if (arOppen) {
  stang();
} else {
  oppna();
}

Det som står i parentesen ska vara sant eller falskt – true eller false.

Jämförelser

SkrivsBetyder
===är exakt lika med
!==är inte lika med
> < >= <=större än, mindre än, och med "eller lika"
&&och – båda måste stämma
||eller – minst en måste stämma
!inte – vänder sant till falskt

Tre likhetstecken, inte två. == finns och gör nästan samma sak, men den jämför slarvigt: "1" == 1 är sant med två tecken och falskt med tre. Använd alltid ===.

Sanning och falskhet

Allt går att använda som villkor, även det som inte är true eller false. Då gäller en enkel regel: tomt är falskt, allt annat är sant.

FalsktSant
false, 0, "" (tom text), null, undefinedAlla andra värden – även "0" och en tom lista

Det är därför if (!knapp) { return; } fungerar: hittades ingen knapp är värdet null, alltså falskt, och !null blir sant.

Kortformen som finns i biblioteket

knapp.textContent = arMork ? TEXT_TILL_LJUS : TEXT_TILL_MORK;

Frågetecknet läses som ett if: "är arMork sant? ta det före kolonet. Annars det efter." Den kallas ternär och är praktisk när båda grenarna är korta. Är de långa, skriv ett vanligt if.

7. Listor och loopar

querySelectorAll ger en lista med element. För att göra något med varje element behöver du gå igenom listan.

delar.forEach(function (del) {
  del.hidden = true;
});

forEach betyder "för varje". Funktionen körs en gång per element, och del är det element som är i tur. Namnet väljer du själv.

Vill du veta vilket nummer i ordningen elementet har får du det som ett andra värde:

bilder.forEach(function (bild, i) {
  bild.hidden = i !== aktuell;
});

i är index, och det börjar på 0. Första bilden är 0, andra är 1. Det är därför karusell.js skriver aktuell + 1 när den visar "Bild 1 av 3" för människor.

Den andra loopen: for

Du ser också den här formen, och quiz.js använder den:

for (let i = 0; i < fragor.length; i++) {
  const fraga = fragor[i];
  …
}

Tre delar i parentesen: börja på 0 · fortsätt så länge i är mindre än antalet · öka i med ett varje varv. .length är hur många, och fragor[i] är elementet på plats i.

Varför två sorter? forEach är lättare att läsa, men går inte att avbryta i förtid. quiz.js måste kunna avbryta när den hittar en obesvarad fråga, och därför använder den for. Det är hela skillnaden.

Objekt: en lista med namn i stället för nummer

FACIT i quiz.js ser ut så här:

const FACIT = {
  f1: "b",
  f2: "c",
  f3: "a"
};

Det är ett objekt: värden som hämtas med ett namn i stället för ett nummer. FACIT.f1 eller FACIT["f1"] ger "b". Du behöver inte kunna bygga objekt i den här kursen, men du ska känna igen dem – två av modulerna har sitt facit eller sina etiketter i ett.

Prova själv

I konsolen på artsidan:

document.querySelectorAll("[data-grupp]").length

Svaret är hur många sektioner som går att filtrera.

8. Koppla in en modul

Det här avsnittet är lektion 53, och det är de fem stegen du gör varje gång.

1. Lägg filen i js/

Skapa mappen js i ditt repo om den inte finns, och lägg modulens .js-fil där. Filnamnet får du behålla. Gemener, bindestreck, ingen å ä ö i filnamn – samma regler som för bilder och sidor.

2. Lägg in script-taggen

Sist i body, precis före </body>, på varje sida där modulen ska användas:

    <script src="js/meny.js" defer></script>

  </body>

3. Kontrollera sökvägen

src="js/meny.js" betyder "mappen js, i samma mapp som den här HTML-filen". Ligger sidan i en undermapp blir det ../js/meny.js. Det är samma regler som för <link rel="stylesheet"> och för bilder – och det är fortfarande det vanligaste felet.

4. Lägg in den HTML modulen kräver

Varje modul säger överst i filen exakt vilken HTML den behöver. Den HTML:en måste finnas, annars avslutar modulen tyst (avsnitt 3). Kopiera från modulbibliotekets sida, eller från demosidan i referensprojekt/demo/.

5. Ta med CSS:en

Modulen har ett avsnitt i stil.css – 13a till 13f. Kopiera hela avsnittet, kommentarer och allt, och klistra in sist i din egen stilmall.

Vad defer gör, och varför det måste stå där

Utan defer läser webbläsaren HTML:en uppifrån och ner och stannar när den möter en script-tagg: hämtar filen, kör den, och fortsätter sedan. Ett skript som körs innan sidan är färdigläst hittar inte de element det letar efter.

Med defer hämtas filen parallellt och körs när hela HTML:en finns. Resultatet: sidan laddas snabbare, och skriptet hittar alltid sina element.

Så härVad som händer
<script src="…"> i headKör för tidigt. querySelector ger null
<script src="…"> sist i bodyFungerar, men blockerar inläsningen
<script src="…" defer>Rätt. Hämtas parallellt, körs när HTML:en är klar

Flera moduler på samma sida

Lägg en script-tagg per modul. Ordningen spelar ingen roll – varje modul är inkapslad och vet ingenting om de andra.

<script src="js/meny.js" defer></script>
<script src="js/morkt-lage.js" defer></script>
<script src="js/galleri.js" defer></script>

Prova själv

Öppna din egen sajt, lägg in meny.js enligt de fem stegen, och ladda om. Fungerar det inte: gå till avsnitt 9 innan du ändrar något i koden.

9. Konsolen

Konsolen är webbläsarens meddelanderuta, och den är ditt viktigaste verktyg i det här området. Öppna den innan du felsöker, inte efter.

F12, eller högerklick → Granska, sedan fliken Console.

Läs felet uppifrån

Ett felmeddelande har tre delar, och alla tre behövs:

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
    at meny.js:48
DelVad den säger
TypeErrorVilken sorts fel
Cannot read properties of nullVad som gick fel
at meny.js:48Vilken fil och vilken rad

Sista raden är den du ska börja med. Klicka på den – webbläsaren öppnar filen på rätt rad.

De fem fel du kommer att få

Meddelandet sägerVad det betyderVad du gör
Failed to load resource: 404Filen hittades inteFel sökväg i src, eller fel filnamn. Kontrollera stavningen, inklusive stora och små bokstäver
Cannot read properties of nullSkriptet hittade inte elementetKlassnamnet i koden och i HTML:en stämmer inte. Eller skriptet kördes för tidigt – saknas defer?
X is not definedEtt namn som inte finnsStavfel i ett variabelnamn
X is not a functionNamnet finns, men är inte en funktionStavfel i ett metodnamn: querySelectorAll med litet s, addEventlistener med litet l
Unexpected tokenKoden går inte att läsaEn parentes, klammer eller ett citattecken som saknas. Ofta raden före den som anges

Filen kördes inte alls

Ser du inget fel men inget händer? Kontrollera att filen verkligen hämtades: fliken Network i samma verktyg, ladda om, och leta efter din .js-fil i listan. Står det 404 där är det steg 3 i förra avsnittet som är fel.

console.log – när du vill veta vad koden gör

console.log("Här är jag", knapp);

Skriv raden där du vill veta om koden kommer fram, och vad ett värde är just då. Utskriften hamnar i konsolen.

Ta bort dem när du är klar. En konsol full av dina egna utskrifter är en konsol där du inte ser felen. Modulbiblioteket innehåller noll console.log.

Prova själv

Öppna referensprojektets startsida, konsolen, och skriv dokument.title (med k). Läs felet. Rätta till document.title.

10. Anpassa en modul

Det här är lektion 54, och det är gränsen som gör hela biblioteket användbart.

Varje modul har en zon överst:

  /* ===== ÄNDRA HÄR ====================================================== */

  const KNAPP = ".menyknapp";
  const LISTA = "#huvudmeny-lista";
  const TEXT_STANGD = "Meny";
  const TEXT_OPPEN = "Stäng";

  /* ===== SLUT PÅ ÄNDRA HÄR – nedanför behöver ingenting ändras ========= */

Allt i zonen är ditt. Allt under är inte det.

Vad du får ändra

SortExempelVad du ska tänka på
TexterTEXT_STANGD = "Meny"Vad som helst. Behåll citattecknen
Klassnamn och idKNAPP = ".menyknapp"Måste stämma exakt med din HTML. Punkt för klass, brädgård för id
InställningarBORJA_OM = trueLäs kommentaren bredvid – den säger vad värdena betyder
Innehåll i objektFACIT, GRUPPNAMNLägg till eller ta bort rader. Behåll kommatecknen mellan raderna

Att byta klassnamn – gör det på två ställen

Vill du att din knapp ska heta .oppna-meny i stället för .menyknapp måste båda ändras:

const KNAPP = ".oppna-meny";     // i modulen
<button type="button" class="oppna-meny" hidden …>   <!-- i HTML:en -->
.oppna-meny { … }                /* och i CSS:en */

Missar du ett av de tre hittar skriptet ingenting, och du får null i konsolen. Enklare väg: behåll modulens klassnamn och ändra din HTML i stället. Då är det ett ställe mindre att glömma.

Vad du inte ska röra

Allt under zonen. Om du ändå vill – och det gör du i A-spåret – gäller två regler:

  1. Ändra en sak i taget och ladda om. Går det sönder vet du vad det var.
  2. Ha originalet kvar. Kopiera filen innan du börjar, eller committa först. Git är till för precis det här.

Kontrollen: fungerar sidan utan modulen?

När du byggt in en modul, gör det här en gång:

  1. Kommentera bort script-taggen: <!-- <script src="js/meny.js" defer></script> -->
  2. Ladda om.
  3. Fungerar sidan? Går menyn att använda, syns innehållet?

Svaret ska vara ja, och orsaken är att det som bara fungerar med skript har hidden i HTML:en. Det här är inte ett krav i Projekt 5 – men det är hela område 7, och det är mycket lättare att bygga rätt från början än att laga i efterhand.

Prova själv

Öppna js/morkt-lage.js – i referensprojektet, eller läs den på modulbibliotekets sida. Byt TEXT_TILL_MORK till något eget, ladda om sidan och se knappens text ändras. Byt sedan NYCKEL och ladda om – ditt sparade val är borta, för modulen letar under ett nytt namn.

11. Läs en hel modul: meny.js

Det här är lektion 52:s moment, och det står här så att du kan göra om det själv. Modulen är 75 rader; nedan är de som gör något, i ordning.

(function () {
  "use strict";

Kapseln. Allt inuti är privat för den här filen. Sex moduler på samma sida kan alla ha en variabel som heter knapp utan att krocka. "use strict" gör att ett stavfel i ett variabelnamn blir ett fel i konsolen i stället för att tyst skapa en ny variabel.

  const KNAPP = ".menyknapp";
  const LISTA = "#huvudmeny-lista";
  const TEXT_STANGD = "Meny";
  const TEXT_OPPEN = "Stäng";

Inställningarna. Avsnitt 10.

  const knapp = document.querySelector(KNAPP);
  const lista = document.querySelector(LISTA);
  if (!knapp || !lista) { return; }

Hitta elementen, avbryt om de inte finns. Avsnitt 3.

  knapp.hidden = false;
  knapp.textContent = TEXT_STANGD;

Nu får knappen synas. Den hade hidden i HTML:en. Kommer skriptet hit fungerar det, och då – och bara då – visas knappen. Det är den rad som gör modulen diskret.

  function oppna() {
    knapp.setAttribute("aria-expanded", "true");
    knapp.textContent = TEXT_OPPEN;
  }

  function stang() {
    knapp.setAttribute("aria-expanded", "false");
    knapp.textContent = TEXT_STANGD;
  }

Två funktioner som gör var sin sak. Lägg märke till att ingen av dem gömmer eller visar listan – de byter bara ett attribut. Det är CSS:en i avsnitt 13a som reagerar.

  knapp.addEventListener("click", function () {
    const arOppen = knapp.getAttribute("aria-expanded") === "true";
    if (arOppen) {
      stang();
    } else {
      oppna();
    }
  });

Klicket. Läs av attributet, jämför med "true", och gör motsatsen mot det som är. Modulen behöver ingen egen variabel för att minnas om menyn är öppen – attributet är minnet, och det är samma attribut som skärmläsaren läser.

  document.addEventListener("keydown", function (handelse) {
    if (handelse.key === "Escape" && knapp.getAttribute("aria-expanded") === "true") {
      stang();
      knapp.focus();
    }
  });

Escape. Lyssnaren sitter på document, inte på knappen, för tangenttrycket ska fungera var som helst på sidan. && betyder att båda villkoren måste stämma: det ska vara Escape och menyn ska vara öppen. knapp.focus() flyttar fokus tillbaka, så att den som navigerar med tangentbord vet var hen är.

})();

Kapseln stängs och körs. Parenteserna sist är det som startar hela funktionen.

Prova själv

Gör samma sak med js/morkt-lage.js, som står i sin helhet på modulbibliotekets sida. Den har en sak meny.js inte har: try och catch runt localStorage. Varför? Svaret står i kommentaren.

12. Ta det längre

För C och A i Projekt 5 räcker det inte att modulen fungerar. Här är tre spår.

Anpassa på riktigt – ändra beteendet, inte bara texten

Ta en modul och ändra något under ÄNDRA HÄR-zonen, medvetet och dokumenterat. Exempel som är lagom stora:

Skriv i README.md vad du ändrade och varför. Det är den motiveringen C-nivån frågar efter.

Skriv modulen själv – A-spåret

Varje modul på modulbibliotekets sida har ett avsnitt Skriv den själv: en kravlista i tre till fem punkter, utan kod. Välj en modul, läs kraven, och skriv den från grunden utan att titta på originalet. Jämför sedan.

Det är inte samma sak som att kopiera och byta namn, och det är det A-spåret mäter: att du kan gå från krav till kod.

Gör modulen tillgänglig i det du redan byggt

Ta en modul du byggt in och gå igenom den med område 4:s verktyg: tabba genom den, kontrollera att fokus syns och följer läsordningen, kör WAVE. Hittar du något – rätta det och skriv ner vad det var. En modul som bryter tangentbordsnavigationen är en modul som gjort sajten sämre.

13. Felsökning

16 rader

SymptomTrolig orsakÅtgärd
Ingenting händer, inget fel i konsolenFilen hämtades aldrigFliken Network, leta efter din .js-fil. Står det 404 är sökvägen fel
404 på .js-filenFel sökväg eller fel filnamnLigger filen i js/? Stämmer stora och små bokstäver? GitHub Pages skiljer på dem, din dator kanske inte
Cannot read properties of nullElementet hittades inteJämför klassnamnet i modulens ÄNDRA HÄR-zon med din HTML, tecken för tecken
Samma fel, men HTML:en ser rätt utSkriptet kördes för tidigtSaknas defer i script-taggen?
Modulen fungerar på en sida men inte en annanscript-taggen saknas på den andra sidanVarje sida behöver sin egen script-tagg
Modulen fungerar lokalt men inte på GitHub PagesStora och små bokstäver i filnamnetMeny.js och meny.js är olika filer på servern
Knappen syns aldrigSkriptet kom aldrig fram till raden som tar bort hiddenTitta i konsolen. Det finns ett fel ovanför
Knappen syns men gör ingetLyssnaren sattes på fel elementKontrollera att KNAPP pekar på knappen, inte på något runt omkring
Menyn går inte att stängaTvå script-taggar för samma filSök i HTML:en. Modulen kördes två gånger och lyssnar två gånger
Filtret visar inga knapparInget element har data-gruppAttributet ska sitta på det som ska filtreras, inte på filterraden
Karusellen visar alla bilderFärre än två bilder, eller karusell-styr saknasModulen avslutar om något saknas. Jämför med demosidan
Formuläret skickas trots felnovalidate sattes men lyssnaren kraschadeLäs konsolen. Ett fel i submit-funktionen stoppar preventDefault
Quizet säger "inte svarat" fast jag svaratdata-fraga och name hör inte ihopVarje fieldset behöver data-fraga, och alla knappar i den samma name
Mörkt läge glöms bortPrivat fönster, eller NYCKEL ändradtry/catch gör att det inte kraschar – men lagringen fungerar inte i alla lägen
Något ändras i konsolen men inte i filenKonsolen ändrar bara den laddade sidanAlla ändringar i konsolen försvinner vid omladdning. Skriv i filen
Unexpected tokenTecken saknasTitta på raden före den som anges. Oftast en } eller en )

14. Snabbreferens

VadSå skriver du
Hitta ett elementdocument.querySelector(".klass")
Hitta alladocument.querySelectorAll("[data-grupp]")
Hitta på iddocument.getElementById("innehall")
Leta uppåt efter närmasteelement.closest("button")
Byta textelement.textContent = "…"
Lägga till klasselement.classList.add("klar")
Ta bort klasselement.classList.remove("klar")
Växla klasselement.classList.toggle("klar")
Växla efter villkorelement.classList.toggle("klar", arRatt)
Sätta attributelement.setAttribute("aria-expanded", "true")
Läsa attributelement.getAttribute("aria-expanded")
Ta bort attributelement.removeAttribute("aria-invalid")
Läsa data--attributelement.dataset.grupp
Göm / visaelement.hidden = true / false
Flytta fokuselement.focus()
Lyssna på händelseelement.addEventListener("click", function () { … })
Stoppa standardbeteendethandelse.preventDefault()
Vilken tangenthandelse.key === "Escape"
Varifrån händelsen komhandelse.target
Gå igenom en listalista.forEach(function (del) { … })
Gå igenom med indexlista.forEach(function (del, i) { … })
Antal i en listalista.length
Villkorif (villkor) { … } else { … }
Lika med===
Inte! · Och: && · Eller: ||
Skriva ut i konsolenconsole.log("text", varde)
Koppla in filen<script src="js/fil.js" defer></script>

15. Ordlista

Ordträning

OrdBetyder
JavaScriptProgrammeringsspråket som körs i webbläsaren och gör sidan interaktiv
modulEn färdig funktion i en egen fil, att koppla in och anpassa
DOMWebbläsarens modell av sidan, som JavaScript läser och ändrar
selektorMönstret som pekar ut ett element: .klass, #id, [attribut]
elementEn del av sidan: en knapp, ett stycke, en bild
variabelEtt namn på ett värde
constVariabel vars namn aldrig pekar på något annat
letVariabel vars värde kommer att ändras
funktionNågra rader kod som fått ett namn och kan köras när man vill
anropaAtt köra en funktion, genom att skriva dess namn med parenteser
parameterEtt värde en funktion tar emot
händelseNågot som sker: ett klick, en tangent, ett formulär som skickas
händelselyssnareKod som väntar på en händelse och svarar på den
händelsedelegeringAtt lyssna på en förälder i stället för på varje barn
villkorKod som bara körs när något stämmer
loopKod som körs en gång per element i en lista
indexEtt elements plats i en lista. Börjar på 0
objektVärden som hämtas med namn i stället för nummer
nullIngenting. Det querySelector ger när den inte hittar något
true / falseSant och falskt
kapsel(function () { … })(); – gör allt inuti privat för filen
"use strict"Gör att stavfel blir fel i konsolen i stället för tysta buggar
deferAttribut på script som gör att koden körs när HTML:en är klar
konsolenWebbläsarens meddelanderuta. F12 → Console
console.logSkriver ut ett värde i konsolen. Tas bort när du är klar
localStorageLitet lagringsutrymme i webbläsaren, kvar mellan besök
XSSSäkerhetshålet som uppstår när text från utsidan tolkas som HTML
diskret funktionalitetAtt sidan fungerar utan JavaScript, och skripten förbättrar. Område 7