chore(i18n): sync translations with latest source changes (chunk 10/20, 100 files)

pull/1668/head
localizeflow[bot] 2 weeks ago
parent 5f05a22a96
commit e2220b8b17

@ -42,10 +42,10 @@ Dette pensum inkluderer importbare pakker til almindelige LMS-arbejdsgange.
- Moodle Cloud har begrænset Common Cartridge-support. Foretræk Moodle-filen ovenfor, som også kan uploades til Canvas.
- Efter import, gennemgå moduler, deadlines og quizindstillinger for at matche din terminsplan.
![Moodle](../../translated_images/moodle.94eb93d714a50cb2c97435b408017dee224348b61bc86203ffd43a4f4e57b95f.da.png)
![Moodle](../../translated_images/moodle.94eb93d714a50cb2.da.png)
> Pensum i et Moodle-klasselokale
![Canvas](../../translated_images/canvas.fbd605ff8e5b8aff567d398528ce113db304446b90b9cad55c654de3fdfcda34.da.png)
![Canvas](../../translated_images/canvas.fbd605ff8e5b8aff.da.png)
> Pensum i Canvas
### Brug repoet direkte (uden Classroom)

@ -17,7 +17,7 @@ Kuule, ymmärrän täysin, jos ohjelmointi tuntuu juuri nyt pelottavalta. Kun al
Tänään tutustumme uskomattomiin työkaluihin, jotka tekevät modernista web-kehityksestä paitsi mahdollisen, myös todella koukuttavan. Puhun samoista editoreista, selaimista ja työnkuluista, joita Netflixin, Spotifyn ja suosikkisi indie-sovellusstudion kehittäjät käyttävät joka päivä. Ja tässä tulee se osuus, joka saa sinut tanssimaan ilosta: suurin osa näistä ammattitason, teollisuusstandardin työkaluista on täysin ilmaisia!
![Intro Programming](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff0b27dcbf1c3f16c8ed46984866f2d29988929678b0058fde.fi.png)
![Intro Programming](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff.fi.png)
> Sketchnote by [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -17,7 +17,7 @@ Tiedän, että tämä voi tuntua aluksi paljolta muistan itsekin tuijottanee
Otamme tämän matkan yhdessä, askel kerrallaan. Ei kiirettä, ei painetta vain sinä, minä ja muutama todella siisti työkalu, joista tulee pian uusia parhaita ystäviäsi!
![Johdanto GitHubiin](../../../../translated_images/webdev101-github.8846d7971abef6f947909b4f9d343e2a23778aa716ca6b9d71df7174ee5009ac.fi.png)
![Johdanto GitHubiin](../../../../translated_images/webdev101-github.8846d7971abef6f9.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid
@ -605,7 +605,7 @@ Etsi ensin GitHubista repositorio (tai **repo**), joka kiinnostaa sinua ja johon
✅ Hyvä tapa löytää 'aloittelijaystävällisiä' repoja on [etsiä tagilla 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
![Kopioi repo paikallisesti](../../../../translated_images/clone_repo.5085c48d666ead57664f050d806e325d7f883be6838c821e08bc823ab7c66665.fi.png)
![Kopioi repo paikallisesti](../../../../translated_images/clone_repo.5085c48d666ead57.fi.png)
Koodin kopioimiseen on useita tapoja. Yksi tapa on "klonata" repositorion sisältö HTTPS:n, SSH:n tai GitHub CLI:n (komentoriviliittymän) avulla.

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# Luodaan saavutettavia verkkosivuja
![Kaikki saavutettavuudesta](../../../../translated_images/webdev101-a11y.8ef3025c858d897a403a1a42c0897c76e11b724d9a8a0c0578dd4316f7507622.fi.png)
![Kaikki saavutettavuudesta](../../../../translated_images/webdev101-a11y.8ef3025c858d897a.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScriptin perusteet: Tietotyypit
![JavaScriptin perusteet - Tietotyypit](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.fi.png)
![JavaScriptin perusteet - Tietotyypit](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScriptin perusteet: metodit ja funktiot
![JavaScript Basics - Functions](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b7605c36330ac42eeb5cd8ed02bcdd60fdac778174d6cb865.fi.png)
![JavaScript Basics - Functions](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b.fi.png)
> Sketchnote by [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScriptin perusteet: Päätöksenteko
![JavaScriptin perusteet - Päätöksenteko](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0b1cb2f8adaff3ed2a77c4f91db96d8a0594132a353fa189a.fi.png)
![JavaScriptin perusteet - Päätöksenteko](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScriptin perusteet: Taulukot ja silmukat
![JavaScriptin perusteet - Taulukot](../../../../translated_images/webdev101-js-arrays.439d7528b8a294558d0e4302e448d193f8ad7495cc407539cc81f1afe904b470.fi.png)
![JavaScriptin perusteet - Taulukot](../../../../translated_images/webdev101-js-arrays.439d7528b8a29455.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -26,7 +26,7 @@ journey
Build terrarium: 5: Student
```
![Johdatus HTML:ään](../../../../translated_images/webdev101-html.4389c2067af68e98280c1bde52b6c6269f399eaae3659b7c846018d8a7b0bbd9.fi.png)
![Johdatus HTML:ään](../../../../translated_images/webdev101-html.4389c2067af68e98.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
HTML eli HyperText Markup Language on jokaisen verkkosivun perusta, jonka olet koskaan vieraillut. Ajattele HTML:ää verkkosivujen "luurankona" se määrittää, mihin sisältö sijoitetaan, miten se järjestetään ja mitä kukin osa edustaa. Vaikka CSS myöhemmin "pukee" HTML:n väreillä ja asetteluilla ja JavaScript tuo siihen interaktiivisuutta, HTML tarjoaa olennaisen rakenteen, joka tekee kaiken muun mahdolliseksi.
@ -88,7 +88,7 @@ Luo oma kansio terraario-projektillesi ja lisää ensimmäinen HTML-tiedostosi.
4. Explorer-paneelissa klikkaa "New File" -ikonia
5. Nimeä tiedostosi `index.html`
![VS Code Explorer näyttää uuden tiedoston luomisen](../../../../translated_images/vs-code-index.e2986cf919471eb984a0afef231380c8b132b000635105f2397bd2754d1b689c.fi.png)
![VS Code Explorer näyttää uuden tiedoston luomisen](../../../../translated_images/vs-code-index.e2986cf919471eb9.fi.png)
**Vaihtoehto 2: Käytä terminaalikomentoja**
```bash

@ -30,7 +30,7 @@ journey
Glass reflections: 5: Student
```
![Johdatus CSS:ään](../../../../translated_images/webdev101-css.3f7af5991bf53a200d79e7257e5e450408d8ea97f5b531d31b2e3976317338ee.fi.png)
![Johdatus CSS:ään](../../../../translated_images/webdev101-css.3f7af5991bf53a20.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
Muistatko, kuinka HTML-terrariumisi näytti melko yksinkertaiselta? CSS:n avulla voimme muuttaa tuon pelkistetyn rakenteen visuaalisesti houkuttelevaksi.
@ -205,7 +205,7 @@ body {
Avaa selaimesi kehitystyökalut (F12), siirry Elements-välilehteen ja tarkista `<h1>`-elementtisi. Näet, että se perii fonttiperheen body-elementiltä:
![peritty fontti](../../../../translated_images/1.cc07a5cbe114ad1d4728c35134584ac1b87db688eff83cf75985cf31fe0ed95c.fi.png)
![peritty fontti](../../../../translated_images/1.cc07a5cbe114ad1d.fi.png)
**Kokeilua**: Kokeile asettaa muita periytyviä ominaisuuksia `<body>`-elementille, kuten `color`, `line-height` tai `text-align`. Mitä tapahtuu otsikolle ja muille elementeille?
@ -592,7 +592,7 @@ Valmis parantamaan terrariumiasi realistisilla lasin heijastuksilla? Tämä tekn
Luot hienovaraisia korostuksia, jotka simuloivat, miten valo heijastuu lasipinnoilta. Tämä lähestymistapa on samanlainen kuin miten renessanssimaalari Jan van Eyck käytti valoa ja heijastusta saadakseen maalatun lasin näyttämään kolmiulotteiselta. Tässä on tavoitteenasi:
![valmis terrarium](../../../../translated_images/terrarium-final.2f07047ffc597d0a06b06cab28a77801a10dd12fdb6c7fc630e9c40665491c53.fi.png)
![valmis terrarium](../../../../translated_images/terrarium-final.2f07047ffc597d0a.fi.png)
**Haasteesi:**
- **Luo** hienovaraisia valkoisia tai vaaleanvärisiä soikeita muotoja lasin heijastuksille

@ -26,7 +26,7 @@ journey
Complete terrarium: 5: Student
```
![DOM ja sulkeuma](../../../../translated_images/webdev101-js.10280393044d7eaaec7e847574946add7ddae6be2b2194567d848b61d849334a.fi.png)
![DOM ja sulkeuma](../../../../translated_images/webdev101-js.10280393044d7eaa.fi.png)
> Sketchnote: [Tomomi Imura](https://twitter.com/girlie_mac)
Tervetuloa yhteen verkkokehityksen kiehtovimmista osa-alueista interaktiivisuuden luomiseen! Document Object Model (DOM) toimii sillan tavoin HTML:n ja JavaScriptin välillä, ja tänään käytämme sitä herättääksemme terrariosi eloon. Kun Tim Berners-Lee loi ensimmäisen verkkoselaimen, hän kuvitteli verkon, jossa dokumentit voisivat olla dynaamisia ja interaktiivisia DOM tekee tämän vision mahdolliseksi.
@ -105,7 +105,7 @@ flowchart TD
style Q fill:#ffebee
```
![DOM-puun esitys](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.fi.png)
![DOM-puun esitys](../../../../translated_images/dom-tree.7daf0e763cbbba92.fi.png)
> DOM:n ja sitä vastaavan HTML-koodin esitys. Lähde: [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
@ -150,7 +150,7 @@ flowchart LR
> 💡 **Sulkeumien ymmärtäminen**: Sulkeumat ovat merkittävä aihe JavaScriptissä, ja monet kehittäjät käyttävät niitä vuosia ennen kuin täysin ymmärtävät kaikki teoreettiset näkökohdat. Tänään keskitymme käytännön sovellukseen näet, kuinka sulkeumat syntyvät luonnollisesti interaktiivisia ominaisuuksia rakentaessamme. Ymmärrys kehittyy, kun näet, kuinka ne ratkaisevat todellisia ongelmia.
![DOM-puun esitys](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.fi.png)
![DOM-puun esitys](../../../../translated_images/dom-tree.7daf0e763cbbba92.fi.png)
> DOM:n ja sitä vastaavan HTML-koodin esitys. Lähde: [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
@ -589,7 +589,7 @@ Testaa nyt interaktiivista terrariumiasi! Avaa `index.html`-tiedosto verkkoselai
- **Laitteiden välinen tuki**: Toimii sekä työpöydällä että mobiililaitteilla
- **Suorituskyky huomioitu**: Ei muistivuotoja tai tarpeettomia laskelmia
![valmis terrarium](../../../../translated_images/terrarium-final.0920f16e87c13a84cd2b553a5af9a3ad1cffbd41fbf8ce715d9e9c43809a5e2c.fi.png)
![valmis terrarium](../../../../translated_images/terrarium-final.0920f16e87c13a84.fi.png)
---

@ -1,45 +1,30 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "7965cd2bc5dc92ad888dc4c6ab2ab70a",
"translation_date": "2025-08-27T20:04:42+00:00",
"original_hash": "bc5c5550f79d10add90ce419ee34abb3",
"translation_date": "2026-01-07T01:03:14+00:00",
"source_file": "3-terrarium/README.md",
"language_code": "fi"
}
-->
# Minun Terraarioni: Projekti HTML:n, CSS:n ja DOM-manipulaation oppimiseen JavaScriptin avulla 🌵🌱
## Julkaise Terrariumisi
Pieni drag and drop -koodimeditaatio. Vähän HTML:ää, JS:ää ja CSS:ää käyttäen voit rakentaa verkkokäyttöliittymän, tyylitellä sen ja lisätä siihen useita haluamiasi vuorovaikutuksia.
Voit julkaista Terrariumisi verkossa käyttämällä **Azure Static Web Apps** -palvelua.
![minun terraarioni](../../../translated_images/screenshot_gray.0c796099a1f9f25e40aa55ead81f268434c00af30d7092490759945eda63067d.fi.png)
1. Tee fork tästä repositoriosta
# Oppitunnit
2. Paina tätä painiketta 👇
1. [Johdanto HTML:ään](./1-intro-to-html/README.md)
2. [Johdanto CSS:ään](./2-intro-to-css/README.md)
3. [Johdanto DOM:iin ja JS Closures -toimintoihin](./3-intro-to-DOM-and-closures/README.md)
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.StaticApp)
## Tekijät
Kirjoitettu ♥️:lla [Jen Looperin](https://www.twitter.com/jenlooper) toimesta.
CSS:n avulla luotu terraario on saanut inspiraationsa Jakub Mandran lasipurkki [codepenistä](https://codepen.io/Rotarepmi/pen/rjpNZY).
Taide on käsin piirretty [Jen Looperin](http://jenlooper.com) toimesta Procreate-sovelluksen avulla.
## Julkaise Terraariosi
Voit julkaista terraariosi verkossa käyttämällä Azure Static Web Apps -palvelua.
1. Haarauta tämä repo
2. Paina tätä painiketta
[![Deploy to Azure button](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
3. Käy läpi ohjattu toiminto sovelluksesi luomiseksi. Varmista, että asetat sovelluksen juuren joko `/solution`-kansioon tai koodipohjasi juureen. Tässä sovelluksessa ei ole API:ta, joten siitä ei tarvitse huolehtia. Haarautettuun repositorioosi luodaan GitHub-kansio, joka auttaa Azure Static Web Apps -rakennuspalveluita rakentamaan ja julkaisemaan sovelluksesi uuteen URL-osoitteeseen.
3. Seuraa asennusvelhon ohjeita luodaksesi sovelluksesi.
- Aseta **App root** joko `/solution` tai koodipohjasi juureen.
- Tässä sovelluksessa ei ole APIa, joten voit ohittaa API:n määrityksen.
- `.github`-kansio luodaan automaattisesti auttamaan Azure Static Web Appsia rakentamaan ja julkaisemaan sovelluksesi.
---
**Vastuuvapauslauseke**:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua [Co-op Translator](https://github.com/Azure/co-op-translator). Vaikka pyrimme tarkkuuteen, huomioithan, että automaattiset käännökset voivat sisältää virheitä tai epätarkkuuksia. Alkuperäinen asiakirja sen alkuperäisellä kielellä tulisi pitää ensisijaisena lähteenä. Kriittisen tiedon osalta suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa väärinkäsityksistä tai virhetulkinnoista, jotka johtuvat tämän käännöksen käytöstä.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Vastuuvapauslauseke**:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua [Co-op Translator](https://github.com/Azure/co-op-translator). Pyrimme tarkkuuteen, mutta ota huomioon, että automaattikäännöksissä saattaa esiintyä virheitä tai epätarkkuuksia. Alkuperäistä asiakirjaa sen alkuperäiskielellä pidetään virallisena lähteenä. Tärkeissä tiedoissa suositellaan ammattimaisen ihmiskääntäjän käyttöä. Emme ole vastuussa tämän käännöksen käytöstä aiheutuvista väärinymmärryksistä tai tulkinnoista.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Pieni vedä ja pudota -koodimeditaatio. Vähän HTML:ää, JS:ää ja CSS:ää käyttäen voit rakentaa verkkokäyttöliittymän, tyylitellä sen ja lisätä siihen vuorovaikutteisuutta.
![minun terraarioni](../../../../translated_images/screenshot_gray.0c796099a1f9f25e40aa55ead81f268434c00af30d7092490759945eda63067d.fi.png)
![minun terraarioni](../../../../translated_images/screenshot_gray.0c796099a1f9f25e.fi.png)
## Tekijät

@ -26,7 +26,7 @@ journey
Polish experience: 5: Student
```
![Selaimen luonnos](../../../../translated_images/browser.60317c9be8b7f84adce43e30bff8d47a1ae15793beab762317b2bc6b74337c1a.fi.jpg)
![Selaimen luonnos](../../../../translated_images/browser.60317c9be8b7f84a.fi.jpg)
> Luonnos: [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
## Ennakkokysely
@ -79,7 +79,7 @@ Tämä prosessi muistuttaa, kuinka ensimmäinen selain, WorldWideWeb, suunnitelt
**Pieni historia**: Ensimmäinen selain oli nimeltään 'WorldWideWeb' ja sen loi Sir Timothy Berners-Lee vuonna 1990.
![varhaiset selaimet](../../../../translated_images/earlybrowsers.d984b711cdf3a42ddac919d46c4b5ca7232f68ccfbd81395e04e5a64c0015277.fi.jpg)
![varhaiset selaimet](../../../../translated_images/earlybrowsers.d984b711cdf3a42d.fi.jpg)
> Joitakin varhaisia selaimia, lähde: [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
### Kuinka selaimet käsittelevät verkkosisältöä
@ -198,7 +198,7 @@ quadrantChart
Laajennuksen asennusprosessin ymmärtäminen auttaa sinua ennakoimaan käyttäjäkokemusta, kun ihmiset asentavat laajennuksesi. Asennusprosessi on standardoitu moderneissa selaimissa, pienillä käyttöliittymäsuunnittelun eroilla.
![kuvakaappaus Edge-selaimesta, jossa edge://extensions-sivu ja asetukset-valikko ovat avoinna](../../../../translated_images/install-on-edge.d68781acaf0b3d3dada8b7507cde7a64bf74b7040d9818baaa9070668e819f90.fi.png)
![kuvakaappaus Edge-selaimesta, jossa edge://extensions-sivu ja asetukset-valikko ovat avoinna](../../../../translated_images/install-on-edge.d68781acaf0b3d3d.fi.png)
> **Tärkeää**: Varmista, että kehittäjätila on kytketty päälle ja salli laajennusten asentaminen muista kaupoista testatessasi omia laajennuksiasi.
@ -313,10 +313,10 @@ Tämä noudattaa progressiivisen paljastamisen periaatetta, jota on käytetty k
### Laajennusnäkymien yleiskatsaus
**Asetusnäkymä** - Ensimmäisen käyttökerran asetukset:
![kuvakaappaus valmiista laajennuksesta avoinna selaimessa, jossa näkyy lomake alueen nimen ja API-avaimen syöttämiseksi.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.fi.png)
![kuvakaappaus valmiista laajennuksesta avoinna selaimessa, jossa näkyy lomake alueen nimen ja API-avaimen syöttämiseksi.](../../../../translated_images/1.b6da8c1394b07491.fi.png)
**Tulosnäkymä** - Hiilijalanjälkitietojen näyttö:
![kuvakaappaus valmiista laajennuksesta, joka näyttää hiilen käytön ja fossiilisten polttoaineiden prosenttiosuuden US-NEISO-alueelle.](../../../../translated_images/2.1dae52ff0804224692cd648afbf2342955d7afe3b0101b617268130dfb427f55.fi.png)
![kuvakaappaus valmiista laajennuksesta, joka näyttää hiilen käytön ja fossiilisten polttoaineiden prosenttiosuuden US-NEISO-alueelle.](../../../../translated_images/2.1dae52ff08042246.fi.png)
### Asetuslomakkeen rakentaminen

@ -266,7 +266,7 @@ stateDiagram-v2
ClearStorage --> FirstTime: Back to setup
```
![Paikallisen tallennuksen näkymä](../../../../translated_images/localstorage.472f8147b6a3f8d141d9551c95a2da610ac9a3c6a73d4a1c224081c98bae09d9.fi.png)
![Paikallisen tallennuksen näkymä](../../../../translated_images/localstorage.472f8147b6a3f8d1.fi.png)
> ⚠️ **Tietoturvahuomio**: Tuotantosovelluksissa API-avainten tallentaminen LocalStorageen aiheuttaa tietoturvariskejä, koska JavaScript voi käyttää näitä tietoja. Oppimiskäyttöön tämä lähestymistapa toimii hyvin, mutta oikeissa sovelluksissa tulisi käyttää turvallista palvelinpuolen tallennusta arkaluontoisille tunnuksille.

@ -126,7 +126,7 @@ Avaa Edge-selaimen kehitystyökalut klikkaamalla oikeassa yläkulmassa olevia ko
Kokeillaan tätä. Avaa verkkosivusto (Microsoft.com toimii hyvin tähän) ja klikkaa 'Tallenna'-painiketta. Päivitä sivu ja katso, kuinka profiilintyökalu tallentaa kaiken, mitä tapahtuu. Kun lopetat tallennuksen, näet yksityiskohtaisen erittelyn siitä, kuinka selain 'skriptasi', 'renderöi' ja 'maalasi' sivuston. Se muistuttaa minua siitä, kuinka ohjauskeskus seuraa jokaista järjestelmää raketin laukaisun aikana saat reaaliaikaista dataa siitä, mitä tapahtuu ja milloin.
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01cfec9aab74173dba13f91d2c968e1a1ae434c26165792df15.fi.png)
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01c.fi.png)
✅ [Microsoftin dokumentaatio](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) sisältää paljon lisätietoa, jos haluat syventyä aiheeseen.
@ -136,11 +136,11 @@ Valitse profiilin aikajanan osia zoomataksesi tapahtumiin, jotka tapahtuvat sivu
Saat yleiskuvan sivusi suorituskyvystä valitsemalla osan profiilin aikajanasta ja katsomalla yhteenvetopaneelia:
![Edge profiler snapshot](../../../../translated_images/snapshot.97750180ebcad73794a3594b36925eb5c8dbaac9e03fec7f9b974188c9ac63c7.fi.png)
![Edge profiler snapshot](../../../../translated_images/snapshot.97750180ebcad737.fi.png)
Tarkista Tapahtumaloki-paneeli nähdäksesi, kestikö jokin tapahtuma yli 15 ms:
![Edge event log](../../../../translated_images/log.804026979f3707e00eebcfa028b2b5a88cec6292f858767bb6703afba65a7d9c.fi.png)
![Edge event log](../../../../translated_images/log.804026979f3707e0.fi.png)
✅ Tutustu profiilityökaluusi! Avaa kehitystyökalut tällä sivustolla ja katso, onko pullonkauloja. Mikä on hitaimmin latautuva resurssi? Nopein?

@ -23,7 +23,7 @@ Tätä laajennusta käyttäjä voi kutsua ad hoc -tyyliin, kun API-avain ja alue
### Kiitokset
![vihreä selaimen laajennus](../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![vihreä selaimen laajennus](../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Kiitokset

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Käyttämällä tmrow:n CO2 Signal -API:ta sähkönkulutuksen seuraamiseen voit rakentaa selainlaajennuksen, joka muistuttaa sinua suoraan selaimessa siitä, kuinka kuormittavaa alueesi sähkönkulutus on. Tämän laajennuksen satunnainen käyttö auttaa sinua tekemään päätöksiä toimistasi tämän tiedon perusteella.
![laajennuksen kuvakaappaus](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![laajennuksen kuvakaappaus](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloittaminen
@ -31,7 +31,7 @@ npm run build
Asentaaksesi laajennuksen Edge-selaimeen, käytä selaimen oikean yläkulman 'kolmen pisteen' valikkoa löytääksesi Laajennukset-paneelin. Valitse sieltä 'Lataa purkamaton' ladataksesi uuden laajennuksen. Avaa 'dist'-kansio kehotteessa, ja laajennus latautuu. Käyttääksesi sitä tarvitset API-avaimen CO2 Signal -API:lle ([hanki avain sähköpostitse täältä](https://www.co2signal.com/) - syötä sähköpostiosoitteesi tämän sivun laatikkoon) sekä [alueesi koodin](http://api.electricitymap.org/v3/zones), joka vastaa [Electricity Map](https://www.electricitymap.org/map) -karttaa (esimerkiksi Bostonissa käytän koodia 'US-NEISO').
![asennus](../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![asennus](../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun API-avain ja alueen koodi on syötetty laajennuksen käyttöliittymään, selaimen laajennuspalkin värillinen piste muuttuu heijastamaan alueesi energiankulutusta ja antaa sinulle vihjeitä siitä, mitkä energiaintensiiviset toiminnot olisivat sopivia suorittaa. Tämän 'pistejärjestelmän' konsepti tuli minulle [Energy Lollipop -laajennuksesta](https://energylollipop.com/) Kalifornian päästöjen seuraamiseen.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Käyttämällä tmrow'n CO2 Signal -API:ta sähkönkulutuksen seuraamiseen, luo selainlaajennus, joka muistuttaa sinua suoraan selaimessasi alueesi sähkönkulutuksesta. Tämän ad hoc -laajennuksen käyttö auttaa sinua tekemään päätöksiä toimintasi suhteen näiden tietojen perusteella.
![laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloittaminen
@ -31,7 +31,7 @@ npm run build
Asentaaksesi laajennuksen Edge-selaimeen, käytä selaimen oikean yläkulman 'kolmen pisteen' valikkoa löytääksesi Laajennukset-paneelin. Valitse sieltä 'Lataa purkamaton laajennus' ladataksesi uuden laajennuksen. Avaa 'dist'-kansio kehotteessa, ja laajennus latautuu. Käyttääksesi laajennusta tarvitset API-avaimen CO2 Signal -API:lle ([hanki avain sähköpostitse täältä](https://www.co2signal.com/) - syötä sähköpostiosoitteesi sivun laatikkoon) sekä [alueesi koodin](http://api.electricitymap.org/v3/zones), joka vastaa [Electricity Map -karttaa](https://www.electricitymap.org/map) (esimerkiksi Bostonissa käytän 'US-NEISO').
![asennus](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![asennus](../../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun API-avain ja alue on syötetty laajennuksen käyttöliittymään, selaimen laajennuspalkin värillisen pisteen tulisi muuttua heijastamaan alueesi energiankulutusta ja antaa sinulle vihjeen siitä, millaisia energiaintensiivisiä toimintoja olisi sopivaa tehdä. Tämän 'pistejärjestelmän' konsepti on saanut inspiraationsa [Energy Lollipop -laajennuksesta](https://energylollipop.com/) Kalifornian päästöjen osalta.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Tmrow:n CO2 Signal API:n avulla seurataan sähkönkulutusta ja luodaan selainlaajennus, joka muistuttaa sinua siitä, kuinka kuormittavaa alueesi sähkönkäyttö on selaimessasi. Tämän laajennuksen käyttö auttaa sinua tekemään päätöksiä toiminnastasi tämän tiedon perusteella.
![Laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![Laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloittaminen
@ -31,7 +31,7 @@ npm run build
Asentaaksesi sen Edge-selaimeen, käytä selaimen oikeassa yläkulmassa olevaa "kolmen pisteen" valikkoa löytääksesi laajennuspaneelin. Valitse sieltä "Lataa purkamaton" ladataksesi uuden laajennuksen. Avaa kehotteessa "dist"-kansio, ja laajennus latautuu. Käyttääksesi sitä, tarvitset CO2 Signal API -avaimen ([saatavilla sähköpostitse täältä](https://www.co2snal.com/) - syötä sähköpostiosoitteesi sivun laatikkoon) ja [alueesi koodin](http://api.electricitymap.org/v3/zones) [Electricity Map](https://www.electricitymap.org/map) -sivustolta (esimerkiksi Bostonissa käytän "US-NEISO").
![Asennus](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![Asennus](../../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun API-avain ja alue on syötetty laajennuksen käyttöliittymään, selaimen laajennuspalkissa oleva värillinen piste muuttuu heijastamaan alueesi energiankäyttöä ja antaa sinulle indikaattorin siitä, mitkä energiaintensiiviset toiminnot sopivat parhaiten suoritettavaksi. Tämän "piste"-järjestelmän idea tuli minulle Kalifornian päästöjen [Energy Lollipop -laajennuksesta](https://energylollipop.com/).

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Tässä projektissa käytetään tmrow:n Signal CO2 -rajapintaa sähköenergian käytön seuraamiseen. Tarkoituksena on luoda selainlaajennus, joka muistuttaa suoraan selaimessa, kuinka kuormittavaa sähköenergian käyttö on omalla alueella. Tämän laajennuksen avulla voi arvioida omia toimintojaan näiden tietojen perusteella.
![laajennuksen näkymä](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![laajennuksen näkymä](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloittaminen
@ -31,7 +31,7 @@ npm run build
Asentaaksesi laajennuksen Edge-selaimeen, käytä selaimen oikeassa yläkulmassa olevaa "kolmen pisteen" valikkoa ja etsi Laajennukset-paneeli. Jos kehittäjätila ei ole vielä käytössä, ota se käyttöön (vasemmassa alakulmassa). Valitse "Lataa purkamaton" lisätäksesi uuden laajennuksen. Avaa "dist"-kansio kehotteessa, ja laajennus ladataan. Käyttöä varten tarvitset API-avaimen CO2 Signal -rajapintaan (voit [hankkia sen sähköpostitse täältä](https://www.co2signal.com/) - syötä sähköpostiosoitteesi sivulla olevaan kenttään) sekä [alueesi koodin](http://api.electricitymap.org/v3/zones), joka vastaa [sähkökarttaa](https://www.electricitymap.org/map) (esimerkiksi Bostonissa "US-NEISO").
![asennus](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![asennus](../../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun API-avain ja alue on syötetty laajennuksen käyttöliittymään, selaimen laajennuspalkissa oleva väripiste muuttuu heijastamaan alueen energiankäyttöä. Se antaa myös vihjeitä siitä, mitkä korkean energiankulutuksen toiminnot olisivat sopivia suorittaa. Tämän "pistejärjestelmän" konsepti on peräisin [Energy Lollipop -laajennuksesta](https://energylollipop.com/), joka seuraa Kalifornian päästöjä.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Rakennetaan selainlaajennus, joka käyttää tmrow:n CO2 Signal API:ta seuratakseen energiankulutusta ja näyttää muistutuksena, kuinka paljon sähköä alueellasi käytetään. Tämän laajennuksen avulla voit tehdä päätöksiä toiminnastasi tämän tiedon perusteella.
![laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloitus
@ -31,7 +31,7 @@ npm run build
Asentaaksesi laajennuksen Edge-selaimeen, etsi selaimen oikeasta yläkulmasta "kolmen pisteen" valikosta "Laajennukset"-paneeli. Valitse sieltä "Load Unpacked" ja lataa uusi laajennus. Kun sinua kehotetaan, avaa "dist"-kansio, jolloin laajennus latautuu. Käyttääksesi laajennusta tarvitset CO2 Signal API:n API-avaimen ([hanki yksi sähköpostitse täältä](https://www.co2signal.com/) - syötä sähköpostisi tämän sivun laatikkoon) sekä [Electricity Map](https://www.electricitymap.org/map) -sivuston mukaisen [aluekoodin](http://api.electricitymap.org/v3/zones) (esimerkiksi Bostonissa käytetään 'US-NEISO').
![asennus](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![asennus](../../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun syötät API-avaimen ja aluekoodin laajennuksen käyttöliittymään, selainlaajennuspalkissa näkyvä värillinen piste muuttuu ja heijastaa alueesi energiankulutusta. Tämä auttaa sinua arvioimaan, millaisia energiaa vaativia toimintoja on sopivaa tehdä. Tämän "piste"-järjestelmän idea tuli minulle Kalifornian päästöjen [Energy Lollipop -laajennuksesta](https://energylollipop.com/).

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Käyttämällä tmrow:n CO2 Signal -API:ta sähkönkulutuksen seuraamiseen, rakenna selaimen laajennus, joka antaa sinulle ilmoituksia siitä, kuinka raskasta alueesi sähkönkulutus on. Tämän laajennuksen käyttö auttaa sinua tekemään tietoisempia päätöksiä toiminnastasi näiden tietojen perusteella.
![selaimen laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![selaimen laajennuksen kuvakaappaus](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloita tästä
@ -31,7 +31,7 @@ npm run build
Asentaaksesi laajennuksen Edge-selaimeen, käytä selaimen oikeassa yläkulmassa olevaa "kolmen pisteen" valikkoa löytääksesi Laajennukset-paneelin. Valitse sieltä 'Load Unpacked' ladataksesi uuden laajennuksen. Avaa 'dist'-kansio pyynnön mukaisesti, ja laajennus latautuu. Käyttääksesi sitä tarvitset API-avaimen CO2 Signal -API:lle ([hanki avain sähköpostitse täältä](https://www.co2signal.com/) - syötä sähköpostiosoitteesi sivun laatikkoon) sekä [alueesi koodin](http://api.electricitymap.org/v3/zones), joka vastaa [Electricity Map](https://www.electricitymap.org/map) -karttaa (esimerkiksi Bostonissa käytän 'US-NEISO').
![lataus käynnissä](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![lataus käynnissä](../../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun API-avain ja aluekoodi on syötetty laajennuksen käyttöliittymään, selaimen laajennuspalkin värillinen piste muuttuu heijastamaan alueesi energiankulutusta ja antaa sinulle vihjeitä siitä, millaisia raskaita toimintoja kannattaa tehdä. Tämän "pistejärjestelmän" konsepti tuli minulle [Energy Lollipop -selaimen laajennuksesta](https://energylollipop.com/) Kalifornian päästöjen seuraamiseen.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Käyttämällä tmrow'n CO2 Signal API:ta sähkönkulutuksen seuraamiseen, voit rakentaa selaimen laajennuksen, joka muistuttaa sinua suoraan selaimessa siitä, kuinka kuormittavaa alueesi sähkönkulutus on. Tämän laajennuksen satunnainen käyttö auttaa sinua tekemään harkittuja päätöksiä toimistasi tämän tiedon perusteella.
![laajennuksen kuvakaappaus](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.fi.png)
![laajennuksen kuvakaappaus](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.fi.png)
## Aloittaminen
@ -31,7 +31,7 @@ npm run build
Asentaaksesi laajennuksen Edge-selaimeen, käytä selaimen oikean yläkulman "kolmen pisteen" valikkoa löytääksesi Laajennukset-paneelin. Valitse sieltä "Lataa purkamaton" ladataksesi uuden laajennuksen. Avaa kehotteessa "dist"-kansio, ja laajennus latautuu. Käyttääksesi sitä, tarvitset API-avaimen CO2 Signal API:lle ([hanki avain sähköpostitse täältä](https://www.co2signal.com/) - syötä sähköpostiosoitteesi tämän sivun laatikkoon) sekä [alueesi koodin](http://api.electricitymap.org/v3/zones), joka vastaa [Electricity Map](https://www.electricitymap.org/map) -karttaa (esimerkiksi Bostonissa käytän koodia 'US-NEISO').
![asennus](../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.fi.png)
![asennus](../../../../translated_images/install-on-edge.78634f02842c4828.fi.png)
Kun API-avain ja alueen koodi on syötetty laajennuksen käyttöliittymään, selaimen laajennuspalkin värillinen piste muuttuu heijastamaan alueesi energiankulutusta ja antaa sinulle vihjeitä siitä, mitkä energiaintensiiviset toiminnot olisivat sopivia suorittaa. Tämän "piste"-järjestelmän konsepti on peräisin [Energy Lollipop -laajennuksesta](https://energylollipop.com/) Kalifornian päästöjen seurantaan.

@ -108,7 +108,7 @@ quadrantChart
UI Elements: [0.9, 0.1]
```
![canvasin ruudukko](../../../../translated_images/canvas_grid.5f209da785ded492a01ece440e3032afe51efa500cc2308e5ea4252487ceaf0b.fi.png)
![canvasin ruudukko](../../../../translated_images/canvas_grid.5f209da785ded492.fi.png)
> Kuva [MDN:stä](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
Canvas-elementille piirtäminen noudattaa samaa kolmen vaiheen prosessia, joka muodostaa kaikkien canvas-grafiikoiden perustan. Kun teet tämän muutaman kerran, se muuttuu toiseksi luonteeksi:
@ -329,11 +329,11 @@ Sinun tulee rakentaa verkkosivu, jossa on Canvas-elementti. Sen tulisi näyttä
- Sankarilaiva
![Sankarilaiva](../../../../translated_images/player.dd24c1afa8c71e9b82b2958946d4bad13308681392d4b5ddcc61a0e818ef8088.fi.png)
![Sankarilaiva](../../../../translated_images/player.dd24c1afa8c71e9b.fi.png)
- 5*5 hirviöjoukko
![Hirviölaiva](../../../../translated_images/enemyShip.5df2a822c16650c2fb3c06652e8ec8120cdb9122a6de46b9a1a56d54db22657f.fi.png)
![Hirviölaiva](../../../../translated_images/enemyShip.5df2a822c16650c2.fi.png)
### Suositellut kehitysvaiheet
@ -467,7 +467,7 @@ for (let x = START_X; x < STOP_X; x += ENEMY_SPACING) {
Valmis tulos näyttää tältä:
![Musta ruutu, jossa sankari ja 5*5 hirviötä](../../../../translated_images/partI-solution.36c53b48c9ffae2a5e15496b23b604ba5393433e4bf91608a7a0a020eb7a2691.fi.png)
![Musta ruutu, jossa sankari ja 5*5 hirviötä](../../../../translated_images/partI-solution.36c53b48c9ffae2a.fi.png)
## Ratkaisu

@ -160,7 +160,7 @@ sequenceDiagram
```
- **Pistejärjestelmä**: Jokainen tuhottu vihollisalus antaa 100 pistettä (pyöreät numerot ovat helpompia pelaajien laskea mielessään). Pisteet näytetään vasemmassa alakulmassa.
- **Elämälaskuri**: Sankarisi aloittaa kolmella elämällä standardi, jonka varhaiset arcade-pelit asettivat tasapainottamaan haastetta ja pelattavuutta. Jokainen törmäys viholliseen maksaa yhden elämän. Näytämme jäljellä olevat elämät oikeassa alakulmassa aluksen ikoneilla ![elämäkuva](../../../../translated_images/life.6fb9f50d53ee0413cd91aa411f7c296e10a1a6de5c4a4197c718b49bf7d63ebf.fi.png).
- **Elämälaskuri**: Sankarisi aloittaa kolmella elämällä standardi, jonka varhaiset arcade-pelit asettivat tasapainottamaan haastetta ja pelattavuutta. Jokainen törmäys viholliseen maksaa yhden elämän. Näytämme jäljellä olevat elämät oikeassa alakulmassa aluksen ikoneilla ![elämäkuva](../../../../translated_images/life.6fb9f50d53ee0413.fi.png).
## Aloitetaan rakentaminen!

@ -639,7 +639,7 @@ sequenceDiagram
`history.pushState` luo uusia merkintöjä selaimen navigointihistoriaan. Voit tarkistaa tämän pitämällä *takaisin-painiketta* painettuna selaimessasi, sen pitäisi näyttää jotain tällaista:
![Navigointihistorian kuvakaappaus](../../../../translated_images/history.7fdabbafa521e06455b738d3dafa3ff41d3071deae60ead8c7e0844b9ed987d8.fi.png)
![Navigointihistorian kuvakaappaus](../../../../translated_images/history.7fdabbafa521e064.fi.png)
Jos yrität klikata takaisin-painiketta muutaman kerran, huomaat, että nykyinen URL-osoite muuttuu ja historia päivittyy, mutta sama template pysyy näytettynä.

@ -295,7 +295,7 @@ Ensiksi tarkastellaan, mitä tapahtuu peruslomakkeen lähetyksessä:
2. Tarkkaile muutoksia selaimesi osoiterivillä
3. Huomaa, kuinka sivu latautuu uudelleen ja tiedot näkyvät URL-osoitteessa
![Kuvakaappaus selaimen URL-osoitteen muutoksesta Rekisteröidy-painikkeen klikkauksen jälkeen](../../../../translated_images/click-register.e89a30bf0d4bc9ca867dc537c4cea679a7c26368bd790969082f524fed2355bc.fi.png)
![Kuvakaappaus selaimen URL-osoitteen muutoksesta Rekisteröidy-painikkeen klikkauksen jälkeen](../../../../translated_images/click-register.e89a30bf0d4bc9ca.fi.png)
### HTTP-menetelmien vertailu
@ -350,7 +350,7 @@ Konfiguroidaan rekisteröintilomakkeesi kommunikoimaan oikein taustapalvelimen A
2. **Klikkaa** "Luo tili" -painiketta
3. **Tarkkaile** palvelimen vastausta selaimessasi
![Selaimen ikkuna osoitteessa localhost:5000/api/accounts, jossa näkyy JSON-merkkijono käyttäjätiedoilla](../../../../translated_images/form-post.61de4ca1b964d91a9e338416e19f218504dd0af5f762fbebabfe7ae80edf885f.fi.png)
![Selaimen ikkuna osoitteessa localhost:5000/api/accounts, jossa näkyy JSON-merkkijono käyttäjätiedoilla](../../../../translated_images/form-post.61de4ca1b964d91a.fi.png)
**Mitä sinun pitäisi nähdä:**
- **Selaimen uudelleenohjaus** API-päätepisteen URL-osoitteeseen
@ -554,7 +554,7 @@ async function register() {
3. **Klikkaa** "Luo tili"
4. **Tarkkaile** konsoliviestejä ja käyttäjäpalautetta
![Näyttökuva, jossa näkyy lokiviesti selaimen konsolissa](../../../../translated_images/browser-console.efaf0b51aaaf67782a29e1a0bb32cc063f189b18e894eb5926e02f1abe864ec2.fi.png)
![Näyttökuva, jossa näkyy lokiviesti selaimen konsolissa](../../../../translated_images/browser-console.efaf0b51aaaf6778.fi.png)
**Mitä sinun pitäisi nähdä:**
- **Lataustila** näkyy lähetyspainikkeessa
@ -729,7 +729,7 @@ Parannetaan rekisteröintilomakettasi vankalla validoinnilla, joka tarjoaa erino
3. **Kokeile** erikoismerkkejä käyttäjänimi-kentässä
4. **Anna** negatiivinen saldo
![Näyttökuva, jossa näkyy validointivirhe lomakkeen lähettämisen yhteydessä](../../../../translated_images/validation-error.8bd23e98d416c22f80076d04829a4bb718e0e550fd622862ef59008ccf0d5dce.fi.png)
![Näyttökuva, jossa näkyy validointivirhe lomakkeen lähettämisen yhteydessä](../../../../translated_images/validation-error.8bd23e98d416c22f.fi.png)
**Mitä huomaat:**
- **Selaimen näyttämät** natiivivalidointiviestit
@ -859,7 +859,7 @@ Näytä virheilmoitus HTML:ssä, jos käyttäjä on jo olemassa.
Tässä on esimerkki siitä, miltä lopullinen kirjautumissivu voi näyttää pienen tyylittelyn jälkeen:
![Näyttökuva kirjautumissivusta CSS-tyylien lisäämisen jälkeen](../../../../translated_images/result.96ef01f607bf856aa9789078633e94a4f7664d912f235efce2657299becca483.fi.png)
![Näyttökuva kirjautumissivusta CSS-tyylien lisäämisen jälkeen](../../../../translated_images/result.96ef01f607bf856a.fi.png)
## Luentojälkeinen kysely

@ -160,7 +160,7 @@ sequenceDiagram
Browser->>User: Displays new page (flash/reload)
```
![Päivitysprosessi monisivuisessa sovelluksessa](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.fi.png)
![Päivitysprosessi monisivuisessa sovelluksessa](../../../../translated_images/mpa.7f7375a1a2d4aa77.fi.png)
**Miksi tämä lähestymistapa tuntui kömpelöltä:**
- Jokainen klikkaus tarkoitti koko sivun uudelleenrakentamista
@ -187,7 +187,7 @@ sequenceDiagram
Browser->>User: Shows updated content (no reload)
```
![Päivitysprosessi yksisivuisessa sovelluksessa](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.fi.png)
![Päivitysprosessi yksisivuisessa sovelluksessa](../../../../translated_images/spa.268ec73b41f992c2.fi.png)
**Miksi SPA:t tuntuvat niin paljon paremmilta:**
- Vain ne osat, jotka oikeasti muuttuivat, päivitetään (fiksua, eikö?)
@ -515,7 +515,7 @@ if (data.error) {
Nyt kun testaat virheellisellä tilillä, näet hyödyllisen virheilmoituksen suoraan sivulla!
![Näyttökuva, jossa virheilmoitus näkyy kirjautumisen aikana](../../../../translated_images/login-error.416fe019b36a63276764c2349df5d99e04ebda54fefe60c715ee87a28d5d4ad0.fi.png)
![Näyttökuva, jossa virheilmoitus näkyy kirjautumisen aikana](../../../../translated_images/login-error.416fe019b36a6327.fi.png)
#### Vaihe 4: Ole inklusiivinen saavutettavuuden suhteen
@ -928,7 +928,7 @@ Valmis viemään pankkisovelluksesi seuraavalle tasolle? Tehdään siitä jotain
Tältä viimeistelty kojelauta voisi näyttää:
![Esimerkkikuva viimeistellystä kojelaudasta tyylittelyn jälkeen](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.fi.png)
![Esimerkkikuva viimeistellystä kojelaudasta tyylittelyn jälkeen](../../../../translated_images/screen2.123c82a831a1d14a.fi.png)
Sinun ei tarvitse kopioida tätä täysin - käytä sitä inspiraationa ja tee siitä oman näköisesi!

@ -190,7 +190,7 @@ Kuten Titanicin osastoitu rakenne, joka vaikutti vankalta, kunnes useat osastot
Sen sijaan, että juoksisimme ympyrää, luomme **keskitetyn tilanhallintajärjestelmän**. Ajattele sitä kuin yhtä todella järjestelmällistä henkilöä, joka vastaa kaikesta tärkeästä:
![Kaavio, joka näyttää datavirrat HTML:n, käyttäjän toimien ja tilan välillä](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.fi.png)
![Kaavio, joka näyttää datavirrat HTML:n, käyttäjän toimien ja tilan välillä](../../../../translated_images/data-flow.fa2354e0908fecc8.fi.png)
```mermaid
flowchart TD

@ -112,7 +112,7 @@ Katso [palvelimen API-dokumentaatio](../api/README.md) saadaksesi tietoa:
**Odotettu tulos:**
Tehtävän suorittamisen jälkeen pankkisovelluksessasi pitäisi olla täysin toimiva "Lisää tapahtuma" -ominaisuus, joka näyttää ja käyttäytyy ammattimaisesti:
![Näyttökuva esimerkkidialogista "Lisää tapahtuma"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.fi.png)
![Näyttökuva esimerkkidialogista "Lisää tapahtuma"](../../../../translated_images/dialog.93bba104afeb79f1.fi.png)
## Toteutuksen testaus

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Tässä projektissa opit rakentamaan kuvitteellisen pankin. Näissä oppitunneissa annetaan ohjeita siitä, miten verkkosovellus suunnitellaan ja reitit määritetään, miten lomakkeita rakennetaan, tilaa hallitaan ja tietoja haetaan API:sta, josta voit hakea pankin tiedot.
| ![Screen1](../../../translated_images/screen1.baccbba0f1f93364672eb250d2fbd21574bb1caf79a2155022dc098a741cbdfe.fi.png) | ![Screen2](../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.fi.png) |
| ![Screen1](../../../translated_images/screen1.baccbba0f1f93364.fi.png) | ![Screen2](../../../translated_images/screen2.123c82a831a1d14a.fi.png) |
|--------------------------------|--------------------------------|
## Oppitunnit

@ -185,7 +185,7 @@ Aivan kuten Alexander Graham Bellin puhelin yhdisti etäisiä paikkoja, GitHub-t
Kun kaikki on latautunut, näet kauniin ja selkeän työtilan, joka on suunniteltu pitämään sinut keskittyneenä siihen, mikä on tärkeää koodisi!
![VSCode.dev:n oletuskäyttöliittymä](../../../../translated_images/default-vscode-dev.5d06881d65c1b3234ce50cd9ed3b0028e6031ad5f5b441bcbed96bfa6311f6d0.fi.png)
![VSCode.dev:n oletuskäyttöliittymä](../../../../translated_images/default-vscode-dev.5d06881d65c1b323.fi.png)
**Tässä on kierros naapurustossa:**
- **Toimintopalkki** (vasemmalla oleva kaistale): Päänavigointisi, jossa on Explorer 📁, Search 🔍, Source Control 🌿, Extensions 🧩 ja Settings ⚙️
@ -233,7 +233,7 @@ Tämä on täydellinen, kun aloitat VSCode.devissä ja haluat avata tietyn repos
1. Siirry osoitteeseen [vscode.dev](https://vscode.dev), jos et ole jo siellä
2. Etsi "Open Remote Repository" -painike aloitusnäytöltä ja klikkaa sitä
![Avaa etärepositorio](../../../../translated_images/open-remote-repository.bd9c2598b8949e7fc283cdfc8f4050c6205a7c7c6d3f78c4b135115d037d6fa2.fi.png)
![Avaa etärepositorio](../../../../translated_images/open-remote-repository.bd9c2598b8949e7f.fi.png)
3. Liitä mikä tahansa GitHub-repositorion URL (kokeile tätä: `https://github.com/microsoft/Web-Dev-For-Beginners`)
4. Paina Enter ja katso, kuinka taikuus tapahtuu!
@ -242,7 +242,7 @@ Tämä on täydellinen, kun aloitat VSCode.devissä ja haluat avata tietyn repos
Haluatko tuntea itsesi koodausvelhoksi? Kokeile tätä näppäinyhdistelmää: Ctrl+Shift+P (tai Cmd+Shift+P Macilla) avataksesi komentopalettin:
![Komentopaletti](../../../../translated_images/palette-menu.4946174e07f426226afcdad707d19b8d5150e41591c751c45b5dee213affef91.fi.png)
![Komentopaletti](../../../../translated_images/palette-menu.4946174e07f42622.fi.png)
**Komentopaletti on kuin hakukone kaikelle, mitä voit tehdä:**
- Kirjoita "open remote", ja se löytää repositorion avaajan puolestasi
@ -304,7 +304,7 @@ Aivan kuten arkkitehdin toimistossa piirustusten järjestäminen, tiedostojen lu
3. Syötä tiedoston nimi, mukaan lukien oikea tiedostopääte (`style.css`, `script.js`, `index.html`)
4. Paina Enter luodaksesi tiedoston
![Uuden tiedoston luominen](../../../../translated_images/create-new-file.2814e609c2af9aeb6c6fd53156c503ac91c3d538f9cac63073b2dd4a7631f183.fi.png)
![Uuden tiedoston luominen](../../../../translated_images/create-new-file.2814e609c2af9aeb.fi.png)
**Nimeämiskäytännöt:**
- Käytä kuvailevia nimiä, jotka kertovat tiedoston tarkoituksen
@ -322,7 +322,7 @@ Tässä alkaa todellinen hauskuus! VSCode.dev:n editori on täynnä hyödyllisi
2. Aloita kirjoittaminen ja katso, kuinka VSCode.dev auttaa sinua väreillä, ehdotuksilla ja virheiden tunnistamisella
3. Tallenna työsi Ctrl+S (Windows/Linux) tai Cmd+S (Mac) vaikka se tallentaa automaattisesti!
![Tiedostojen muokkaaminen VSCode.devissä](../../../../translated_images/edit-a-file.52c0ee665ef19f08119d62d63f395dfefddc0a4deb9268d73bfe791f52c5807a.fi.png)
![Tiedostojen muokkaaminen VSCode.devissä](../../../../translated_images/edit-a-file.52c0ee665ef19f08.fi.png)
**Siistit jutut, jotka tapahtuvat koodatessasi:**
- Koodisi saa kauniin värikoodauksen, joten sitä on helppo lukea
@ -398,7 +398,7 @@ Laajennusmarkkinapaikka on todella hyvin järjestetty, joten et eksy etsiessäsi
2. Selaa tai etsi jotain tiettyä
3. Klikkaa mitä tahansa kiinnostavaa saadaksesi lisätietoja
![Laajennusmarkkinapaikan käyttöliittymä](../../../../translated_images/extensions.eca0e0c7f59a10b5c88be7fe24b3e32cca6b6058b35a49026c3a9d80b1813b7c.fi.png)
![Laajennusmarkkinapaikan käyttöliittymä](../../../../translated_images/extensions.eca0e0c7f59a10b5.fi.png)
**Mitä siellä näet:**
@ -451,7 +451,7 @@ Useimmissa laajennuksissa on asetuksia, joita voit säätää, jotta ne toimivat
3. Valitse "Laajennuksen asetukset" pudotusvalikosta
4. Säädä asetuksia, kunnes ne tuntuvat sopivilta työnkulullesi
![Laajennusasetusten räätälöinti](../../../../translated_images/extension-settings.21c752ae4f4cdb78a867f140ccd0680e04619d0c44bb4afb26373e54b829d934.fi.png)
![Laajennusasetusten räätälöinti](../../../../translated_images/extension-settings.21c752ae4f4cdb78.fi.png)
**Yleisiä asioita, joita saatat haluta säätää:**
- Miten koodisi muotoillaan (välilehdet vs välilyönnit, rivin pituus jne.)

@ -78,7 +78,7 @@ Koska VSCode.dev vaatii vähintään yhden tiedoston repositorion avaamiseen, lu
4. **Kirjoita** commit-viesti: "Lisätty alkuperäinen HTML-rakenne"
5. **Klikkaa** "Commit new file" tallentaaksesi muutokset
![Luodaan alkuperäinen tiedosto GitHubissa](../../../../translated_images/new-file-github.com.c886796d800e8056561829a181be1382c5303da9d902d8b2dd82b68a4806e21f.fi.png)
![Luodaan alkuperäinen tiedosto GitHubissa](../../../../translated_images/new-file-github.com.c886796d800e8056.fi.png)
**Mitä tämä alkuperäinen asetus saavuttaa:**
- **Luo** asianmukaisen HTML5-dokumenttirakenteen semanttisilla elementeillä
@ -104,7 +104,7 @@ Nyt kun repositorion perusta on luotu, siirrytään VSCode.dev:iin varsinaista k
**Onnistumisen merkki**: Näet projektitiedostosi Explorer-sivupalkissa ja `index.html`-tiedoston muokattavissa pääeditorialueella.
![Projekti ladattu VSCode.dev:ssä](../../../../translated_images/project-on-vscode.dev.e79815a9a95ee7feac72ebe5c941c91279716be37c575dbdbf2f43bea2c7d8b6.fi.png)
![Projekti ladattu VSCode.dev:ssä](../../../../translated_images/project-on-vscode.dev.e79815a9a95ee7fe.fi.png)
**Mitä näet käyttöliittymässä:**
- **Explorer-sivupalkki**: **Näyttää** repositorion tiedostot ja kansiorakenteen
@ -448,7 +448,7 @@ Laajennukset parantavat kehityskokemustasi tarjoamalla reaaliaikaisia esikatselu
**Välittömät tulokset asennuksen jälkeen:**
Kun CodeSwing on asennettu, näet ansioluettelosivustosi reaaliaikaisen esikatselun editorissa. Tämä mahdollistaa sen, että näet tarkalleen, miltä sivustosi näyttää tehdessäsi muutoksia.
![CodeSwing-laajennus näyttää reaaliaikaisen esikatselun](../../../../translated_images/after-codeswing-extension-pb.0ebddddcf73b550994947a9084e35e2836c713ae13839d49628e3c764c1cfe83.fi.png)
![CodeSwing-laajennus näyttää reaaliaikaisen esikatselun](../../../../translated_images/after-codeswing-extension-pb.0ebddddcf73b5509.fi.png)
**Parannetun käyttöliittymän ymmärtäminen:**
- **Jaettu näkymä**: **Näyttää** koodisi toisella puolella ja reaaliaikaisen esikatselun toisella

@ -61,7 +61,7 @@ print(response.choices[0].message.content)
Tältä valmis projektisi näyttää:
![Keskustelusovelluksen käyttöliittymä, jossa näkyy keskustelu käyttäjän ja tekoälyavustajan välillä](../../../translated_images/screenshot.0a1ee0d123df681b4501eb53ffb267519fcc20aa653eabecef1e7561ddfb1cab.fi.png)
![Keskustelusovelluksen käyttöliittymä, jossa näkyy keskustelu käyttäjän ja tekoälyavustajan välillä](../../../translated_images/screenshot.0a1ee0d123df681b.fi.png)
## 🗺️ Oppimismatka tekoälysovellusten kehittämiseen
@ -194,7 +194,7 @@ mindmap
**Keskeinen periaate**: Tekoälysovellusten kehitys yhdistää perinteiset verkkokehitystaidot tekoälypalveluiden integrointiin, luoden älykkäitä sovelluksia, jotka tuntuvat käyttäjille luonnollisilta ja reagoivilta.
![GitHub Models AI Playground -käyttöliittymä, jossa mallin valinta ja testausalue](../../../translated_images/playground.d2b927122224ff8ff4028fc842176e353c339147d8925455f36c92fb1655c477.fi.png)
![GitHub Models AI Playground -käyttöliittymä, jossa mallin valinta ja testausalue](../../../translated_images/playground.d2b927122224ff8f.fi.png)
**Mikä tekee Playgroundista niin hyödyllisen:**
- **Kokeile** eri tekoälymalleja, kuten GPT-4o-mini, Claude ja muita (kaikki ilmaisia!)
@ -204,7 +204,7 @@ mindmap
Kun olet kokeillut hieman, klikkaa vain "Code"-välilehteä ja valitse ohjelmointikieli saadaksesi toteutuskoodin, jota tarvitset.
![Playground-vaihtoehto, jossa näkyy koodin generointivaihtoehdot eri ohjelmointikielille](../../../translated_images/playground-choice.1d23ba7d407f47584c9f446c77f0bcf70cae794cc9c8d7849a3cca4a3693e6c4.fi.png)
![Playground-vaihtoehto, jossa näkyy koodin generointivaihtoehdot eri ohjelmointikielille](../../../translated_images/playground-choice.1d23ba7d407f4758.fi.png)
## Python-taustaintegraation asettaminen
@ -2141,14 +2141,14 @@ Haluatko kokeilla tätä projektia pilvipohjaisessa kehitysympäristössä? GitH
- **Siirry** [Web Dev For Beginners -repositoryyn](https://github.com/microsoft/Web-Dev-For-Beginners)
- **Klikkaa** "Use this template" oikeassa yläkulmassa (varmista, että olet kirjautunut GitHubiin)
![Luo mallista -käyttöliittymä, jossa näkyy vihreä "Use this template" -painike](../../../translated_images/template.67ad477109d29a2b04599a83c964c87fcde041256d4f04d3589cbb00c696f76c.fi.png)
![Luo mallista -käyttöliittymä, jossa näkyy vihreä "Use this template" -painike](../../../translated_images/template.67ad477109d29a2b.fi.png)
**Vaihe 2: Käynnistä Codespaces**
- **Avaa** juuri luomasi repository
- **Klikkaa** vihreää "Code"-painiketta ja valitse "Codespaces"
- **Valitse** "Create codespace on main" aloittaaksesi kehitysympäristön
![Luo Codespace -käyttöliittymä, jossa näkyy vaihtoehdot pilvipohjaisen kehitysympäristön käynnistämiseen](../../../translated_images/codespace.bcecbdf5d2747d3d17da67a78ad911c8853d68102e34748ec372cde1e9236e1d.fi.png)
![Luo Codespace -käyttöliittymä, jossa näkyy vaihtoehdot pilvipohjaisen kehitysympäristön käynnistämiseen](../../../translated_images/codespace.bcecbdf5d2747d3d.fi.png)
**Vaihe 3: Ympäristön konfigurointi**
Kun Codespace latautuu, sinulla on käytössäsi:

@ -1,261 +1,280 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "63e29f5a308b533df9d70336bbb2e2b8",
"translation_date": "2025-11-25T17:54:13+00:00",
"original_hash": "fea3a0fceb8ad86fd640c09cf63a2aac",
"translation_date": "2026-01-07T01:01:45+00:00",
"source_file": "README.md",
"language_code": "fi"
}
-->
[![GitHub license](https://img.shields.io/github/license/microsoft/Web-Dev-For-Beginners.svg)](https://github.com/microsoft/Web-Dev-For-Beginners/blob/master/LICENSE)
[![GitHub contributors](https://img.shields.io/github/contributors/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/graphs/contributors/)
[![GitHub issues](https://img.shields.io/github/issues/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/issues/)
[![GitHub pull-requests](https://img.shields.io/github/issues-pr/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/pulls/)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![GitHub license](https://img.shields.io/github/license/microsoft/Web-Dev-For-Beginners.svg)](https://github.com/microsoft/Web-Dev-For-Beginners/blob/master/LICENSE)
[![GitHub contributors](https://img.shields.io/github/contributors/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/graphs/contributors/)
[![GitHub issues](https://img.shields.io/github/issues/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/issues/)
[![GitHub pull-requests](https://img.shields.io/github/issues-pr/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/pulls/)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![GitHub watchers](https://img.shields.io/github/watchers/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Watch&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/watchers/)
[![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Fork&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/network/)
[![GitHub stars](https://img.shields.io/github/stars/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/stargazers/)
[![GitHub watchers](https://img.shields.io/github/watchers/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Watch&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/watchers/)
[![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Fork&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/network/)
[![GitHub stars](https://img.shields.io/github/stars/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/stargazers/)
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
# Verkkokehitys aloittelijoille - Opetussuunnitelma
# Verkkokehitys aloittelijoille - Opetussuunnitelma
Opi verkkokehityksen perusteet Microsoft Cloud Advocatesin 12 viikon kattavalla kurssilla. Jokainen 24 oppitunnista käsittelee JavaScriptiä, CSS:ää ja HTML:ää käytännön projektien, kuten terraarioiden, selainlaajennusten ja avaruuspelien, kautta. Osallistu visoihin, keskusteluihin ja käytännön tehtäviin. Paranna taitojasi ja optimoi oppimisesi tehokkaalla projektipohjaisella lähestymistavallamme. Aloita koodausmatkasi jo tänään!
Opi verkkokehityksen perusteet Microsoft Cloud Advocatesin 12 viikon kattavassa kurssissa. Jokainen 24 oppitunnista syventyy JavaScriptiin, CSS:ään ja HTML:ään käytännön projektien, kuten terrarionien, selainlaajennusten ja avaruuspeliensä kautta. Osallistu tietovisailuihin, keskusteluihin ja käytännön tehtäviin. Kehitä taitojasi ja optimoi oppimisesi tehokkaan projektioppimisen menetelmämme avulla. Aloita koodausmatkasi jo tänään!
Liity Azure AI Foundry Discord -yhteisöön
Liity Azure AI Foundry Discord -yhteisöön
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
Seuraa näitä ohjeita aloittaaksesi näiden resurssien käytön:
1. **Haarauta arkisto**: Klikkaa [![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-beginners.svg?style=social&label=Fork)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/fork)
2. **Kloonaa arkisto**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
3. [**Liity Azure AI Foundry Discordiin ja tapaa asiantuntijoita ja muita kehittäjiä**](https://discord.com/invite/ByRwuEEgH4)
Noudata näitä ohjeita aloittaaksesi näiden resurssien käytön:
1. **Forkkaa repositorio**: Klikkaa [![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-beginners.svg?style=social&label=Fork)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/fork)
2. **Kloonaa repositorio**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
3. [**Liity Azure AI Foundry Discordiin ja tapaa asiantuntijoita sekä muita kehittäjiä**](https://discord.com/invite/ByRwuEEgH4)
### 🌐 Monikielinen tuki
### 🌐 Monikielinen tuki
#### Tuettu GitHub Actionin kautta (automaattinen ja aina ajan tasalla)
#### Tuettu GitHub Actionin kautta (Automaattinen & aina ajan tasalla)
<!-- CO-OP TRANSLATOR LANGUAGES TABLE START -->
[Arabic](../ar/README.md) | [Bengali](../bn/README.md) | [Bulgarian](../bg/README.md) | [Burmese (Myanmar)](../my/README.md) | [Chinese (Simplified)](../zh/README.md) | [Chinese (Traditional, Hong Kong)](../hk/README.md) | [Chinese (Traditional, Macau)](../mo/README.md) | [Chinese (Traditional, Taiwan)](../tw/README.md) | [Croatian](../hr/README.md) | [Czech](../cs/README.md) | [Danish](../da/README.md) | [Dutch](../nl/README.md) | [Estonian](../et/README.md) | [Finnish](./README.md) | [French](../fr/README.md) | [German](../de/README.md) | [Greek](../el/README.md) | [Hebrew](../he/README.md) | [Hindi](../hi/README.md) | [Hungarian](../hu/README.md) | [Indonesian](../id/README.md) | [Italian](../it/README.md) | [Japanese](../ja/README.md) | [Korean](../ko/README.md) | [Lithuanian](../lt/README.md) | [Malay](../ms/README.md) | [Marathi](../mr/README.md) | [Nepali](../ne/README.md) | [Norwegian](../no/README.md) | [Persian (Farsi)](../fa/README.md) | [Polish](../pl/README.md) | [Portuguese (Brazil)](../br/README.md) | [Portuguese (Portugal)](../pt/README.md) | [Punjabi (Gurmukhi)](../pa/README.md) | [Romanian](../ro/README.md) | [Russian](../ru/README.md) | [Serbian (Cyrillic)](../sr/README.md) | [Slovak](../sk/README.md) | [Slovenian](../sl/README.md) | [Spanish](../es/README.md) | [Swahili](../sw/README.md) | [Swedish](../sv/README.md) | [Tagalog (Filipino)](../tl/README.md) | [Tamil](../ta/README.md) | [Thai](../th/README.md) | [Turkish](../tr/README.md) | [Ukrainian](../uk/README.md) | [Urdu](../ur/README.md) | [Vietnamese](../vi/README.md)
<!-- CO-OP TRANSLATOR LANGUAGES TABLE END -->
<!-- CO-OP TRANSLATOR LANGUAGES TABLE START -->
[Arabic](../ar/README.md) | [Bengali](../bn/README.md) | [Bulgarian](../bg/README.md) | [Burmese (Myanmar)](../my/README.md) | [Chinese (Simplified)](../zh/README.md) | [Chinese (Traditional, Hong Kong)](../hk/README.md) | [Chinese (Traditional, Macau)](../mo/README.md) | [Chinese (Traditional, Taiwan)](../tw/README.md) | [Croatian](../hr/README.md) | [Czech](../cs/README.md) | [Danish](../da/README.md) | [Dutch](../nl/README.md) | [Estonian](../et/README.md) | [Finnish](./README.md) | [French](../fr/README.md) | [German](../de/README.md) | [Greek](../el/README.md) | [Hebrew](../he/README.md) | [Hindi](../hi/README.md) | [Hungarian](../hu/README.md) | [Indonesian](../id/README.md) | [Italian](../it/README.md) | [Japanese](../ja/README.md) | [Kannada](../kn/README.md) | [Korean](../ko/README.md) | [Lithuanian](../lt/README.md) | [Malay](../ms/README.md) | [Malayalam](../ml/README.md) | [Marathi](../mr/README.md) | [Nepali](../ne/README.md) | [Nigerian Pidgin](../pcm/README.md) | [Norwegian](../no/README.md) | [Persian (Farsi)](../fa/README.md) | [Polish](../pl/README.md) | [Portuguese (Brazil)](../br/README.md) | [Portuguese (Portugal)](../pt/README.md) | [Punjabi (Gurmukhi)](../pa/README.md) | [Romanian](../ro/README.md) | [Russian](../ru/README.md) | [Serbian (Cyrillic)](../sr/README.md) | [Slovak](../sk/README.md) | [Slovenian](../sl/README.md) | [Spanish](../es/README.md) | [Swahili](../sw/README.md) | [Swedish](../sv/README.md) | [Tagalog (Filipino)](../tl/README.md) | [Tamil](../ta/README.md) | [Telugu](../te/README.md) | [Thai](../th/README.md) | [Turkish](../tr/README.md) | [Ukrainian](../uk/README.md) | [Urdu](../ur/README.md) | [Vietnamese](../vi/README.md)
**Jos haluat lisätä uusia käännöksiä, tuetut kielet löytyvät [täältä](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
> **Haluatko kloonata paikallisesti?**
[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20Visual%20Studio%20Code&labelColor=2c2c32&color=007acc&logoColor=007acc)](https://open.vscode.dev/microsoft/Web-Dev-For-Beginners)
> Tämä repositorio sisältää yli 50 kielen käännökset, mikä lisää merkittävästi latauskokoa. Jos haluat kloonata ilman käännöksiä, käytä sparse checkoutia:
> ```bash
> git clone --filter=blob:none --sparse https://github.com/microsoft/Web-Dev-For-Beginners.git
> cd Web-Dev-For-Beginners
> git sparse-checkout set --no-cone '/*' '!translations' '!translated_images'
> ```
> Saat kaiken tarvitsemasi kurssin suorittamiseen huomattavasti nopeammalla latauksella.
<!-- CO-OP TRANSLATOR LANGUAGES TABLE END -->
#### 🧑‍🎓 _Oletko opiskelija?_
**Jos haluat lisää tuettuja käännöskieliä, ne on listattu [tässä](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
Vieraile [**Student Hub -sivulla**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon), josta löydät aloitteleville suunnattuja resursseja, opiskelijapaketit ja jopa tapoja saada ilmainen sertifikaattivoucher. Tämä on sivu, jonka haluat tallentaa kirjanmerkkeihin ja tarkistaa säännöllisesti, sillä sisältö vaihtuu kuukausittain.
[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20Visual%20Studio%20Code&labelColor=2c2c32&color=007acc&logoColor=007acc)](https://open.vscode.dev/microsoft/Web-Dev-For-Beginners)
### 📣 Ilmoitus - Uusia GitHub Copilot Agent -haasteita!
#### 🧑‍🎓 _Oletko opiskelija?_
Uusi haaste lisätty, etsi "GitHub Copilot Agent Challenge 🚀" useimmista luvuista. Tämä on uusi haaste, jonka voit suorittaa GitHub Copilotin ja Agent-tilan avulla. Jos et ole käyttänyt Agent-tilaa aiemmin, se ei vain luo tekstiä, vaan voi myös luoda ja muokata tiedostoja, suorittaa komentoja ja paljon muuta.
Vieraile [**Student Hub -sivulla**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon), jolta löydät aloittelijan resurssit, opiskelijapaketit ja jopa tapoja saada ilmainen sertifikaattikuponki. Tämä on sivu, jonka haluat lisätä kirjanmerkkeihin ja tarkistaa säännöllisesti, sillä päivitämme sisältöä kuukausittain.
### 📣 Ilmoitus - _Uusi projekti Generative AI:n avulla_
### 📣 Ilmoitus - Uudet GitHub Copilot Agent -tilan haasteet suoritettaviksi!
Uusi AI Assistant -projekti on juuri lisätty, tutustu siihen [projekti](./09-chat-project/README.md)
Uusi haaste lisätty, etsi "GitHub Copilot Agent Challenge 🚀" useimmista luvuista. Tämä on uusi haaste, jonka suoritat GitHub Copilotin ja Agent-tilan avulla. Jos et ole käyttänyt Agent-tilaa aiemmin, se pystyy paitsi tuottamaan tekstiä, myös luomaan ja muokkaamaan tiedostoja, suorittamaan komentoja ja paljon muuta.
### 📣 Ilmoitus - _Uusi opetussuunnitelma_ Generative AI:sta JavaScriptille julkaistu
### 📣 Ilmoitus - _Uusi Generatiivisen tekoälyn projekti_
Älä missaa uutta Generative AI -opetussuunnitelmaamme!
Uusi AI-avustajaprojekti juuri lisätty, tutustu projektiin [tästä](./9-chat-project/README.md)
Vieraile [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) aloittaaksesi!
### 📣 Ilmoitus - _Uusi opetussuunnitelma_ Generatiivisesta tekoälystä JavaScriptille julkaistu
![Tausta](../../translated_images/background.148a8d43afde57303419a663f50daf586681bc2fabf833f66ef6954073983c66.fi.png)
Älä jää paitsi uudesta Generatiivisen AI:n opetussuunnitelmastamme!
- Oppitunteja, jotka kattavat kaiken perusteista RAG:iin.
- Keskustele historiallisten hahmojen kanssa GenAI:n ja kumppanisovelluksemme avulla.
- Hauska ja mukaansatempaava tarina, jossa matkustat ajassa!
Käy osoitteessa [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) aloittaaksesi!
![hahmo](../../translated_images/character.5c0dd8e067ffd693c16e2c5b7412ab075a2215ce31f998305639fa3a05e14fbe.fi.png)
![Background](../../translated_images/background.148a8d43afde5730.fi.png)
Jokainen oppitunti sisältää tehtävän, tietotestin ja haasteen, jotka ohjaavat sinua oppimaan aiheita, kuten:
- Kehotus ja kehotustekniikat
- Teksti- ja kuvasovellusten luominen
- Hakusovellukset
- Oppitunnit kattavat kaiken perusteista RAG:iin.
- Vuorovaikutus historiallisten hahmojen kanssa GenAI:n ja lisäsovelluksemme kautta.
- Hauska ja mukaansatempaava tarinankerronta, matkustat ajassa!
Vieraile [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) aloittaaksesi!
![character](../../translated_images/character.5c0dd8e067ffd693.fi.png)
## 🌱 Aloittaminen
> **Opettajat**, olemme [lisänneet joitakin ehdotuksia](for-teachers.md) tämän opetussuunnitelman käyttöön. Haluaisimme kuulla palautettanne [keskustelufoorumillamme](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
Jokaisessa oppitunnissa on tehtävä suoritettavaksi, tietoarviointi ja haaste, jotka ohjaavat sinua oppimaan aiheista kuten:
- Kehotteen kirjoittaminen ja kehoteinsinööritys
- Teksti- ja kuva-applikaatioiden generointi
- Hakusovellukset
**[Oppijat](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, jokaisessa oppitunnissa aloita ennakkotestillä ja jatka lukemalla oppimateriaali, suorittamalla erilaisia aktiviteetteja ja tarkista ymmärryksesi jälkitestillä.
Käy osoitteessa [https://aka.ms/genai-js-course](../../[https:/aka.ms/genai-js-course) aloittaaksesi!
Parantaaksesi oppimiskokemustasi, yhdistä voimasi muiden kanssa työskennelläksesi projekteissa yhdessä! Keskustelut ovat tervetulleita [keskustelufoorumillamme](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), jossa moderaattoritiimimme vastaa kysymyksiisi.
Jatkaaksesi oppimistasi suosittelemme tutustumaan [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) -sivustoon lisämateriaalien löytämiseksi.
### 📋 Ympäristön asettaminen
## 🌱 Aloittaminen
Tämä opetussuunnitelma sisältää valmiin kehitysympäristön! Aloittaessasi voit valita, haluatko suorittaa opetussuunnitelman [Codespacessa](https://github.com/features/codespaces/) (_selaimessa toimiva ympäristö, ei asennuksia tarvita_) vai paikallisesti tietokoneellasi käyttämällä tekstieditoria, kuten [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
> **Opettajat**, olemme [lisänneet joitakin ehdotuksia](for-teachers.md) siitä, miten tätä opetussuunnitelmaa voi käyttää. Haluaisimme saada palautetta [keskustelufoorumillamme](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
#### Luo oma arkistosi
Jotta voit helposti tallentaa työsi, suosittelemme luomaan oman kopion tästä arkistosta. Voit tehdä tämän klikkaamalla **Käytä tätä mallia** -painiketta sivun yläosassa. Tämä luo uuden arkiston GitHub-tilillesi kopiona opetussuunnitelmasta.
**[Oppijat](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, jokaista oppituntia varten aloita esiluentotestillä ja jatka luentomateriaalin lukemisella, erilaisten aktiviteettien suorittamisella ja tarkista ymmärryksesi jälkiluentotestillä.
Seuraa näitä ohjeita:
1. **Haarauta arkisto**: Klikkaa "Fork"-painiketta tämän sivun oikeassa yläkulmassa.
2. **Kloonaa arkisto**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
Paranna oppimiskokemustasi yhdistämällä vertaisryhmiesi kanssa projektityöhön! Keskusteluja suositellaan [keskustelufoorumillamme](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), jossa moderaattoritiimimme on valmiina vastaamaan kysymyksiisi.
#### Opetussuunnitelman suorittaminen Codespacessa
Jatkaaksesi opiskelua suosittelemme vahvasti tutustumaan [Microsoft Learniin](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) lisäoppimateriaalien saamiseksi.
Omassa kopiossasi tästä arkistosta, jonka loit, klikkaa **Code**-painiketta ja valitse **Open with Codespaces**. Tämä luo uuden Codespacen, jossa voit työskennellä.
### 📋 Ympäristön pystyttäminen
![Codespace](../../translated_images/createcodespace.0238bbf4d7a8d955fa8fa7f7b6602a3cb6499a24708fbee589f83211c5a613b7.fi.png)
Tässä opetussuunnitelmassa on valmiiksi määritetty kehitysympäristö! Voit aloittaessasi valita suorittavasi opetussuunnitelman [Codespacessa](https://github.com/features/codespaces/) (_selainnäkymäinen, asennuksia ei tarvita_), tai paikallisesti tietokoneellasi tekstieditorilla, kuten [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
#### Opetussuunnitelman suorittaminen paikallisesti tietokoneellasi
#### Luo oma repositoriosi
Työsi tallentamisen helpottamiseksi on suositeltavaa luoda oma kopiosi tästä repositoriosta. Voit tehdä sen klikkaamalla sivun ylälaidasta kohtaa **Use this template**. Tämä luo uuden repositorion GitHub-tilillesi kopiona opetussuunnitelmasta.
Suorittaaksesi tämän opetussuunnitelman paikallisesti tietokoneellasi, tarvitset tekstieditorin, selaimen ja komentorivityökalun. Ensimmäinen oppituntimme, [Johdanto ohjelmointikieliin ja työkaluihin](../../1-getting-started-lessons/1-intro-to-programming-languages), opastaa sinut eri vaihtoehtojen läpi, jotta voit valita itsellesi parhaiten sopivat työkalut.
Noudata näitä ohjeita:
1. **Forkkaa repositorio**: Klikkaa oikeasta yläkulmasta "Fork".
2. **Kloonaa repositorio**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
Suosituksemme on käyttää [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) -editoria, jossa on myös sisäänrakennettu [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon). Voit ladata Visual Studio Coden [täältä](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
#### Opetussuunnitelman suorittaminen Codespacessa
1. Kloonaa arkistosi tietokoneellesi. Voit tehdä tämän klikkaamalla **Code**-painiketta ja kopioimalla URL-osoitteen:
Omassa kopiossasi tästä repositoriosta, jonka loit, klikkaa **Code** ja valitse **Open with Codespaces**. Tämä luo sinulle uuden Codespace-työtilan.
[CodeSpace](./images/createcodespace.png)
![Codespace](../../translated_images/createcodespace.0238bbf4d7a8d955.fi.png)
Avaa sitten [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) [Visual Studio Codessa](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) ja suorita seuraava komento, korvaten `<your-repository-url>` juuri kopioimallasi URL-osoitteella:
#### Opetussuunnitelman suorittaminen paikallisesti tietokoneella
Jos haluat suorittaa opetussuunnitelman paikallisesti tietokoneellasi, tarvitset tekstieditorin, selaimen ja komentorivityökalun. Ensimmäinen oppituntimme, [Ohjelmointikieliin ja työkaluisiin perehtyminen](../../1-getting-started-lessons/1-intro-to-programming-languages), opastaa sinut eri vaihtoehdoissa kuhunkin näistä työkaluista, jotta voit valita sinulle parhaiten sopivat.
Suosittelemme käyttämään editorina [Visual Studio Codea](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon), joka sisältää myös sisäänrakennetun [Päätteen](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon). Voit ladata Visual Studio Coden [tästä](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
1. Kloonaa repositoriosi tietokoneellesi. Voit tehdä tämän klikkaamalla **Code** ja kopioimalla URL-osoitteen:
[CodeSpace](./images/createcodespace.png)
Sitten avaa [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) -sovelluksessa ja suorita seuraava komento korvaten `<your-repository-url>` äsken kopioimallasi URL-osoitteella:
```bash
git clone <your-repository-url>
```
2. Avaa kansio Visual Studio Codessa. Voit tehdä tämän klikkaamalla **File** > **Open Folder** ja valitsemalla juuri kloonaamasi kansion.
> Suositellut Visual Studio Code -laajennukset:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - HTML-sivujen esikatseluun Visual Studio Codessa
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - auttaa sinua kirjoittamaan koodia nopeammin
2. Avaa kansio Visual Studio Codessa. Voit tehdä tämän valitsemalla **File** > **Open Folder** ja valitsemalla juuri kloonatun kansion.
> Suositellut Visual Studio Code -laajennukset:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - HTML-sivujen esikatseluun suoraan Visual Studio Codessa
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - auttamaan koodin kirjoittamisessa nopeammin
## 📂 Jokainen oppitunti sisältää:
- valinnainen luonnosmuistiinpano
- valinnainen lisävideo
- alkulämmittelykysely ennen oppituntia
- kirjallinen oppitunti
- projektipohjaisissa oppitunneissa vaiheittaiset ohjeet projektin rakentamiseen
- tietojen tarkistukset
- haaste
- valinnaisen muistion
- valinnaisen lisävideo
- ennakkoharjoituksen / lämmittelykyselyn
- kirjallisen oppitunnin
- projektipohjaisissa oppitunneissa ohjeet projektin rakentamiseen vaihe vaiheelta
- tietotarkistuksia
- haasteen
- lisälukemista
- tehtävä
- [kysely oppitunnin jälkeen](https://ff-quizzes.netlify.app/web/)
- tehtävän
- [jälkioppitunnin kyselyn](https://ff-quizzes.netlify.app/web/)
> **Huomio kyselyistä**: Kaikki kyselyt löytyvät Quiz-app-kansiosta, yhteensä 48 kyselyä, joissa jokaisessa on kolme kysymystä. Ne ovat saatavilla [ällä](https://ff-quizzes.netlify.app/web/), ja kyselysovelluksen voi ajaa paikallisesti tai julkaista Azureen; seuraa ohjeita `quiz-app`-kansiossa.
> **Huomautus kyselyistä**: Kaikki kyselyt löytyvät Quiz-app-kansiosta, yhteensä 48 kyselyä, joissa jokaisessa on kolme kysymystä. Ne ovat saatavilla [ssä](https://ff-quizzes.netlify.app/web/). Kyselysovellus voidaan suorittaa paikallisesti tai ottaa käyttöön Azureen; noudata ohjeita `quiz-app`-kansiossa.
## 🗃️ Oppitunnit
| | Projektin nimi | Opetettavat käsitteet | Oppimistavoitteet | Linkitetty oppitunti | Tekijä |
| :-: | :------------------------------------------------------: | :--------------------------------------------------------------------: | ----------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------: | :---------------------: |
| 01 | Aloitetaan | Johdatus ohjelmointiin ja työkaluihin | Opi ohjelmointikielten perusperiaatteet ja ohjelmistot, jotka auttavat ammattilaiskehittäjiä työssään | [Johdatus ohjelmointikieliin ja työkaluihin](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Aloitetaan | GitHubin perusteet, sisältää tiimityöskentelyn | Kuinka käyttää GitHubia projektissasi ja tehdä yhteistyötä muiden kanssa koodipohjassa | [Johdatus GitHubiin](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Aloitetaan | Saavutettavuus | Opi verkkosaavutettavuuden perusteet | [Saavutettavuuden perusteet](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS:n perusteet | JavaScriptin tietotyypit | JavaScriptin tietotyyppien perusteet | [Tietotyypit](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS:n perusteet | Funktiot ja metodit | Opi funktioista ja metodeista sovelluksen logiikan hallintaan | [Funktiot ja metodit](./2-js-basics/2-functions-methods/README.md) | Jasmine ja Christopher |
| 06 | JS:n perusteet | Päätöksenteko JS:llä | Opi luomaan ehtoja koodissasi päätöksentekomenetelmien avulla | [Päätöksenteko](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS:n perusteet | Taulukot ja silmukat | Työskentele datan kanssa JavaScriptin taulukoiden ja silmukoiden avulla | [Taulukot ja silmukat](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terraario](./3-terrarium/solution/README.md) | HTML käytännössä | Rakenna HTML luodaksesi verkkoterraarion, keskittyen asettelun rakentamiseen | [Johdatus HTML:ään](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terraario](./3-terrarium/solution/README.md) | CSS käytännössä | Rakenna CSS tyylittääksesi verkkoterraarion, keskittyen CSS:n perusteisiin, mukaan lukien sivun responsiivisuus | [Johdatus CSS:ään](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terraario](./3-terrarium/solution/README.md) | JavaScriptin sulkeumat, DOM-manipulointi | Rakenna JavaScript, jotta terraario toimii vedä/pudota-käyttöliittymänä, keskittyen sulkeumiin ja DOM-manipulointiin | [JavaScriptin sulkeumat, DOM-manipulointi](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Kirjoituspeli](./4-typing-game/solution/README.md) | Rakenna kirjoituspeli | Opi käyttämään näppäimistötapahtumia JavaScript-sovelluksesi logiikan ohjaamiseen | [Tapahtumapohjainen ohjelmointi](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Vihreä selainlaajennus](./5-browser-extension/solution/README.md) | Työskentely selainten kanssa | Opi, miten selaimet toimivat, niiden historia ja miten luoda selainlaajennuksen ensimmäiset elementit | [Tietoa selaimista](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Vihreä selainlaajennus](./5-browser-extension/solution/README.md) | Lomakkeen rakentaminen, API-kutsut ja muuttujien tallentaminen paikallisesti | Rakenna selainlaajennuksesi JavaScript-elementit kutsumaan API:a käyttäen paikallisesti tallennettuja muuttujia | [API:t, lomakkeet ja paikallinen tallennus](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Vihreä selainlaajennus](./5-browser-extension/solution/README.md) | Taustaprosessit selaimessa, verkkosuorituskyky | Käytä selaimen taustaprosesseja hallitsemaan laajennuksen kuvaketta; opi verkkosuorituskyvystä ja optimoinneista | [Taustatehtävät ja suorituskyky](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Avaruuspeli](./6-space-game/solution/README.md) | Edistyneempi pelikehitys JavaScriptillä | Opi perimästä käyttäen sekä luokkia että koostumusta sekä Pub/Sub-mallia pelin rakentamisen valmistelussa | [Johdatus edistyneeseen pelikehitykseen](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Avaruuspeli](./6-space-game/solution/README.md) | Piirtäminen kankaalle | Opi Canvas API:sta, jota käytetään elementtien piirtämiseen näytölle | [Piirtäminen kankaalle](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Avaruuspeli](./6-space-game/solution/README.md) | Elementtien liikuttaminen näytöllä | Opi, miten elementit voivat liikkua käyttäen koordinaatistoa ja Canvas API:a | [Elementtien liikuttaminen](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Avaruuspeli](./6-space-game/solution/README.md) | Törmäyksen tunnistus | Tee elementeistä törmääviä ja reagoivia toisiinsa näppäinpainallusten avulla ja tarjoa viivefunktio pelin suorituskyvyn varmistamiseksi | [Törmäyksen tunnistus](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Avaruuspeli](./6-space-game/solution/README.md) | Pisteiden laskeminen | Suorita matemaattisia laskelmia pelin tilan ja suorituskyvyn perusteella | [Pisteiden laskeminen](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Avaruuspeli](./6-space-game/solution/README.md) | Pelin lopettaminen ja uudelleenkäynnistys | Opi pelin lopettamisesta ja uudelleenkäynnistämisestä, mukaan lukien resurssien siivoaminen ja muuttujien arvojen palauttaminen | [Lopetusehto](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Pankkisovellus](./7-bank-project/solution/README.md) | HTML-mallit ja reitit verkkosovelluksessa | Opi luomaan monisivuisen verkkosivuston arkkitehtuurin perusta käyttäen reititystä ja HTML-malleja | [HTML-mallit ja reitit](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Pankkisovellus](./7-bank-project/solution/README.md) | Kirjautumis- ja rekisteröintilomakkeen rakentaminen | Opi rakentamaan lomakkeita ja käsittelemään validointirutiineja | [Lomakkeet](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Pankkisovellus](./7-bank-project/solution/README.md) | Datan hakemisen ja käytön menetelmät | Miten data virtaa sovellukseesi, miten sitä haetaan, tallennetaan ja hävitetään | [Data](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Pankkisovellus](./7-bank-project/solution/README.md) | Tilanhallinnan käsitteet | Opi, miten sovelluksesi säilyttää tilan ja miten sitä hallitaan ohjelmallisesti | [Tilanhallinta](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Selain/VSCode-koodi](../../8-code-editor) | Työskentely VSCode:lla | Opi käyttämään koodieditoria | [Käytä VSCode-koodieditoria](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI-avustajat](./9-chat-project/README.md) | Työskentely tekoälyn kanssa | Opi rakentamaan oma tekoälyavustaja | [Tekoälyavustajaprojekti](./9-chat-project/README.md) | Chris |
| | Projektin nimi | Opitut käsitteet | Oppimistavoitteet | Linkitetty oppitunti | Tekijä |
| :-: | :--------------------------------------------------------: | :--------------------------------------------------------------------: | ----------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------: | :---------------------: |
| 01 | Aloittaminen | Johdatus ohjelmointiin ja työkaluihin | Opit ohjelmointikielten perustan ja ohjelmistot, jotka auttavat ammattilaisia työssään | [Intro to Programming Languages and Tools of the Trade](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Aloittaminen | GitHubin perusteet, myös tiimityöskentely | Kuinka käyttää GitHubia projektissa ja miten tehdä yhteistyötä koodipohjalla | [Intro to GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Aloittaminen | Esteettömyys | Opit verkkosivujen esteettömyyden perusteet | [Accessibility Fundamentals](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS Basics | JavaScriptin tietotyypit | JavaScriptin tietotyyppien perusteet | [Data Types](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS Basics | Funktiot ja metodit | Opit sovelluksen logiikan hallinnan funktioiden ja metodien avulla | [Functions and Methods](./2-js-basics/2-functions-methods/README.md) | Jasmine ja Christopher |
| 06 | JS Basics | Päätöksenteko JavaScriptillä | Kuinka luoda ehtoja koodissasi päätöksentekomenetelmien avulla | [Making Decisions](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS Basics | Taulukot ja silmukat | Työskentele datan kanssa taulukoiden ja silmukoiden avulla JavaScriptissä | [Arrays and Loops](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML käytännössä | Rakenna HTML luodaksesi online-terraariumin, keskittyen layoutin rakentamiseen | [Introduction to HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS käytännössä | Rakenna CSS tyylittääksesi online-terraariumia, keskittyen CSS:n perusteisiin mukaan lukien sivun responsiivisuuden tekemisen | [Introduction to CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | JavaScriptin sulut (closures), DOM-manipulointi | Rakenna JavaScript, joka tekee terraariumista toimivan drag/drop-käyttöliittymän, keskittyen sulkuihin ja DOM-manipulointiin | [JavaScript Closures, DOM manipulation](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typing Game](./4-typing-game/solution/README.md) | Kirjoituspelin rakentaminen | Opit käyttämään näppäimistötapahtumia JavaScript-sovelluksen logiikan ohjaamiseen | [Event-Driven Programming](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Työskentely selainten kanssa | Opit, miten selaimet toimivat, niiden historian ja miten luoda ensimmäiset elementit selaimen laajennukseen | [About Browsers](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Lomakkeen rakentaminen, API-kutsut ja muuttujien tallennus paikalliseen muistiin | Rakenna selaimen laajennuksen JavaScript-elementit API:n kutsumiseen käyttäen muuttujiin tallennettuja paikalliseen muistiin | [APIs, Forms, and Local Storage](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Taustaprosessit selaimessa, verkkosivuston suorituskyky | Käytä selaimen taustaprosesseja hallitsemaan laajennuksen kuvaketta; opi web-suorituskyvystä ja optimoinnista | [Background Tasks and Performance](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | Edistyneempi pelikehitys JavaScriptillä | Opit periytymisestä luokkien ja koostumisen avulla sekä Pub/Sub-kuvion, valmistautuen pelin rakentamiseen | [Introduction to Advanced Game Development](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Piirtäminen kankaalle | Opit Canvas API:sta, jota käytetään elementtien piirtämiseen näytölle | [Drawing to Canvas](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Elementtien liikuttaminen ruudulla | Opi, miten elementtejä voi liikuttaa kartesisilla koordinaateilla ja Canvas API:lla | [Moving Elements Around](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Törmäyksentunnistus | Tee elementeistä törmäileviä ja reagoivia toisiinsa näppäinpainallusten avulla, ja lisää cooldown-funktio pelin suorituskyvyn varmistamiseksi | [Collision Detection](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Pisteiden kirjaaminen | Suorita matemaattisia laskuja pelin tilan ja suorituskyvyn mukaan | [Keeping Score](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Pelin lopetus ja uudelleenkäynnistys | Opit pelin lopettamisesta ja uudelleenkäynnistyksestä, mukaan lukien resurssien siistimisestä ja muuttujien nollaamisesta | [The Ending Condition](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Banking App](./7-bank-project/solution/README.md) | HTML-mallit ja reititykset web-sovelluksessa | Opit rakentamaan monisivuisen verkkosivuston arkkitehtuurin reitityksen ja HTML-mallien avulla | [HTML Templates and Routes](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Banking App](./7-bank-project/solution/README.md) | Kirjautumis- ja rekisteröitymislomakkeen rakentaminen | Opit lomakkeiden rakentamisesta ja validointirutiinien hallinnasta | [Forms](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Banking App](./7-bank-project/solution/README.md) | Tietojen hakemisen ja käytön menetelmät | Kuinka tieto virtaa sovellukseen ja sieltä ulos, miten hakea, tallentaa ja poistaa sitä | [Data](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Banking App](./7-bank-project/solution/README.md) | Tilanhallinnan käsitteet | Opit, kuinka sovelluksesi säilyttää tilaa ja miten sitä hallitaan ohjelmallisesti | [State Management](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Browser/VScode Code](../../8-code-editor) | Työskentely VScoden kanssa | Opit käyttämään koodieditoria | [Use VScode Code Editor](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Assistants](./9-chat-project/README.md) | Työskentely tekoälyn kanssa | Opit rakentamaan oman tekoälyavustajan | [AI Assistant project](./9-chat-project/README.md) | Chris |
## 🏫 Pedagogiikka
Opetussuunnitelmamme on suunniteltu kahden keskeisen pedagogisen periaatteen mukaisesti:
Opetussuunnitelmamme on suunniteltu kahden keskeisen pedagogisen periaatteen mukaan:
* projektipohjainen oppiminen
* toistuvat kyselyt
* usein toistuvat kyselyt
Ohjelma opettaa JavaScriptin, HTML:n ja CSS:n perusteet sekä uusimmat työkalut ja tekniikat, joita nykypäivän verkkokehittäjät käyttävät. Opiskelijat saavat käytännön kokemusta rakentamalla kirjoituspelin, virtuaalisen terraarion, ympäristöystävällisen selainlaajennuksen, avaruusinvader-tyylisen pelin ja yrityksille suunnatun pankkisovelluksen. Sarjan lopussa opiskelijoilla on vankka ymmärrys verkkokehityksestä.
Ohjelma opettaa JavaScriptin, HTML:n ja CSS:n perusteet sekä viimeisimmät työkalut ja tekniikat, joita nykyiset web-kehittäjät käyttävät. Oppilaat pääsevät kehittämään käytännön kokemusta rakentamalla kirjoituspelin, virtuaalisen terraariumin, ympäristöystävällisen selaimen laajennuksen, avaruuslainen henkisen pelin ja pankkisovelluksen yrityksille. Sarjan lopussa oppilaat ovat saaneet vankan ymmärryksen web-kehityksestä.
> 🎓 Voit suorittaa tämän opetussuunnitelman ensimmäiset oppitunnit [Learn Path](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) -kurssina Microsoft Learnissa!
> 🎓 Voit suorittaa tämän opetussuunnitelman ensimmäiset oppitunnit Microsoft Learnin [Learn Path](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) -polun kautta!
Varmistamalla, että sisältö liittyy projekteihin, prosessi on opiskelijoille kiinnostavampi ja käsitteiden muistaminen paranee. Kirjoitimme myös useita JavaScriptin perusteisiin liittyviä aloitusoppitunteja käsitteiden esittelemiseksi, yhdistettynä videoon "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)" -videotutoriaalikokoelmasta, joiden tekijät osallistuivat tämän opetussuunnitelman laatimiseen.
Varmistamalla, että sisältö vastaa projekteja, prosessi on opiskelijoille mielekkäämpi ja käsitteiden muistaminen tehostuu. Kirjoitimme lisäksi useita aloitusoppitunteja JavaScriptin perusteista esitelläksemme käsitteitä, yhdistettynä videoihin "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)" -videokokoelmasta, joiden tekijät osallistuivat tähän opetussuunnitelmaan.
Lisäksi matalan kynnyksen kysely ennen oppituntia suuntaa opiskelijan huomion aiheen oppimiseen, kun taas toinen kysely oppitunnin jälkeen varmistaa paremman muistamisen. Tämä opetussuunnitelma on suunniteltu joustavaksi ja hauskaksi, ja sen voi suorittaa kokonaan tai osittain. Projektit alkavat pienistä ja muuttuvat yhä monimutkaisemmiksi 12 viikon jakson loppuun mennessä.
Lisäksi oppituntia edeltävä matalariskinen kysely asettaa opiskelijalle opiskeluaiheen tavoitteen, ja oppitunnin jälkeinen toinen kysely varmistaa jatkumon. Tämä opetussuunnitelma on suunniteltu joustavaksi ja hauskaksi, ja sen voi suorittaa kokonaisuudessaan tai osittain. Projektit alkavat pieninä ja muuttuvat yhä vaativammiksi 12 viikon aikana.
Vaikka olemme tarkoituksella välttäneet JavaScript-kehysten esittelyä keskittyäksemme verkkokehittäjänä tarvittaviin perustaitoihin ennen kehysten käyttöönottoa, hyvä seuraava askel tämän opetussuunnitelman suorittamisen jälkeen olisi oppia Node.js:stä toisen videosarjan kautta: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
Vaikka tarkoituksella olemme välttäneet JavaScript-kirjastojen käyttöönottoa keskittyäksemme verkkokehittäjän perustaitoihin ennen kehysten käyttöönottoa, hyvä seuraava askel tämän opetussuunnitelman jälkeen olisi oppia Node.js:stä toisen videokokoelman kautta: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
> Tutustu [käytännesääntöihimme](CODE_OF_CONDUCT.md) ja [ohjeisiin osallistumiseen](CONTRIBUTING.md). Otamme mielellämme vastaan rakentavaa palautettasi!
> Tutustu [käyttäytymissääntöihimme](CODE_OF_CONDUCT.md) ja [osallistumisohjeisiin](CONTRIBUTING.md). Arvostamme rakentavaa palautettasi!
## 🧭 Offline-käyttö
Voit käyttää tätä dokumentaatiota offline-tilassa käyttämällä [Docsify](https://docsify.js.org/#/). Haarauta tämä repo, [asenna Docsify](https://docsify.js.org/#/quickstart) paikalliselle koneellesi ja kirjoita tämän repon juurikansiossa `docsify serve`. Verkkosivusto palvelee portissa 3000 localhostissasi: `localhost:3000`.
Voit käyttää tätä dokumentaatiota offline-tilassa käyttämällä [Docsify](https://docsify.js.org/#/). Haarauta tämä repositorio, [asenna Docsify](https://docsify.js.org/#/quickstart) paikalliselle koneellesi ja siirry tämän repositorion juurikansioon, kirjoita `docsify serve`. Sivusto palvelee portissa 3000 paikallisessa koneessasi: `localhost:3000`.
## 📘 PDF
Kaikkien oppituntien PDF löytyy [täältä](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
PDF-versio kaikista oppitunneista löytyy [täältä](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
## 🎒 Muut kurssit
Tiimimme tuottaa myös muita kursseja! Tutustu:
<!-- CO-OP TRANSLATOR OTHER COURSES START -->
### Azure / Edge / MCP / Agents
[![AZD for Beginners](https://img.shields.io/badge/AZD%20for%20Beginners-0078D4?style=for-the-badge&labelColor=E5E7EB&color=0078D4)](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Edge AI aloittelijoille](https://img.shields.io/badge/Edge%20AI%20aloittelijoille-00B8E4?style=for-the-badge&labelColor=E5E7EB&color=00B8E4)](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![MCP aloittelijoille](https://img.shields.io/badge/MCP%20aloittelijoille-009688?style=for-the-badge&labelColor=E5E7EB&color=009688)](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[![AI-agentit aloittelijoille](https://img.shields.io/badge/AI%20agentit%20aloittelijoille-00C49A?style=for-the-badge&labelColor=E5E7EB&color=00C49A)](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
### LangChain
[![LangChain4j for Beginners](https://img.shields.io/badge/LangChain4j%20for%20Beginners-22C55E?style=for-the-badge&&labelColor=E5E7EB&color=0553D6)](https://aka.ms/langchain4j-for-beginners)
[![LangChain.js for Beginners](https://img.shields.io/badge/LangChain.js%20for%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=0553D6)](https://aka.ms/langchainjs-for-beginners?WT.mc_id=m365-94501-dwahlin)
---
### Generatiivisen tekoälyn sarja
[![Generatiivinen tekoäly aloittelijoille](https://img.shields.io/badge/Generatiivinen%20tekoäly%20aloittelijoille-8B5CF6?style=for-the-badge&labelColor=E5E7EB&color=8B5CF6)](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Generatiivinen tekoäly (.NET)](https://img.shields.io/badge/Generatiivinen%20tekoäly%20(.NET)-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[![Generatiivinen tekoäly (Java)](https://img.shields.io/badge/Generatiivinen%20tekoäly%20(Java)-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[![Generatiivinen tekoäly (JavaScript)](https://img.shields.io/badge/Generatiivinen%20tekoäly%20(JavaScript)-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
### Azure / Edge / MCP / Agents
[![AZD for Beginners](https://img.shields.io/badge/AZD%20for%20Beginners-0078D4?style=for-the-badge&labelColor=E5E7EB&color=0078D4)](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Edge AI for Beginners](https://img.shields.io/badge/Edge%20AI%20for%20Beginners-00B8E4?style=for-the-badge&labelColor=E5E7EB&color=00B8E4)](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![MCP for Beginners](https://img.shields.io/badge/MCP%20for%20Beginners-009688?style=for-the-badge&labelColor=E5E7EB&color=009688)](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[![AI Agents for Beginners](https://img.shields.io/badge/AI%20Agents%20for%20Beginners-00C49A?style=for-the-badge&labelColor=E5E7EB&color=00C49A)](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
---
### Keskeiset oppimateriaalit
[![ML aloittelijoille](https://img.shields.io/badge/ML%20aloittelijoille-22C55E?style=for-the-badge&labelColor=E5E7EB&color=22C55E)](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[![Data-analytiikka aloittelijoille](https://img.shields.io/badge/Data-analytiikka%20aloittelijoille-84CC16?style=for-the-badge&labelColor=E5E7EB&color=84CC16)](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[![Tekoäly aloittelijoille](https://img.shields.io/badge/Tekoäly%20aloittelijoille-A3E635?style=for-the-badge&labelColor=E5E7EB&color=A3E635)](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[![Kyberturvallisuus aloittelijoille](https://img.shields.io/badge/Kyberturvallisuus%20aloittelijoille-F97316?style=for-the-badge&labelColor=E5E7EB&color=F97316)](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[![Web-kehitys aloittelijoille](https://img.shields.io/badge/Web-kehitys%20aloittelijoille-EC4899?style=for-the-badge&labelColor=E5E7EB&color=EC4899)](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[![IoT aloittelijoille](https://img.shields.io/badge/IoT%20aloittelijoille-14B8A6?style=for-the-badge&labelColor=E5E7EB&color=14B8A6)](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[![XR-kehitys aloittelijoille](https://img.shields.io/badge/XR-kehitys%20aloittelijoille-38BDF8?style=for-the-badge&labelColor=E5E7EB&color=38BDF8)](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
### Generative AI Series
[![Generative AI for Beginners](https://img.shields.io/badge/Generative%20AI%20for%20Beginners-8B5CF6?style=for-the-badge&labelColor=E5E7EB&color=8B5CF6)](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Generative AI (.NET)](https://img.shields.io/badge/Generative%20AI%20(.NET)-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[![Generative AI (Java)](https://img.shields.io/badge/Generative%20AI%20(Java)-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[![Generative AI (JavaScript)](https://img.shields.io/badge/Generative%20AI%20(JavaScript)-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
---
### Core Learning
[![ML for Beginners](https://img.shields.io/badge/ML%20for%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=22C55E)](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[![Data Science for Beginners](https://img.shields.io/badge/Data%20Science%20for%20Beginners-84CC16?style=for-the-badge&labelColor=E5E7EB&color=84CC16)](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[![AI for Beginners](https://img.shields.io/badge/AI%20for%20Beginners-A3E635?style=for-the-badge&labelColor=E5E7EB&color=A3E635)](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[![Cybersecurity for Beginners](https://img.shields.io/badge/Cybersecurity%20for%20Beginners-F97316?style=for-the-badge&labelColor=E5E7EB&color=F97316)](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[![Web Dev for Beginners](https://img.shields.io/badge/Web%20Dev%20for%20Beginners-EC4899?style=for-the-badge&labelColor=E5E7EB&color=EC4899)](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[![IoT for Beginners](https://img.shields.io/badge/IoT%20for%20Beginners-14B8A6?style=for-the-badge&labelColor=E5E7EB&color=14B8A6)](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[![XR Development for Beginners](https://img.shields.io/badge/XR%20Development%20for%20Beginners-38BDF8?style=for-the-badge&labelColor=E5E7EB&color=38BDF8)](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
### Copilot-sarja
[![Copilot tekoälyavusteiseen ohjelmointiin](https://img.shields.io/badge/Copilot%20tekoälyavusteiseen%20ohjelmointiin-FACC15?style=for-the-badge&labelColor=E5E7EB&color=FACC15)](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[![Copilot C#/.NET:lle](https://img.shields.io/badge/Copilot%20C%23/.NET:lle-FBBF24?style=for-the-badge&labelColor=E5E7EB&color=FBBF24)](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
[![Copilot-seikkailu](https://img.shields.io/badge/Copilot-seikkailu-FDE68A?style=for-the-badge&labelColor=E5E7EB&color=FDE68A)](https://github.com/microsoft/CopilotAdventures?WT.mc_id=academic-105485-koreyst)
---
### Copilot Series
[![Copilot for AI Paired Programming](https://img.shields.io/badge/Copilot%20for%20AI%20Paired%20Programming-FACC15?style=for-the-badge&labelColor=E5E7EB&color=FACC15)](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[![Copilot for C#/.NET](https://img.shields.io/badge/Copilot%20for%20C%23/.NET-FBBF24?style=for-the-badge&labelColor=E5E7EB&color=FBBF24)](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
[![Copilot Adventure](https://img.shields.io/badge/Copilot%20Adventure-FDE68A?style=for-the-badge&labelColor=E5E7EB&color=FDE68A)](https://github.com/microsoft/CopilotAdventures?WT.mc_id=academic-105485-koreyst)
<!-- CO-OP TRANSLATOR OTHER COURSES END -->
## Apua saatavilla
## Apua saatavana
Jos jäät jumiin tai sinulla on kysymyksiä tekoälysovellusten rakentamisesta, liity muiden oppijoiden ja kokeneiden kehittäjien keskusteluihin MCP:stä. Se on tukevainen yhteisö, jossa kysymykset ovat tervetulleita ja tietoa jaetaan avoimesti.
Jos jumitut tai sinulla on kysyttävää tekoälysovellusten rakentamisesta. Liity muiden oppijoiden ja kokeneiden kehittäjien keskusteluihin MCP:stä. Se on kannustava yhteisö, jossa kysymykset ovat tervetulleita ja tieto jaetaan vapaasti.
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
Jos sinulla on tuotepalautetta tai virheitä rakentamisen aikana, vieraile:
Jos sinulla on tuotepalaute tai kohtaat virheitä rakentamisen aikana, käy:
[![Microsoft Foundry Developer Forum](https://img.shields.io/badge/GitHub-Microsoft_Foundry_Developer_Forum-blue?style=for-the-badge&logo=github&color=000000&logoColor=fff)](https://aka.ms/foundry/forum)
[![Microsoft Foundry Developer Forum](https://img.shields.io/badge/GitHub-Microsoft_Foundry_Developer_Forum-blue?style=for-the-badge&logo=github&color=000000&logoColor=fff)](https://aka.ms/foundry/forum)
## Lisenssi
## Lisenssi
Tämä arkisto on lisensoitu MIT-lisenssillä. Katso [LICENSE](../../LICENSE) tiedosto saadaksesi lisätietoja.
Tämä arkisto on lisensoitu MIT-lisenssillä. Lisätietoja löydät tiedostosta [LICENSE](../../LICENSE).
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Vastuuvapauslauseke**:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua [Co-op Translator](https://github.com/Azure/co-op-translator). Vaikka pyrimme tarkkuuteen, huomioithan, että automaattiset käännökset voivat sisältää virheitä tai epätarkkuuksia. Alkuperäinen asiakirja sen alkuperäisellä kielellä tulisi pitää ensisijaisena lähteenä. Kriittisen tiedon osalta suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa väärinkäsityksistä tai virhetulkinnoista, jotka johtuvat tämän käännöksen käytöstä.
Tämä asiakirja on käännetty tekoälypohjaisella käännöspalvelulla [Co-op Translator](https://github.com/Azure/co-op-translator). Vaikka pyrimme tarkkuuteen, automaattisissa käännöksissä saattaa esiintyä virheitä tai epätarkkuuksia. Alkuperäistä asiakirjaa sen omalla kielellä tulee pitää virallisena lähteenä. Tärkeiden tietojen osalta suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa tämän käännöksen käytöstä aiheutuvista väärinymmärryksistä tai tulkinnoista.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -42,10 +42,10 @@ Tämä opetusohjelma sisältää tuontipaketteja yleisiin LMS-työnkulkuihin.
- Moodle Cloud tukee rajoitetusti Common Cartridgea. Suosi yllä olevaa Moodle-tiedostoa, joka voidaan myös ladata Canvasiin.
- Tuonnin jälkeen tarkista moduulit, määräajat ja visailuasetukset, jotta ne vastaavat lukukautesi aikataulua.
![Moodle](../../translated_images/moodle.94eb93d714a50cb2c97435b408017dee224348b61bc86203ffd43a4f4e57b95f.fi.png)
![Moodle](../../translated_images/moodle.94eb93d714a50cb2.fi.png)
> Opetusohjelma Moodle-luokassa
![Canvas](../../translated_images/canvas.fbd605ff8e5b8aff567d398528ce113db304446b90b9cad55c654de3fdfcda34.fi.png)
![Canvas](../../translated_images/canvas.fbd605ff8e5b8aff.fi.png)
> Opetusohjelma Canvasissa
### Repositorion käyttö suoraan (ilman Classroomia)

@ -17,7 +17,7 @@ Luister, ik snap het helemaal als programmeren nu nog intimiderend lijkt. Toen i
Vandaag gaan we de geweldige tools verkennen die moderne webontwikkeling niet alleen mogelijk maken, maar ook verslavend leuk. Ik heb het over dezelfde editors, browsers en workflows die ontwikkelaars bij Netflix, Spotify en je favoriete indie-appstudio elke dag gebruiken. En hier komt het deel dat je een vreugdedansje laat doen: de meeste van deze professionele, industrienorm-tools zijn helemaal gratis!
![Intro Programmering](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff0b27dcbf1c3f16c8ed46984866f2d29988929678b0058fde.nl.png)
![Intro Programmering](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -17,7 +17,7 @@ Ik weet dat dit in het begin misschien wat overweldigend lijkt ik herinner m
We gaan deze reis samen maken, stap voor stap. Geen haast, geen druk alleen jij, ik, en een paar echt coole tools die je nieuwe beste vrienden gaan worden!
![Intro tot GitHub](../../../../translated_images/webdev101-github.8846d7971abef6f947909b4f9d343e2a23778aa716ca6b9d71df7174ee5009ac.nl.png)
![Intro tot GitHub](../../../../translated_images/webdev101-github.8846d7971abef6f9.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid
@ -604,7 +604,7 @@ Laten we eerst een repository (of **repo**) op GitHub vinden die je interesseert
✅ Een goede manier om 'beginner-vriendelijke' repos te vinden is door [te zoeken op de tag 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
![Een repo lokaal kopiëren](../../../../translated_images/clone_repo.5085c48d666ead57664f050d806e325d7f883be6838c821e08bc823ab7c66665.nl.png)
![Een repo lokaal kopiëren](../../../../translated_images/clone_repo.5085c48d666ead57.nl.png)
Er zijn verschillende manieren om code te kopiëren. Een manier is om de inhoud van de repository te "clonen", met behulp van HTTPS, SSH, of de GitHub CLI (Command Line Interface).

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# Toegankelijke Webpagina's Maken
![Alles Over Toegankelijkheid](../../../../translated_images/webdev101-a11y.8ef3025c858d897a403a1a42c0897c76e11b724d9a8a0c0578dd4316f7507622.nl.png)
![Alles Over Toegankelijkheid](../../../../translated_images/webdev101-a11y.8ef3025c858d897a.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScript Basisprincipes: Gegevenstypen
![JavaScript Basisprincipes - Gegevenstypen](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.nl.png)
![JavaScript Basisprincipes - Gegevenstypen](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScript Basis: Methoden en Functies
![JavaScript Basis - Functies](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b7605c36330ac42eeb5cd8ed02bcdd60fdac778174d6cb865.nl.png)
![JavaScript Basis - Functies](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScript Basis: Beslissingen nemen
![JavaScript Basis - Beslissingen nemen](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0b1cb2f8adaff3ed2a77c4f91db96d8a0594132a353fa189a.nl.png)
![JavaScript Basis - Beslissingen nemen](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)

@ -9,7 +9,7 @@ CO_OP_TRANSLATOR_METADATA:
-->
# JavaScript Basis: Arrays en Lussen
![JavaScript Basis - Arrays](../../../../translated_images/webdev101-js-arrays.439d7528b8a294558d0e4302e448d193f8ad7495cc407539cc81f1afe904b470.nl.png)
![JavaScript Basis - Arrays](../../../../translated_images/webdev101-js-arrays.439d7528b8a29455.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid

@ -26,7 +26,7 @@ journey
Build terrarium: 5: Student
```
![Introductie tot HTML](../../../../translated_images/webdev101-html.4389c2067af68e98280c1bde52b6c6269f399eaae3659b7c846018d8a7b0bbd9.nl.png)
![Introductie tot HTML](../../../../translated_images/webdev101-html.4389c2067af68e98.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
HTML, of HyperText Markup Language, is de basis van elke website die je ooit hebt bezocht. Zie HTML als het skelet dat structuur geeft aan webpagina's het bepaalt waar de inhoud komt, hoe het georganiseerd is en wat elk onderdeel betekent. Terwijl CSS later je HTML "aankleedt" met kleuren en lay-outs, en JavaScript het tot leven brengt met interactiviteit, biedt HTML de essentiële structuur die alles mogelijk maakt.
@ -88,7 +88,7 @@ Je maakt een speciale map voor je terrariumproject en voegt je eerste HTML-besta
4. Klik in het Explorer-paneel op het pictogram "New File"
5. Noem je bestand `index.html`
![VS Code Explorer toont het maken van een nieuw bestand](../../../../translated_images/vs-code-index.e2986cf919471eb984a0afef231380c8b132b000635105f2397bd2754d1b689c.nl.png)
![VS Code Explorer toont het maken van een nieuw bestand](../../../../translated_images/vs-code-index.e2986cf919471eb9.nl.png)
**Optie 2: Gebruik Terminalcommando's**
```bash

@ -30,7 +30,7 @@ journey
Glass reflections: 5: Student
```
![Introductie tot CSS](../../../../translated_images/webdev101-css.3f7af5991bf53a200d79e7257e5e450408d8ea97f5b531d31b2e3976317338ee.nl.png)
![Introductie tot CSS](../../../../translated_images/webdev101-css.3f7af5991bf53a20.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
Weet je nog hoe je HTML-terrarium er vrij basic uitzag? Met CSS transformeren we die eenvoudige structuur tot iets visueel aantrekkelijks.
@ -205,7 +205,7 @@ body {
Open de ontwikkelaarstools van je browser (F12), ga naar het tabblad Elements en inspecteer je `<h1>`-element. Je zult zien dat het de lettertypefamilie van het body-element erft:
![geërfd lettertype](../../../../translated_images/1.cc07a5cbe114ad1d4728c35134584ac1b87db688eff83cf75985cf31fe0ed95c.nl.png)
![geërfd lettertype](../../../../translated_images/1.cc07a5cbe114ad1d.nl.png)
**Experimenteren**: Probeer andere overerfbare eigenschappen in te stellen op `<body>` zoals `color`, `line-height` of `text-align`. Wat gebeurt er met je koptekst en andere elementen?
@ -599,7 +599,7 @@ Klaar om je terrarium te verbeteren met realistische glans op glas? Deze technie
Je gaat subtiele highlights creëren die simuleren hoe licht reflecteert op glasoppervlakken. Deze aanpak is vergelijkbaar met hoe Renaissance-schilders zoals Jan van Eyck licht en reflectie gebruikten om geschilderd glas driedimensionaal te laten lijken. Dit is wat je wilt bereiken:
![finished terrarium](../../../../translated_images/terrarium-final.2f07047ffc597d0a06b06cab28a77801a10dd12fdb6c7fc630e9c40665491c53.nl.png)
![finished terrarium](../../../../translated_images/terrarium-final.2f07047ffc597d0a.nl.png)
**Jouw uitdaging:**
- **Creëer** subtiele witte of lichtgekleurde ovale vormen voor de glans op het glas

@ -26,7 +26,7 @@ journey
Complete terrarium: 5: Student
```
![DOM en een closure](../../../../translated_images/webdev101-js.10280393044d7eaaec7e847574946add7ddae6be2b2194567d848b61d849334a.nl.png)
![DOM en een closure](../../../../translated_images/webdev101-js.10280393044d7eaa.nl.png)
> Sketchnote door [Tomomi Imura](https://twitter.com/girlie_mac)
Welkom bij een van de meest boeiende aspecten van webontwikkeling - interactief maken! Het Document Object Model (DOM) is als een brug tussen je HTML en JavaScript, en vandaag gaan we het gebruiken om je terrarium tot leven te brengen. Toen Tim Berners-Lee de eerste webbrowser creëerde, stelde hij zich een web voor waar documenten dynamisch en interactief konden zijn - de DOM maakt die visie mogelijk.
@ -105,7 +105,7 @@ flowchart TD
style Q fill:#ffebee
```
![DOM boomrepresentatie](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.nl.png)
![DOM boomrepresentatie](../../../../translated_images/dom-tree.7daf0e763cbbba92.nl.png)
> Een representatie van de DOM en de HTML-markup die ernaar verwijst. Van [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
@ -150,7 +150,7 @@ flowchart LR
> 💡 **Closures begrijpen**: Closures zijn een belangrijk onderwerp in JavaScript, en veel ontwikkelaars gebruiken ze jarenlang voordat ze alle theoretische aspecten volledig begrijpen. Vandaag richten we ons op praktische toepassing - je zult zien dat closures natuurlijk ontstaan terwijl we onze interactieve functies bouwen. Begrip zal zich ontwikkelen naarmate je ziet hoe ze echte problemen oplossen.
![DOM boomrepresentatie](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.nl.png)
![DOM boomrepresentatie](../../../../translated_images/dom-tree.7daf0e763cbbba92.nl.png)
> Een representatie van de DOM en de HTML-markup die ernaar verwijst. Van [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
@ -598,7 +598,7 @@ Test nu jouw interactieve terrarium! Open je `index.html`-bestand in een webbrow
- **Ondersteuning voor meerdere apparaten**: Werkt op desktop en mobiel
- **Prestatiebewust**: Geen geheugenlekken of overbodige berekeningen
![afgewerkt terrarium](../../../../translated_images/terrarium-final.0920f16e87c13a84cd2b553a5af9a3ad1cffbd41fbf8ce715d9e9c43809a5e2c.nl.png)
![afgewerkt terrarium](../../../../translated_images/terrarium-final.0920f16e87c13a84.nl.png)
---

@ -1,45 +1,30 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "7965cd2bc5dc92ad888dc4c6ab2ab70a",
"translation_date": "2025-08-27T20:04:52+00:00",
"original_hash": "bc5c5550f79d10add90ce419ee34abb3",
"translation_date": "2026-01-07T01:04:17+00:00",
"source_file": "3-terrarium/README.md",
"language_code": "nl"
}
-->
# Mijn Terrarium: Een project om te leren over HTML, CSS en DOM-manipulatie met JavaScript 🌵🌱
## Zet je Terrarium in productie
Een kleine drag-and-drop code-meditatie. Met een beetje HTML, JS en CSS kun je een webinterface bouwen, deze stylen en zelfs meerdere interacties naar keuze toevoegen.
Je kunt je Terrarium publiceren op het web met behulp van **Azure Static Web Apps**.
![mijn terrarium](../../../translated_images/screenshot_gray.0c796099a1f9f25e40aa55ead81f268434c00af30d7092490759945eda63067d.nl.png)
1. Fork deze repo
# Lessen
2. Druk op deze knop 👇
1. [Introductie tot HTML](./1-intro-to-html/README.md)
2. [Introductie tot CSS](./2-intro-to-css/README.md)
3. [Introductie tot DOM en JS Closures](./3-intro-to-DOM-and-closures/README.md)
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.StaticApp)
## Credits
Geschreven met ♥️ door [Jen Looper](https://www.twitter.com/jenlooper)
Het terrarium gemaakt via CSS is geïnspireerd door Jakub Mandra's glazen pot [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY).
De illustraties zijn met de hand getekend door [Jen Looper](http://jenlooper.com) met behulp van Procreate.
## Publiceer je Terrarium
Je kunt je terrarium op het web publiceren met behulp van Azure Static Web Apps.
1. Fork deze repository
2. Druk op deze knop
[![Deploy to Azure button](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
3. Doorloop de wizard om je app te maken. Zorg ervoor dat je de app-root instelt op ofwel `/solution` of de root van je codebase. Er is geen API in deze app, dus daar hoef je je geen zorgen over te maken. Een GitHub-map wordt aangemaakt in je geforkte repository die Azure Static Web Apps' buildservices helpt om je app te bouwen en te publiceren naar een nieuwe URL.
3. Volg de setup wizard om je app te maken.
- Stel de **App root** in op `/solution` of de root van je codebase.
- Er is geen API in deze app, dus je kunt de API-configuratie overslaan.
- Er wordt automatisch een `.github`-map gemaakt om Azure Static Web Apps te helpen je app te bouwen en publiceren.
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Disclaimer**:
Dit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in zijn oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor kritieke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.
Dit document is vertaald met behulp van de AI-vertalingsdienst [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, dient u er rekening mee te houden dat automatische vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het oorspronkelijke document in de originele taal moet worden beschouwd als de gezaghebbende bron. Voor belangrijke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor enige misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Een kleine drag-and-drop code-meditatie. Met een beetje HTML, JS en CSS kun je een webinterface bouwen, deze stylen en interactie toevoegen.
![mijn terrarium](../../../../translated_images/screenshot_gray.0c796099a1f9f25e40aa55ead81f268434c00af30d7092490759945eda63067d.nl.png)
![mijn terrarium](../../../../translated_images/screenshot_gray.0c796099a1f9f25e.nl.png)
## Credits

@ -26,7 +26,7 @@ journey
Polish experience: 5: Student
```
![Browser sketchnote](../../../../translated_images/browser.60317c9be8b7f84adce43e30bff8d47a1ae15793beab762317b2bc6b74337c1a.nl.jpg)
![Browser sketchnote](../../../../translated_images/browser.60317c9be8b7f84a.nl.jpg)
> Sketchnote door [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
## Pre-Les Quiz
@ -79,7 +79,7 @@ Dit proces weerspiegelt hoe de eerste webbrowser, WorldWideWeb, werd ontworpen d
**Een beetje geschiedenis**: De eerste browser heette 'WorldWideWeb' en werd in 1990 gemaakt door Sir Timothy Berners-Lee.
![vroegtijdige browsers](../../../../translated_images/earlybrowsers.d984b711cdf3a42ddac919d46c4b5ca7232f68ccfbd81395e04e5a64c0015277.nl.jpg)
![vroegtijdige browsers](../../../../translated_images/earlybrowsers.d984b711cdf3a42d.nl.jpg)
> Enkele vroegtijdige browsers, via [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
### Hoe Browsers Webinhoud Verwerken
@ -198,7 +198,7 @@ quadrantChart
Het begrijpen van het installatieproces van extensies helpt je de gebruikerservaring te anticiperen wanneer mensen je extensie installeren. Het installatieproces is gestandaardiseerd in moderne browsers, met kleine variaties in interfaceontwerp.
![screenshot van de Edge-browser die de open edge://extensions-pagina en het open instellingenmenu toont](../../../../translated_images/install-on-edge.d68781acaf0b3d3dada8b7507cde7a64bf74b7040d9818baaa9070668e819f90.nl.png)
![screenshot van de Edge-browser die de open edge://extensions-pagina en het open instellingenmenu toont](../../../../translated_images/install-on-edge.d68781acaf0b3d3d.nl.png)
> **Belangrijk**: Zorg ervoor dat je ontwikkelaarsmodus inschakelt en extensies van andere winkels toestaat bij het testen van je eigen extensies.
@ -313,10 +313,10 @@ Dit volgt het principe van progressieve onthulling dat sinds de vroege dagen van
### Overzicht van Extensie Weergaven
**Setup Weergave** - Configuratie voor eerste gebruik:
![screenshot van de voltooide extensie geopend in een browser, met een formulier met invoervelden voor regio en API-sleutel.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.nl.png)
![screenshot van de voltooide extensie geopend in een browser, met een formulier met invoervelden voor regio en API-sleutel.](../../../../translated_images/1.b6da8c1394b07491.nl.png)
**Resultaten Weergave** - Weergave van CO2-voetafdrukgegevens:
![screenshot van de voltooide extensie die waarden toont voor CO2-gebruik en percentage fossiele brandstoffen voor de regio US-NEISO.](../../../../translated_images/2.1dae52ff0804224692cd648afbf2342955d7afe3b0101b617268130dfb427f55.nl.png)
![screenshot van de voltooide extensie die waarden toont voor CO2-gebruik en percentage fossiele brandstoffen voor de regio US-NEISO.](../../../../translated_images/2.1dae52ff08042246.nl.png)
### Het Configuratieformulier Bouwen

@ -268,7 +268,7 @@ stateDiagram-v2
ClearStorage --> FirstTime: Back to setup
```
![Local storage pane](../../../../translated_images/localstorage.472f8147b6a3f8d141d9551c95a2da610ac9a3c6a73d4a1c224081c98bae09d9.nl.png)
![Local storage pane](../../../../translated_images/localstorage.472f8147b6a3f8d1.nl.png)
> ⚠️ **Beveiligingsoverweging**: In productie-applicaties brengt het opslaan van API-sleutels in LocalStorage beveiligingsrisico's met zich mee, omdat JavaScript toegang heeft tot deze gegevens. Voor leerdoeleinden werkt deze aanpak prima, maar echte applicaties zouden veilige server-side opslag moeten gebruiken voor gevoelige inloggegevens.

@ -126,7 +126,7 @@ Om Developer Tools in Edge te openen, klik je op die drie puntjes rechtsboven, g
Laten we dit uitproberen. Open een website (Microsoft.com werkt goed hiervoor) en klik op die 'Opnemen'-knop. Vernieuw nu de pagina en bekijk hoe de profiler alles vastlegt wat er gebeurt. Wanneer je stopt met opnemen, zie je een gedetailleerde uitsplitsing van hoe de browser de site 'script', 'rendert' en 'schildert'. Het doet me denken aan hoe de missiecontrole elk systeem monitort tijdens een raketlancering - je krijgt realtime gegevens over precies wat er gebeurt en wanneer.
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01cfec9aab74173dba13f91d2c968e1a1ae434c26165792df15.nl.png)
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01c.nl.png)
✅ De [Microsoft Documentatie](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) heeft veel meer details als je dieper wilt duiken.
@ -136,11 +136,11 @@ Selecteer elementen van de profieltijdlijn om in te zoomen op gebeurtenissen die
Krijg een momentopname van de prestaties van je pagina door een deel van de profieltijdlijn te selecteren en naar het samenvattingspaneel te kijken:
![Edge profiler snapshot](../../../../translated_images/snapshot.97750180ebcad73794a3594b36925eb5c8dbaac9e03fec7f9b974188c9ac63c7.nl.png)
![Edge profiler snapshot](../../../../translated_images/snapshot.97750180ebcad737.nl.png)
Controleer het Event Log-paneel om te zien of een gebeurtenis langer dan 15 ms duurde:
![Edge event log](../../../../translated_images/log.804026979f3707e00eebcfa028b2b5a88cec6292f858767bb6703afba65a7d9c.nl.png)
![Edge event log](../../../../translated_images/log.804026979f3707e0.nl.png)
✅ Leer je profiler kennen! Open de ontwikkelaarstools op deze site en kijk of er knelpunten zijn. Wat is het langzaamst ladende bestand? Het snelste?

@ -23,7 +23,7 @@ Deze extensie kan ad hoc door een gebruiker worden opgeroepen zodra een API-sleu
### Credits
![een groene browserextensie](../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![een groene browserextensie](../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Credits

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Gebruik de CO2 Signal API van tmrow om het elektriciteitsverbruik bij te houden en bouw een browserextensie zodat je direct in je browser een herinnering hebt over hoe zwaar het elektriciteitsverbruik in jouw regio is. Door deze extensie ad hoc te gebruiken, kun je beter beslissingen nemen over je activiteiten op basis van deze informatie.
![extensie screenshot](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![extensie screenshot](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de slag
@ -31,7 +31,7 @@ npm run build
Om de extensie op Edge te installeren, gebruik je het menu met de 'drie stippen' rechtsboven in de browser om het Extensies-paneel te vinden. Selecteer daar 'Load Unpacked' om een nieuwe extensie te laden. Open de 'dist'-map wanneer hierom wordt gevraagd en de extensie wordt geladen. Om het te gebruiken, heb je een API-sleutel nodig voor de CO2 Signal API ([hier via e-mail verkrijgen](https://www.co2signal.com/) - voer je e-mailadres in het veld op deze pagina in) en de [code voor jouw regio](http://api.electricitymap.org/v3/zones) die overeenkomt met de [Electricity Map](https://www.electricitymap.org/map) (in Boston gebruik ik bijvoorbeeld 'US-NEISO').
![installeren](../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![installeren](../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Zodra de API-sleutel en regio zijn ingevoerd in de interface van de extensie, zou de gekleurde stip in de browserextensiebalk moeten veranderen om het energieverbruik in jouw regio weer te geven. Het geeft je een aanwijzing over welke energie-intensieve activiteiten geschikt zijn om uit te voeren. Het concept achter dit 'stip'-systeem is geïnspireerd door de [Energy Lollipop extensie](https://energylollipop.com/) voor emissies in Californië.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Met behulp van de CO2 Signal API van tmrow om het elektriciteitsverbruik te volgen, maak je een browserextensie zodat je direct in je browser een herinnering kunt krijgen over het elektriciteitsverbruik in jouw regio. Het gebruik van deze ad-hoc extensie helpt je om je activiteiten te beoordelen op basis van deze informatie.
![extensie screenshot](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![extensie screenshot](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de slag
@ -31,7 +31,7 @@ npm run build
Om de extensie op Edge te installeren, gebruik je het menu met de 'drie puntjes' in de rechterbovenhoek van de browser om het Extensies-paneel te vinden. Selecteer daar 'Uitgepakte extensie laden' om een nieuwe extensie te laden. Open de map 'dist' wanneer daarom wordt gevraagd, en de extensie wordt geladen. Om de extensie te gebruiken, heb je een API-sleutel nodig voor de CO2 Signal API ([verkrijg er hier een via e-mail](https://www.co2signal.com/) - voer je e-mailadres in het veld op deze pagina in) en de [code voor jouw regio](http://api.electricitymap.org/v3/zones) die overeenkomt met de [Electricity Map](https://www.electricitymap.org/map) (in Boston gebruik ik bijvoorbeeld 'US-NEISO').
![installatie](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![installatie](../../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Zodra de API-sleutel en de regio zijn ingevoerd in de extensie-interface, zou het gekleurde puntje in de extensiebalk van de browser moeten veranderen om het energieverbruik in jouw regio weer te geven. Dit geeft je een indicatie van welke energie-intensieve activiteiten op dat moment geschikt zijn. Het concept achter dit 'puntensysteem' is geïnspireerd door de [Energy Lollipop extensie](https://energylollipop.com/) voor emissies in Californië.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Met behulp van de CO2 Signal API van tmrow om het elektriciteitsverbruik te volgen, bouwen we een browser-extensie die je eraan herinnert hoe zwaar het elektriciteitsverbruik in jouw regio is. Door deze extensie te gebruiken, kun je op basis van deze informatie beslissingen nemen over je activiteiten.
![Extensie Screenshot](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![Extensie Screenshot](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de slag
@ -31,7 +31,7 @@ npm run build
Om te installeren in Edge, gebruik het 'drie-puntjes'-menu in de rechterbovenhoek van de browser om het extensiepaneel te vinden. Kies daar 'Ongepakte extensie laden'. Open de 'dist'-map in de prompt en de extensie wordt geladen. Om het te gebruiken, heb je een API-sleutel nodig voor de CO2 Signal API ([verkrijgbaar via e-mail hier](https://www.co2signal.com/) - voer je e-mailadres in het vak op die pagina in) en [de code voor jouw regio](http://api.electricitymap.org/v3/zones) van [Electricity Map](https://www.electricitymap.org/map) (bijvoorbeeld, in Boston gebruik ik 'US-NEISO').
![installeren](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![installeren](../../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Zodra de API-sleutel en regio in de extensie-interface zijn ingevoerd, zou de gekleurde stip in de browser-extensiebalk moeten veranderen om het energieverbruik in jouw regio weer te geven. Dit geeft je een indicatie van welke energie-intensieve activiteiten geschikt zijn op dat moment. Het idee achter dit 'stip'-systeem is geïnspireerd door de [Energy Lollipop-extensie](https://energylollipop.com/) voor emissies in Californië.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
We zullen de Signal CO2 API van tmrow gebruiken om het elektriciteitsverbruik te monitoren en een browserextensie te maken. Zo kun je direct in je browser een herinnering krijgen over hoe zwaar het elektriciteitsverbruik in jouw regio is. Het gebruik van deze op maat gemaakte extensie helpt je om je activiteiten te evalueren op basis van deze informatie.
![screenshot van de extensie](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![screenshot van de extensie](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de Slag
@ -31,7 +31,7 @@ npm run build
Om de extensie in Edge te installeren, gebruik je het menu met de "drie puntjes" in de rechterbovenhoek van de browser om het Extensies-paneel te vinden. Als het nog niet is ingeschakeld, zet dan de Ontwikkelaarsmodus aan (linksonder). Selecteer "Uitgepakte extensie laden" om een nieuwe extensie te laden. Open de map "dist" in het prompt, en de extensie wordt geladen. Om het te gebruiken, heb je een API-sleutel nodig voor de CO2 Signal API (je kunt er [hier via e-mail een krijgen](https://www.co2signal.com/) - voer je e-mailadres in het veld op deze pagina in) en de [code voor jouw regio](http://api.electricitymap.org/v3/zones) die overeenkomt met de [elektriciteitskaart](https://www.electricitymap.org/map) (bijvoorbeeld, in Boston is dat "US-NEISO").
![installatie](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![installatie](../../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Zodra de API-sleutel en de regio zijn ingevoerd in de interface van de extensie, zou het gekleurde puntje in de browserextensiebalk moeten veranderen om het energieverbruik van de regio weer te geven. Het biedt ook een aanwijzing over welke energie-intensieve activiteiten geschikt zijn om uit te voeren. Het concept achter dit "puntensysteem" is geïnspireerd door de [Energy Lollipop-extensie](https://energylollipop.com/) voor emissies in Californië.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Bouw een browserextensie die, met behulp van de CO2 Signal API van tmrow, het energieverbruik in jouw regio bijhoudt en dit als een herinnering op je browser weergeeft. Door deze extensie ad-hoc te gebruiken, kun je je activiteiten baseren op deze informatie.
![extension screenshot](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![extension screenshot](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de slag
@ -31,7 +31,7 @@ npm run build
Om de extensie in Edge te installeren, ga je naar het "drie stippen"-menu rechtsboven in de browser en zoek je het paneel "Extensies". Kies daar "Load Unpacked" en laad de nieuwe extensie. Wanneer je wordt gevraagd, open je de "dist"-map om de extensie te laden. Om de extensie te gebruiken, heb je een API-sleutel van de CO2 Signal API nodig ([hier via e-mail verkrijgen](https://www.co2signal.com/) - voer je e-mailadres in het vak op die pagina in) en een [code voor jouw regio](http://api.electricitymap.org/v3/zones) die overeenkomt met de [Electricity Map](https://www.electricitymap.org/map) (bijvoorbeeld, voor Boston gebruik je 'US-NEISO').
![installing](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![installing](../../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Wanneer je de API-sleutel en regio invoert in de extensie-interface, verandert de gekleurde stip die in de extensiebalk van je browser wordt weergegeven. Deze stip weerspiegelt het energieverbruik in jouw regio en geeft aan welke activiteiten geschikt zijn op basis van het energieverbruik. Het concept van dit "stip"-systeem is geïnspireerd door de [Energy Lollipop extension](https://energylollipop.com/) voor emissies in Californië.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Gebruik de CO2 Signal API van tmrow om het elektriciteitsverbruik te monitoren en bouw een browserextensie waarmee je waarschuwingen kunt ontvangen over hoe zwaar het elektriciteitsverbruik in jouw regio is. Het gebruik van deze extensie helpt je om je activiteiten beter af te stemmen op deze informatie.
![screenshot van browserextensie](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![screenshot van browserextensie](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de Slag
@ -31,7 +31,7 @@ npm run build
Om de extensie in Edge te installeren, gebruik je het menu met de 'drie puntjes' in de rechterbovenhoek van de browser om het Extensies-paneel te vinden. Kies daar 'Load Unpacked' om een nieuwe extensie te laden. Open de 'dist'-map wanneer hierom wordt gevraagd en de extensie wordt geladen. Om de extensie te gebruiken, heb je een API-sleutel nodig voor de CO2 Signal API ([verkrijg er een via e-mail hier](https://www.co2signal.com/) - voer je e-mailadres in het veld op deze pagina in) en [de code voor jouw regio](http://api.electricitymap.org/v3/zones) die overeenkomt met [Electricity Map](https://www.electricitymap.org/map) (in Boston gebruik ik bijvoorbeeld 'US-NEISO').
![bezig met downloaden](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![bezig met downloaden](../../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Zodra de API-sleutel en regio zijn ingevoerd in de interface van de extensie, zal de gekleurde stip in de browserextensiebalk veranderen om het energieverbruik in jouw regio weer te geven en je een indicatie geven van welke zware activiteiten geschikt zijn om te doen. Het idee achter dit 'stip'-systeem is geïnspireerd door [de Energy Lollipop browserextensie](https://energylollipop.com/) voor de uitstoot in Californië.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Met behulp van de CO2 Signal API van tmrow om elektriciteitsgebruik bij te houden, bouw je een browserextensie zodat je direct in je browser een herinnering hebt over hoe zwaar het elektriciteitsgebruik in jouw regio is. Door deze extensie ad hoc te gebruiken, kun je beter beslissingen nemen over je activiteiten op basis van deze informatie.
![extensie screenshot](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.nl.png)
![extensie screenshot](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.nl.png)
## Aan de slag
@ -31,7 +31,7 @@ npm run build
Om de extensie op Edge te installeren, gebruik je het menu met de 'drie puntjes' rechtsboven in de browser om het Extensiepaneel te vinden. Selecteer daar 'Load Unpacked' om een nieuwe extensie te laden. Open de map 'dist' wanneer daarom wordt gevraagd, en de extensie wordt geladen. Om de extensie te gebruiken, heb je een API-sleutel nodig voor de CO2 Signal API ([hier aanvragen via e-mail](https://www.co2signal.com/) - voer je e-mailadres in op deze pagina) en de [code voor jouw regio](http://api.electricitymap.org/v3/zones) die overeenkomt met de [Electricity Map](https://www.electricitymap.org/map) (in Boston gebruik ik bijvoorbeeld 'US-NEISO').
![installeren](../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.nl.png)
![installeren](../../../../translated_images/install-on-edge.78634f02842c4828.nl.png)
Zodra de API-sleutel en regio zijn ingevoerd in de interface van de extensie, zou de gekleurde stip in de browserextensiebalk moeten veranderen om het energiegebruik in jouw regio weer te geven. Het geeft je ook een aanwijzing over welke energie-intensieve activiteiten geschikt zijn om te doen. Het idee achter dit 'stip'-systeem is geïnspireerd door de [Energy Lollipop-extensie](https://energylollipop.com/) voor emissies in Californië.

@ -108,7 +108,7 @@ quadrantChart
UI Elements: [0.9, 0.1]
```
![het raster van de canvas](../../../../translated_images/canvas_grid.5f209da785ded492a01ece440e3032afe51efa500cc2308e5ea4252487ceaf0b.nl.png)
![het raster van de canvas](../../../../translated_images/canvas_grid.5f209da785ded492.nl.png)
> Afbeelding van [MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
Om op het canvas-element te tekenen, volg je hetzelfde drie-stappenproces dat de basis vormt van alle canvasgraphics. Zodra je dit een paar keer hebt gedaan, wordt het een tweede natuur:
@ -329,11 +329,11 @@ Je gaat een webpagina maken met een Canvas-element. Het moet een zwart scherm va
- Heldenschip
![Heldenschip](../../../../translated_images/player.dd24c1afa8c71e9b82b2958946d4bad13308681392d4b5ddcc61a0e818ef8088.nl.png)
![Heldenschip](../../../../translated_images/player.dd24c1afa8c71e9b.nl.png)
- 5*5 monster
![Monsterschip](../../../../translated_images/enemyShip.5df2a822c16650c2fb3c06652e8ec8120cdb9122a6de46b9a1a56d54db22657f.nl.png)
![Monsterschip](../../../../translated_images/enemyShip.5df2a822c16650c2.nl.png)
### Aanbevolen stappen om te beginnen met ontwikkelen
@ -470,7 +470,7 @@ for (let x = START_X; x < STOP_X; x += ENEMY_SPACING) {
Het eindresultaat zou er zo uit moeten zien:
![Zwart scherm met een held en 5*5 monsters](../../../../translated_images/partI-solution.36c53b48c9ffae2a5e15496b23b604ba5393433e4bf91608a7a0a020eb7a2691.nl.png)
![Zwart scherm met een held en 5*5 monsters](../../../../translated_images/partI-solution.36c53b48c9ffae2a.nl.png)
## Oplossing

@ -160,7 +160,7 @@ sequenceDiagram
```
- **Puntensysteem**: Elk vernietigd vijandelijk schip levert 100 punten op (ronde getallen zijn gemakkelijker voor spelers om mentaal te berekenen). De score wordt weergegeven in de linkerbenedenhoek.
- **Leventeller**: Je held begint met drie levens - een standaard die door vroege arcadespellen werd vastgesteld om uitdaging en speelbaarheid in balans te brengen. Elke botsing met een vijand kost één leven. We tonen de resterende levens in de rechterbenedenhoek met scheepsiconen ![life image](../../../../translated_images/life.6fb9f50d53ee0413cd91aa411f7c296e10a1a6de5c4a4197c718b49bf7d63ebf.nl.png).
- **Leventeller**: Je held begint met drie levens - een standaard die door vroege arcadespellen werd vastgesteld om uitdaging en speelbaarheid in balans te brengen. Elke botsing met een vijand kost één leven. We tonen de resterende levens in de rechterbenedenhoek met scheepsiconen ![life image](../../../../translated_images/life.6fb9f50d53ee0413.nl.png).
## Laten we beginnen met bouwen!

@ -652,7 +652,7 @@ sequenceDiagram
Het gebruik van `history.pushState` creëert nieuwe invoeren in de navigatiegeschiedenis van de browser. Je kunt dat controleren door de *terugknop* van je browser ingedrukt te houden, het zou er ongeveer zo uit moeten zien:
![Screenshot van navigatiegeschiedenis](../../../../translated_images/history.7fdabbafa521e06455b738d3dafa3ff41d3071deae60ead8c7e0844b9ed987d8.nl.png)
![Screenshot van navigatiegeschiedenis](../../../../translated_images/history.7fdabbafa521e064.nl.png)
Als je een paar keer op de terugknop klikt, zie je dat de huidige URL verandert en de geschiedenis wordt bijgewerkt, maar dezelfde template blijft worden weergegeven.

@ -295,7 +295,7 @@ Laten we eerst observeren wat er gebeurt bij een basisformulierverzending:
2. Observeer de veranderingen in de adresbalk van je browser
3. Merk op hoe de pagina opnieuw laadt en gegevens in de URL verschijnen
![Screenshot van de URL-verandering in de browser na het klikken op de Registreren-knop](../../../../translated_images/click-register.e89a30bf0d4bc9ca867dc537c4cea679a7c26368bd790969082f524fed2355bc.nl.png)
![Screenshot van de URL-verandering in de browser na het klikken op de Registreren-knop](../../../../translated_images/click-register.e89a30bf0d4bc9ca.nl.png)
### Vergelijking van HTTP-methoden
@ -350,7 +350,7 @@ Laten we je registratieformulier configureren om correct te communiceren met de
2. **Klik** op de knop "Account aanmaken"
3. **Observeer** de serverrespons in je browser
![Een browservenster op het adres localhost:5000/api/accounts, met een JSON-string met gebruikersgegevens](../../../../translated_images/form-post.61de4ca1b964d91a9e338416e19f218504dd0af5f762fbebabfe7ae80edf885f.nl.png)
![Een browservenster op het adres localhost:5000/api/accounts, met een JSON-string met gebruikersgegevens](../../../../translated_images/form-post.61de4ca1b964d91a.nl.png)
**Wat je zou moeten zien:**
- **Browser verwijst** naar de API-eindpunt-URL
@ -615,7 +615,7 @@ async function register() {
3. **Klik** op "Account aanmaken"
4. **Observeer** de consoleberichten en gebruikersfeedback
![Screenshot met logbericht in de browserconsole](../../../../translated_images/browser-console.efaf0b51aaaf67782a29e1a0bb32cc063f189b18e894eb5926e02f1abe864ec2.nl.png)
![Screenshot met logbericht in de browserconsole](../../../../translated_images/browser-console.efaf0b51aaaf6778.nl.png)
**Wat je zou moeten zien:**
- **Laadstatus** verschijnt op de verzendknop
@ -790,7 +790,7 @@ Laten we je registratieformulier verbeteren met robuuste validatie die een uitst
3. **Probeer** speciale tekens in het gebruikersnaamveld
4. **Voer** een negatief saldo in
![Screenshot met validatiefout bij het proberen het formulier in te dienen](../../../../translated_images/validation-error.8bd23e98d416c22f80076d04829a4bb718e0e550fd622862ef59008ccf0d5dce.nl.png)
![Screenshot met validatiefout bij het proberen het formulier in te dienen](../../../../translated_images/validation-error.8bd23e98d416c22f.nl.png)
**Wat je zult zien:**
- **Browser toont** native validatiemeldingen
@ -952,7 +952,7 @@ Toon een foutmelding in de HTML als de gebruiker al bestaat.
Hier is een voorbeeld van hoe de uiteindelijke inlogpagina eruit kan zien na wat styling:
![Screenshot van de inlogpagina na het toevoegen van CSS-stijlen](../../../../translated_images/result.96ef01f607bf856aa9789078633e94a4f7664d912f235efce2657299becca483.nl.png)
![Screenshot van de inlogpagina na het toevoegen van CSS-stijlen](../../../../translated_images/result.96ef01f607bf856a.nl.png)
## Quiz na de les

@ -160,7 +160,7 @@ sequenceDiagram
Browser->>User: Displays new page (flash/reload)
```
![Update workflow in een multi-page applicatie](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.nl.png)
![Update workflow in een multi-page applicatie](../../../../translated_images/mpa.7f7375a1a2d4aa77.nl.png)
**Waarom deze aanpak onhandig aanvoelde:**
- Elke klik betekende dat de hele pagina opnieuw moest worden opgebouwd
@ -187,7 +187,7 @@ sequenceDiagram
Browser->>User: Shows updated content (no reload)
```
![Update workflow in een single-page applicatie](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.nl.png)
![Update workflow in een single-page applicatie](../../../../translated_images/spa.268ec73b41f992c2.nl.png)
**Waarom SPA's zoveel beter aanvoelen:**
- Alleen de delen die daadwerkelijk zijn veranderd worden bijgewerkt (slim, toch?)
@ -523,7 +523,7 @@ if (data.error) {
Nu, wanneer je test met een ongeldig account, zie je een nuttige foutmelding direct op de pagina!
![Screenshot van de foutmelding die wordt weergegeven tijdens het inloggen](../../../../translated_images/login-error.416fe019b36a63276764c2349df5d99e04ebda54fefe60c715ee87a28d5d4ad0.nl.png)
![Screenshot van de foutmelding die wordt weergegeven tijdens het inloggen](../../../../translated_images/login-error.416fe019b36a6327.nl.png)
#### Stap 4: Inclusief zijn met toegankelijkheid
@ -961,7 +961,7 @@ Klaar om je bankingapp naar een hoger niveau te tillen? Laten we ervoor zorgen d
Hier is hoe een gepolijst dashboard eruit zou kunnen zien:
![Screenshot van een voorbeeldresultaat van het dashboard na styling](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.nl.png)
![Screenshot van een voorbeeldresultaat van het dashboard na styling](../../../../translated_images/screen2.123c82a831a1d14a.nl.png)
Voel je niet verplicht om dit precies na te maken - gebruik het als inspiratie en maak er je eigen versie van!

@ -190,7 +190,7 @@ Net als het compartimentontwerp van de Titanic dat robuust leek totdat meerdere
In plaats van achter de feiten aan te lopen, gaan we een **gecentraliseerd state management** systeem creëren. Denk eraan als één echt georganiseerd persoon die verantwoordelijk is voor alle belangrijke zaken:
![Schema dat de datastromen toont tussen de HTML, gebruikersacties en state](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.nl.png)
![Schema dat de datastromen toont tussen de HTML, gebruikersacties en state](../../../../translated_images/data-flow.fa2354e0908fecc8.nl.png)
```mermaid
flowchart TD
@ -803,7 +803,7 @@ Deze uitdaging helpt u te denken als een professionele ontwikkelaar die zowel ge
Hier is een voorbeeldresultaat na het voltooien van de opdracht:
![Screenshot van een voorbeeld "Transactie toevoegen"-dialoogvenster](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.nl.png)
![Screenshot van een voorbeeld "Transactie toevoegen"-dialoogvenster](../../../../translated_images/dialog.93bba104afeb79f1.nl.png)
---

@ -112,7 +112,7 @@ Raadpleeg de [server API-documentatie](../api/README.md) voor:
**Verwacht Resultaat:**
Na het voltooien van deze opdracht moet je bankapp een volledig functionele "Transactie Toevoegen"-functie hebben die er professioneel uitziet en zich professioneel gedraagt:
![Screenshot van een voorbeeld "Transactie Toevoegen" dialoog](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.nl.png)
![Screenshot van een voorbeeld "Transactie Toevoegen" dialoog](../../../../translated_images/dialog.93bba104afeb79f1.nl.png)
## Testen van je Implementatie

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
In dit project leer je hoe je een fictieve bank kunt bouwen. Deze lessen bevatten instructies over hoe je een webapp kunt opzetten en routes kunt toevoegen, formulieren kunt bouwen, de status kunt beheren en gegevens kunt ophalen van een API waarmee je de gegevens van de bank kunt ophalen.
| ![Scherm1](../../../translated_images/screen1.baccbba0f1f93364672eb250d2fbd21574bb1caf79a2155022dc098a741cbdfe.nl.png) | ![Scherm2](../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.nl.png) |
| ![Scherm1](../../../translated_images/screen1.baccbba0f1f93364.nl.png) | ![Scherm2](../../../translated_images/screen2.123c82a831a1d14a.nl.png) |
|--------------------------------|--------------------------------|
## Lessen

@ -185,7 +185,7 @@ Net zoals de telefoon van Alexander Graham Bell verre locaties verbond, verbindt
Zodra alles is geladen, zie je een prachtig schone werkruimte die is ontworpen om je gefocust te houden op wat belangrijk is je code!
![Standaard VSCode.dev interface](../../../../translated_images/default-vscode-dev.5d06881d65c1b3234ce50cd9ed3b0028e6031ad5f5b441bcbed96bfa6311f6d0.nl.png)
![Standaard VSCode.dev interface](../../../../translated_images/default-vscode-dev.5d06881d65c1b323.nl.png)
**Hier is je rondleiding door de buurt:**
- **Activiteitenbalk** (die strook links): Je hoofdnavigatie met Explorer 📁, Zoeken 🔍, Source Control 🌿, Extensies 🧩, en Instellingen ⚙️
@ -233,7 +233,7 @@ Dit is perfect wanneer je nieuw begint in VSCode.dev en een specifieke repositor
1. Ga naar [vscode.dev](https://vscode.dev) als je daar nog niet bent
2. Zoek de knop "Open Remote Repository" op het welkomstscherm en klik erop
![Open remote repository](../../../../translated_images/open-remote-repository.bd9c2598b8949e7fc283cdfc8f4050c6205a7c7c6d3f78c4b135115d037d6fa2.nl.png)
![Open remote repository](../../../../translated_images/open-remote-repository.bd9c2598b8949e7f.nl.png)
3. Plak een GitHub-repository-URL (probeer deze: `https://github.com/microsoft/Web-Dev-For-Beginners`)
4. Druk op Enter en zie de magie gebeuren!
@ -242,7 +242,7 @@ Dit is perfect wanneer je nieuw begint in VSCode.dev en een specifieke repositor
Wil je je als een codeerwizard voelen? Probeer deze sneltoets: Ctrl+Shift+P (of Cmd+Shift+P op Mac) om de Command Palette te openen:
![Command Palette](../../../../translated_images/palette-menu.4946174e07f426226afcdad707d19b8d5150e41591c751c45b5dee213affef91.nl.png)
![Command Palette](../../../../translated_images/palette-menu.4946174e07f42622.nl.png)
**De Command Palette is als een zoekmachine voor alles wat je kunt doen:**
- Typ "open remote" en het vindt de repository-opener voor je
@ -304,7 +304,7 @@ Net zoals het organiseren van blauwdrukken in het kantoor van een architect, vol
3. Voer de bestandsnaam in, inclusief de juiste extensie (`style.css`, `script.js`, `index.html`)
4. Druk op Enter om het bestand te maken
![Een nieuw bestand maken](../../../../translated_images/create-new-file.2814e609c2af9aeb6c6fd53156c503ac91c3d538f9cac63073b2dd4a7631f183.nl.png)
![Een nieuw bestand maken](../../../../translated_images/create-new-file.2814e609c2af9aeb.nl.png)
**Naamgevingsconventies:**
- Gebruik beschrijvende namen die het doel van het bestand aangeven
@ -322,7 +322,7 @@ Hier begint het echte plezier! De editor van VSCode.dev zit boordevol handige fu
2. Begin met typen en zie hoe VSCode.dev je helpt met kleuren, suggesties en foutdetectie
3. Sla je werk op met Ctrl+S (Windows/Linux) of Cmd+S (Mac) hoewel het ook automatisch opslaat!
![Bestanden bewerken in VSCode.dev](../../../../translated_images/edit-a-file.52c0ee665ef19f08119d62d63f395dfefddc0a4deb9268d73bfe791f52c5807a.nl.png)
![Bestanden bewerken in VSCode.dev](../../../../translated_images/edit-a-file.52c0ee665ef19f08.nl.png)
**De coole dingen die gebeuren terwijl je codeert:**
- Je code wordt prachtig ingekleurd, zodat het gemakkelijk te lezen is
@ -343,7 +343,7 @@ Net zoals archeologen gedetailleerde verslagen maken van opgravingslagen, houdt
2. Gewijzigde bestanden verschijnen in de sectie "Changes"
3. Kleuraanduidingen geven wijzigingstypen aan: groen voor toevoegingen, rood voor verwijderingen
![Wijzigingen bekijken in Source Control](../../../../translated_images/working-tree.c58eec08e6335c79cc708c0c220c0b7fea61514bd3c7fb7471905a864aceac7c.nl.png)
![Wijzigingen bekijken in Source Control](../../../../translated_images/working-tree.c58eec08e6335c79.nl.png)
**Je werk opslaan (de commit-workflow):**
@ -438,7 +438,7 @@ De extensiemarkt is heel overzichtelijk, dus je raakt niet verdwaald terwijl je
2. Blader rond of zoek naar iets specifieks
3. Klik op iets interessants om er meer over te leren
![Interface van de extensiemarkt](../../../../translated_images/extensions.eca0e0c7f59a10b5c88be7fe24b3e32cca6b6058b35a49026c3a9d80b1813b7c.nl.png)
![Interface van de extensiemarkt](../../../../translated_images/extensions.eca0e0c7f59a10b5.nl.png)
**Wat je daar zult zien:**
@ -491,7 +491,7 @@ De meeste extensies hebben instellingen die je kunt aanpassen zodat ze precies w
3. Kies "Extensie-instellingen" in het dropdownmenu
4. Pas dingen aan totdat ze perfect aansluiten bij jouw workflow
![Instellingen van extensies aanpassen](../../../../translated_images/extension-settings.21c752ae4f4cdb78a867f140ccd0680e04619d0c44bb4afb26373e54b829d934.nl.png)
![Instellingen van extensies aanpassen](../../../../translated_images/extension-settings.21c752ae4f4cdb78.nl.png)
**Veelvoorkomende dingen die je wilt aanpassen:**
- Hoe je code wordt geformatteerd (tabs vs spaties, regellengte, etc.)

@ -78,7 +78,7 @@ Omdat VSCode.dev ten minste één bestand nodig heeft om een repository te opene
4. **Schrijf** een commitbericht: "Voeg initiële HTML-structuur toe"
5. **Klik op** "Commit new file" om je wijzigingen op te slaan
![Een initiëel bestand maken op GitHub](../../../../translated_images/new-file-github.com.c886796d800e8056561829a181be1382c5303da9d902d8b2dd82b68a4806e21f.nl.png)
![Een initiëel bestand maken op GitHub](../../../../translated_images/new-file-github.com.c886796d800e8056.nl.png)
**Wat deze initiële setup bereikt:**
- **Stelt** een correcte HTML5-documentstructuur in met semantische elementen
@ -104,7 +104,7 @@ Nu de basis van je repository is opgezet, schakelen we over naar VSCode.dev voor
**Succesindicator**: Je zou je projectbestanden moeten zien in de Explorer-zijbalk en `index.html` beschikbaar voor bewerking in het hoofdeditorgebied.
![Project geladen in VSCode.dev](../../../../translated_images/project-on-vscode.dev.e79815a9a95ee7feac72ebe5c941c91279716be37c575dbdbf2f43bea2c7d8b6.nl.png)
![Project geladen in VSCode.dev](../../../../translated_images/project-on-vscode.dev.e79815a9a95ee7fe.nl.png)
**Wat je ziet in de interface:**
- **Explorer-zijbalk**: **Toont** je repository-bestanden en mapstructuur
@ -448,7 +448,7 @@ Extensies verbeteren je ontwikkelervaring door live preview-mogelijkheden en ver
**Directe resultaten na installatie:**
Zodra CodeSwing is geïnstalleerd, zie je een live preview van je CV-website verschijnen in de editor. Hierdoor kun je precies zien hoe je site eruitziet terwijl je wijzigingen aanbrengt.
![CodeSwing-extensie met live preview](../../../../translated_images/after-codeswing-extension-pb.0ebddddcf73b550994947a9084e35e2836c713ae13839d49628e3c764c1cfe83.nl.png)
![CodeSwing-extensie met live preview](../../../../translated_images/after-codeswing-extension-pb.0ebddddcf73b5509.nl.png)
**Begrip van de verbeterde interface:**
- **Gesplitst scherm**: **Toont** je code aan de ene kant en een live preview aan de andere kant

@ -61,7 +61,7 @@ print(response.choices[0].message.content)
Zo ziet je voltooide project eruit:
![Chat-app interface die een gesprek toont tussen gebruiker en AI-assistent](../../../translated_images/screenshot.0a1ee0d123df681b4501eb53ffb267519fcc20aa653eabecef1e7561ddfb1cab.nl.png)
![Chat-app interface die een gesprek toont tussen gebruiker en AI-assistent](../../../translated_images/screenshot.0a1ee0d123df681b.nl.png)
## 🗺️ Jouw leertraject door AI-toepassingsontwikkeling
@ -194,7 +194,7 @@ mindmap
**Kernprincipe**: AI-toepassingsontwikkeling combineert traditionele webontwikkelingsvaardigheden met AI-dienstintegratie, waardoor intelligente toepassingen ontstaan die natuurlijk en responsief aanvoelen voor gebruikers.
![GitHub Models AI Playground interface met modelselectie en testgebied](../../../translated_images/playground.d2b927122224ff8ff4028fc842176e353c339147d8925455f36c92fb1655c477.nl.png)
![GitHub Models AI Playground interface met modelselectie en testgebied](../../../translated_images/playground.d2b927122224ff8f.nl.png)
**Waarom de playground zo handig is:**
- **Probeer** verschillende AI-modellen zoals GPT-4o-mini, Claude en anderen (allemaal gratis!)
@ -204,7 +204,7 @@ mindmap
Zodra je wat hebt geëxperimenteerd, klik je gewoon op het tabblad "Code" en kies je je programmeertaal om de implementatiecode te krijgen die je nodig hebt.
![Playground keuze toont codegeneratie-opties voor verschillende programmeertalen](../../../translated_images/playground-choice.1d23ba7d407f47584c9f446c77f0bcf70cae794cc9c8d7849a3cca4a3693e6c4.nl.png)
![Playground keuze toont codegeneratie-opties voor verschillende programmeertalen](../../../translated_images/playground-choice.1d23ba7d407f4758.nl.png)
## Het instellen van de Python backend-integratie
@ -2365,14 +2365,14 @@ Wil je dit project uitproberen in een cloudontwikkelingsomgeving? GitHub Codespa
- **Ga naar** de [Web Dev For Beginners repository](https://github.com/microsoft/Web-Dev-For-Beginners)
- **Klik** op "Use this template" in de rechterbovenhoek (zorg ervoor dat je bent ingelogd op GitHub)
![Interface voor het maken van een template met de groene knop "Use this template"](../../../translated_images/template.67ad477109d29a2b04599a83c964c87fcde041256d4f04d3589cbb00c696f76c.nl.png)
![Interface voor het maken van een template met de groene knop "Use this template"](../../../translated_images/template.67ad477109d29a2b.nl.png)
**Stap 2: Codespaces Starten**
- **Open** je nieuw aangemaakte repository
- **Klik** op de groene knop "Code" en selecteer "Codespaces"
- **Kies** "Create codespace on main" om je ontwikkelomgeving te starten
![Interface voor het maken van een codespace met opties voor het starten van een cloudontwikkelingsomgeving](../../../translated_images/codespace.bcecbdf5d2747d3d17da67a78ad911c8853d68102e34748ec372cde1e9236e1d.nl.png)
![Interface voor het maken van een codespace met opties voor het starten van een cloudontwikkelingsomgeving](../../../translated_images/codespace.bcecbdf5d2747d3d.nl.png)
**Stap 3: Omgevingsconfiguratie**
Zodra je Codespace is geladen, heb je toegang tot:

@ -1,260 +1,252 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "63e29f5a308b533df9d70336bbb2e2b8",
"translation_date": "2025-11-25T17:59:21+00:00",
"original_hash": "fea3a0fceb8ad86fd640c09cf63a2aac",
"translation_date": "2026-01-07T01:03:20+00:00",
"source_file": "README.md",
"language_code": "nl"
}
-->
[![GitHub license](https://img.shields.io/github/license/microsoft/Web-Dev-For-Beginners.svg)](https://github.com/microsoft/Web-Dev-For-Beginners/blob/master/LICENSE)
[![GitHub contributors](https://img.shields.io/github/contributors/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/graphs/contributors/)
[![GitHub issues](https://img.shields.io/github/issues/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/issues/)
[![GitHub pull-requests](https://img.shields.io/github/issues-pr/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/pulls/)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
# Webontwikkeling voor beginners - Een curriculum
[![GitHub watchers](https://img.shields.io/github/watchers/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Watch&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/watchers/)
[![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Fork&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/network/)
[![GitHub stars](https://img.shields.io/github/stars/microsoft/Web-Dev-For-Beginners.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/stargazers/)
Leer de basisprincipes van webontwikkeling met onze 12 weken durende uitgebreide cursus van Microsoft Cloud Advocates. Elke van de 24 lessen duikt in JavaScript, CSS en HTML door middel van praktische projecten zoals terrariums, browserextensies en ruimtespellen. Doe mee met quizzen, discussies en praktische opdrachten. Verbeter je vaardigheden en optimaliseer je kennisretentie met onze effectieve projectgerichte didactiek. Begin vandaag nog met coderen!
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
Doe mee met de Azure AI Foundry Discord-community
# Webontwikkeling voor Beginners - Een Curriculum
Volg deze stappen om aan de slag te gaan met deze bronnen:
1. **Fork de repository**: Klik [![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-beginners.svg?style=social&label=Fork)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/fork)
2. **Clone de repository**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
3. [**Word lid van de Azure AI Foundry Discord en ontmoet experts en medeontwikkelaars**](https://discord.com/invite/ByRwuEEgH4)
Leer de basisprincipes van webontwikkeling met onze 12-weekse uitgebreide cursus van Microsoft Cloud Advocates. Elke van de 24 lessen behandelt JavaScript, CSS en HTML via praktische projecten zoals terrariums, browserextensies en ruimtegames. Doe mee met quizzen, discussies en praktische opdrachten. Verhoog je vaardigheden en optimaliseer je kennisbehoud met onze effectieve projectgerichte aanpak. Begin vandaag nog met je codeerreis!
### 🌐 Ondersteuning in meerdere talen
Word lid van de Azure AI Foundry Discord Community
#### Ondersteund via GitHub Action (Geautomatiseerd & altijd up-to-date)
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
Volg deze stappen om aan de slag te gaan met deze bronnen:
1. **Fork de Repository**: Klik [![GitHub forks](https://img.shields.io/github/forks/microsoft/Web-Dev-For-beginners.svg?style=social&label=Fork)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/fork)
2. **Clone de Repository**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
3. [**Word lid van de Azure AI Foundry Discord en ontmoet experts en mede-ontwikkelaars**](https://discord.com/invite/ByRwuEEgH4)
### 🌐 Meertalige Ondersteuning
#### Ondersteund via GitHub Action (Automatisch & Altijd Up-to-Date)
<!-- CO-OP TRANSLATOR LANGUAGES TABLE START -->
[Arabisch](../ar/README.md) | [Bengaals](../bn/README.md) | [Bulgaars](../bg/README.md) | [Birmaans (Myanmar)](../my/README.md) | [Chinees (Vereenvoudigd)](../zh/README.md) | [Chinees (Traditioneel, Hong Kong)](../hk/README.md) | [Chinees (Traditioneel, Macau)](../mo/README.md) | [Chinees (Traditioneel, Taiwan)](../tw/README.md) | [Kroatisch](../hr/README.md) | [Tsjechisch](../cs/README.md) | [Deens](../da/README.md) | [Nederlands](./README.md) | [Ests](../et/README.md) | [Fins](../fi/README.md) | [Frans](../fr/README.md) | [Duits](../de/README.md) | [Grieks](../el/README.md) | [Hebreeuws](../he/README.md) | [Hindi](../hi/README.md) | [Hongaars](../hu/README.md) | [Indonesisch](../id/README.md) | [Italiaans](../it/README.md) | [Japans](../ja/README.md) | [Koreaans](../ko/README.md) | [Litouws](../lt/README.md) | [Maleis](../ms/README.md) | [Marathi](../mr/README.md) | [Nepalees](../ne/README.md) | [Noors](../no/README.md) | [Perzisch (Farsi)](../fa/README.md) | [Pools](../pl/README.md) | [Portugees (Brazilië)](../br/README.md) | [Portugees (Portugal)](../pt/README.md) | [Punjabi (Gurmukhi)](../pa/README.md) | [Roemeens](../ro/README.md) | [Russisch](../ru/README.md) | [Servisch (Cyrillisch)](../sr/README.md) | [Slowaaks](../sk/README.md) | [Sloveens](../sl/README.md) | [Spaans](../es/README.md) | [Swahili](../sw/README.md) | [Zweeds](../sv/README.md) | [Tagalog (Filipino)](../tl/README.md) | [Tamil](../ta/README.md) | [Thais](../th/README.md) | [Turks](../tr/README.md) | [Oekraïens](../uk/README.md) | [Urdu](../ur/README.md) | [Vietnamees](../vi/README.md)
<!-- CO-OP TRANSLATOR LANGUAGES TABLE END -->
> **Voorkeur om lokaal te klonen?**
**Als je extra vertalingen wilt, staan de ondersteunde talen [hier](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
> Deze repository bevat vertalingen in 50+ talen, wat de downloadgrootte aanzienlijk vergroot. Om te klonen zonder vertalingen, gebruik sparse checkout:
> ```bash
> git clone --filter=blob:none --sparse https://github.com/microsoft/Web-Dev-For-Beginners.git
> cd Web-Dev-For-Beginners
> git sparse-checkout set --no-cone '/*' '!translations' '!translated_images'
> ```
> Dit geeft je alles wat je nodig hebt om de cursus te voltooien met een veel snellere download.
[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode&label=&message=Open%20in%20Visual%20Studio%20Code&labelColor=2c2c32&color=007acc&logoColor=007acc)](https://open.vscode.dev/microsoft/Web-Dev-For-Beginners)
**Als je extra vertalingsondersteuning wenst, zijn ondersteunde talen hier vermeld [hier](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
#### 🧑‍🎓 _Ben je een student?_
Bezoek de [**Student Hub-pagina**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon) waar je beginnersbronnen, studentpakketten en zelfs manieren vindt om een gratis certificaatvoucher te krijgen. Dit is de pagina die je wilt bookmarken en regelmatig wilt bekijken, aangezien we maandelijks de inhoud wisselen.
Bezoek de [**Student Hub-pagina**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon) waar je beginnersmaterialen, studentenpakketten en zelfs mogelijkheden voor een gratis certificaatvoucher vindt. Dit is de pagina die je wilt bookmarken en van tijd tot tijd wilt bekijken, omdat we maandelijks de inhoud vernieuwen.
### 📣 Aankondiging - Nieuwe GitHub Copilot Agent-modus uitdagingen om te voltooien!
### 📣 Aankondiging - Nieuwe GitHub Copilot Agent modus uitdagingen om te voltooien!
Nieuwe uitdaging toegevoegd, zoek naar "GitHub Copilot Agent Challenge 🚀" in de meeste hoofdstukken. Dit is een nieuwe uitdaging die je kunt voltooien met GitHub Copilot en Agent-modus. Als je Agent-modus nog niet hebt gebruikt, het kan niet alleen tekst genereren, maar ook bestanden maken en bewerken, opdrachten uitvoeren en meer.
Nieuwe uitdaging toegevoegd, zoek naar "GitHub Copilot Agent Challenge 🚀" in de meeste hoofdstukken. Dat is een nieuwe uitdaging die je kunt voltooien met GitHub Copilot en de Agent-modus. Als je deze modus nog niet hebt gebruikt, kan het niet alleen tekst genereren, maar ook bestanden maken en bewerken, commando's uitvoeren en meer.
### 📣 Aankondiging - _Nieuw Project om te bouwen met Generatieve AI_
### 📣 Aankondiging - _Nieuw project te bouwen met Generative AI_
Nieuw AI-assistentproject zojuist toegevoegd, bekijk het [project](./09-chat-project/README.md)
Nieuw AI Assistant-project toegevoegd, bekijk het [project](./9-chat-project/README.md)
### 📣 Aankondiging - _Nieuw Curriculum_ over Generatieve AI voor JavaScript is zojuist uitgebracht
### 📣 Aankondiging - _Nieuw Curriculum_ over Generative AI voor JavaScript is net uitgebracht
Mis ons nieuwe Generatieve AI-curriculum niet!
Mis ons nieuwe Generative AI curriculum niet!
Bezoek [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) om te beginnen!
![Achtergrond](../../translated_images/background.148a8d43afde57303419a663f50daf586681bc2fabf833f66ef6954073983c66.nl.png)
- Lessen die alles behandelen van basis tot RAG.
- Interactie met historische figuren via GenAI en onze begeleidende app.
- Leuk en boeiend verhaal, je reist door de tijd!
- Lessen die alles behandelen, van basisprincipes tot RAG.
- Interactie met historische personages met GenAI en onze begeleidende app.
- Leuk en boeiend verhaal, je gaat tijdreizen!
![personage](../../translated_images/character.5c0dd8e067ffd693c16e2c5b7412ab075a2215ce31f998305639fa3a05e14fbe.nl.png)
Elke les bevat een opdracht om te voltooien, een kenniscontrole en een uitdaging om je te begeleiden bij het leren van onderwerpen zoals:
Elke les bevat een opdracht om te voltooien, een kennistoets en een uitdaging om je te begeleiden bij het leren van onderwerpen zoals:
- Prompting en prompt engineering
- Tekst- en afbeeldingsapp-generatie
- Tekst- en beeldapp-generatie
- Zoekapps
Bezoek [https://aka.ms/genai-js-course](../../[https:/aka.ms/genai-js-course) om te beginnen!
Bezoek [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) om te beginnen!
## 🌱 Aan de slag
> **Docenten**, we hebben [enkele suggesties opgenomen](for-teachers.md) over hoe je dit curriculum kunt gebruiken. We horen graag je feedback [in ons discussieforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
> **Docenten**, we hebben [een aantal suggesties opgenomen](for-teachers.md) over hoe je dit curriculum kunt gebruiken. We horen graag je feedback [in ons discussieforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
**[Leerlingen](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, begin voor elke les met een quiz voorafgaand aan de les en ga verder met het lezen van het lesmateriaal, het voltooien van de verschillende activiteiten en controleer je begrip met de quiz na de les.
**[Leerlingen](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, begin bij elke les met een pre-lecture quiz en volg deze op met het lezen van het lesmateriaal, het voltooien van de verschillende activiteiten en controleer je begrip met de post-lecture quiz.
Om je leerervaring te verbeteren, werk samen met je medestudenten aan de projecten! Discussies worden aangemoedigd in ons [discussieforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions) waar ons team van moderators beschikbaar zal zijn om je vragen te beantwoorden.
Verbeter je leerervaring door samen met je medestudenten aan de projecten te werken! Discussies worden aangemoedigd in ons [discussieforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions) waar ons team van moderators beschikbaar zal zijn om je vragen te beantwoorden.
Om je opleiding verder te ontwikkelen, raden we aan om [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) te verkennen voor aanvullende studiematerialen.
Om je opleiding verder te verrijken raden we aan de extra studiematerialen op [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) te verkennen.
### 📋 Je omgeving instellen
Dit curriculum heeft een ontwikkelomgeving die klaar is voor gebruik! Zodra je begint, kun je ervoor kiezen om het curriculum te draaien in een [Codespace](https://github.com/features/codespaces/) (_een browsergebaseerde omgeving zonder installaties nodig_), of lokaal op je computer met een teksteditor zoals [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
Dit curriculum heeft een kant-en-klare ontwikkelomgeving! Je kunt ervoor kiezen om het curriculum te draaien in een [Codespace](https://github.com/features/codespaces/) (_een browsergebaseerde omgeving zonder installatie_) of lokaal op je computer met een teksteditor zoals [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
#### Maak je repository aan
Om je werk gemakkelijk op te slaan, raden we aan om je eigen kopie van deze repository te maken. Dit kun je doen door op de knop **Use this template** bovenaan de pagina te klikken. Dit maakt een nieuwe repository in je GitHub-account met een kopie van het curriculum.
#### Creëer je repository
Om je werk makkelijk op te slaan, wordt aanbevolen om een eigen kopie van deze repository te maken. Dit kan door bovenaan de pagina op de knop **Use this template** te klikken. Hierdoor wordt een nieuwe repository gemaakt in jouw GitHub-account met een kopie van het curriculum.
Volg deze stappen:
1. **Fork de Repository**: Klik op de knop "Fork" rechtsboven op deze pagina.
2. **Clone de Repository**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
Volg de volgende stappen:
1. **Fork de repository**: Klik op de knop "Fork" rechtsboven op deze pagina.
2. **Clone de repository**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
#### Het curriculum draaien in een Codespace
In je kopie van deze repository die je hebt gemaakt, klik op de knop **Code** en selecteer **Open with Codespaces**. Dit maakt een nieuwe Codespace voor je om in te werken.
Klik in jouw eigen repository op de knop **Code** en selecteer **Open with Codespaces**. Dit maakt een nieuwe Codespace aan waarin je kunt werken.
![Codespace](../../translated_images/createcodespace.0238bbf4d7a8d955fa8fa7f7b6602a3cb6499a24708fbee589f83211c5a613b7.nl.png)
![Codespace](../../translated_images/createcodespace.0238bbf4d7a8d955.nl.png)
#### Het curriculum lokaal draaien op je computer
Om dit curriculum lokaal op je computer te draaien, heb je een teksteditor, een browser en een opdrachtregeltool nodig. Onze eerste les, [Introductie tot Programmeertalen en Tools van het Vak](../../1-getting-started-lessons/1-intro-to-programming-languages), zal je door verschillende opties voor elk van deze tools leiden, zodat je kunt kiezen wat het beste voor je werkt.
Om dit curriculum lokaal te draaien op je computer, heb je een teksteditor, een browser en een opdrachtregeltool nodig. Onze eerste les, [Introductie tot programmeertalen en tools van het vak](../../1-getting-started-lessons/1-intro-to-programming-languages), laat je verschillende opties zien van elk van deze tools zodat je degene kunt kiezen die het beste bij je past.
Onze aanbeveling is om [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) te gebruiken als je editor, die ook een ingebouwde [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) heeft. Je kunt Visual Studio Code [hier downloaden](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
Wij raden aan [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) te gebruiken als editor, die ook een ingebouwde [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) bevat. Je kunt Visual Studio Code [hier downloaden](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
1. Clone je repository naar je computer. Dit kun je doen door op de knop **Code** te klikken en de URL te kopiëren:
1. Clone je repository naar je computer. Dit doe je door op de knop **Code** te klikken en de URL te kopiëren:
[CodeSpace](./images/createcodespace.png)
Open vervolgens [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) binnen [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) en voer het volgende commando uit, waarbij je `<your-repository-url>` vervangt door de URL die je net hebt gekopieerd:
Open vervolgens [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) binnen [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) en voer het volgende commando uit, waarbij je `<your-repository-url>` vervangt door de URL die je zojuist hebt gekopieerd:
```bash
git clone <your-repository-url>
```
2. Open de map in Visual Studio Code. Dit kun je doen door te klikken op **File** > **Open Folder** en de map te selecteren die je net hebt gekloond.
> Aanbevolen Visual Studio Code-extensies:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - om HTML-pagina's te bekijken binnen Visual Studio Code
2. Open de map in Visual Studio Code. Dit kun je doen door te klikken op **Bestand** > **Map openen** en de map te selecteren die je zojuist hebt gekloond.
> Aanbevolen Visual Studio Code-extensies:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - om HTML-pagina's binnen Visual Studio Code te bekijken
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - om je te helpen sneller code te schrijven
## 📂 Elke les bevat:
- optionele sketchnote
- optionele aanvullende video
- opwarmquiz voorafgaand aan de les
- warming-up quiz voor de les
- geschreven les
- voor projectgebaseerde lessen, stapsgewijze handleidingen om het project te bouwen
- kennischecks
- voor projectgebaseerde lessen, stapsgewijze handleidingen over hoe je het project bouwt
- kennistests
- een uitdaging
- aanvullende literatuur
- aanvullende leesstof
- opdracht
- [quiz na de les](https://ff-quizzes.netlify.app/web/)
> **Een opmerking over quizzen**: Alle quizzen zijn opgenomen in de Quiz-app map, in totaal 48 quizzen met elk drie vragen. Ze zijn beschikbaar [hier](https://ff-quizzes.netlify.app/web/) en de quiz-app kan lokaal worden uitgevoerd of worden gedeployed naar Azure; volg de instructies in de `quiz-app` map.
> **Een opmerking over quizzen**: Alle quizzen bevinden zich in de Quiz-app map, in totaal 48 quizzen met elk drie vragen. Ze zijn beschikbaar [hier](https://ff-quizzes.netlify.app/web/). De quiz-app kan lokaal worden uitgevoerd of worden ingezet op Azure; volg de instructies in de `quiz-app` map.
## 🗃️ Lessen
| | Projectnaam | Geleerde concepten | Leerdoelen | Gelinkte les | Auteur |
| :-: | :------------------------------------------------------: | :--------------------------------------------------------------------: | ----------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------: | :---------------------: |
| 01 | Aan de slag | Introductie tot programmeren en tools van het vak | Leer de basisprincipes achter de meeste programmeertalen en over software die professionele ontwikkelaars helpt hun werk te doen | [Introductie tot programmeertalen en tools van het vak](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Aan de slag | Basisprincipes van GitHub, inclusief werken in een team | Hoe GitHub te gebruiken in je project, hoe samen te werken met anderen aan een codebase | [Introductie tot GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Aan de slag | Toegankelijkheid | Leer de basisprincipes van webtoegankelijkheid | [Basisprincipes van toegankelijkheid](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS Basisprincipes | JavaScript Datatypes | De basisprincipes van JavaScript datatypes | [Datatypes](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS Basisprincipes | Functies en Methoden | Leer over functies en methoden om de logische stroom van een applicatie te beheren | [Functies en Methoden](./2-js-basics/2-functions-methods/README.md) | Jasmine en Christopher |
| 06 | JS Basisprincipes | Beslissingen nemen met JS | Leer hoe je voorwaarden in je code kunt maken met behulp van besluitvormingsmethoden | [Beslissingen nemen](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS Basisprincipes | Arrays en Lussen | Werk met data met behulp van arrays en lussen in JavaScript | [Arrays en Lussen](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML in de praktijk | Bouw de HTML om een online terrarium te maken, met de focus op het bouwen van een layout | [Introductie tot HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS in de praktijk | Bouw de CSS om het online terrarium te stylen, met de focus op de basisprincipes van CSS inclusief het responsief maken van de pagina | [Introductie tot CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | JavaScript Closures, DOM manipulatie | Bouw de JavaScript om het terrarium te laten functioneren als een drag/drop interface, met de focus op closures en DOM manipulatie | [JavaScript Closures, DOM manipulatie](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typingspel](./4-typing-game/solution/README.md) | Bouw een Typingspel | Leer hoe je toetsenbordgebeurtenissen kunt gebruiken om de logica van je JavaScript-app aan te sturen | [Event-Driven Programming](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Groene Browserextensie](./5-browser-extension/solution/README.md) | Werken met Browsers | Leer hoe browsers werken, hun geschiedenis, en hoe je de eerste elementen van een browserextensie kunt opzetten | [Over Browsers](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Groene Browserextensie](./5-browser-extension/solution/README.md) | Een formulier bouwen, een API aanroepen en variabelen opslaan in lokale opslag | Bouw de JavaScript-elementen van je browserextensie om een API aan te roepen met variabelen opgeslagen in lokale opslag | [API's, Formulieren, en Lokale Opslag](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Groene Browserextensie](./5-browser-extension/solution/README.md) | Achtergrondprocessen in de browser, webprestaties | Gebruik de achtergrondprocessen van de browser om het pictogram van de extensie te beheren; leer over webprestaties en enkele optimalisaties om te maken | [Achtergrondtaken en Prestaties](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Ruimtespel](./6-space-game/solution/README.md) | Meer Geavanceerde Spelontwikkeling met JavaScript | Leer over Inheritance met zowel Classes als Composition en het Pub/Sub patroon, ter voorbereiding op het bouwen van een spel | [Introductie tot Geavanceerde Spelontwikkeling](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Ruimtespel](./6-space-game/solution/README.md) | Tekenen op canvas | Leer over de Canvas API, gebruikt om elementen op een scherm te tekenen | [Tekenen op Canvas](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Ruimtespel](./6-space-game/solution/README.md) | Elementen bewegen over het scherm | Ontdek hoe elementen beweging kunnen krijgen met behulp van cartesiaanse coördinaten en de Canvas API | [Elementen Bewegen](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Ruimtespel](./6-space-game/solution/README.md) | Botsingsdetectie | Laat elementen botsen en op elkaar reageren met behulp van toetsen en zorg voor een cooldown functie om de prestaties van het spel te garanderen | [Botsingsdetectie](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Ruimtespel](./6-space-game/solution/README.md) | Score bijhouden | Voer wiskundige berekeningen uit op basis van de status en prestaties van het spel | [Score Bijhouden](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Ruimtespel](./6-space-game/solution/README.md) | Het spel beëindigen en opnieuw starten | Leer over het beëindigen en opnieuw starten van het spel, inclusief het opruimen van assets en het resetten van variabele waarden | [De Eindconditie](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Bankapp](./7-bank-project/solution/README.md) | HTML Templates en Routes in een Webapp | Leer hoe je de structuur van een meerpagina website kunt opzetten met routing en HTML templates | [HTML Templates en Routes](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Bankapp](./7-bank-project/solution/README.md) | Bouw een Inlog- en Registratieformulier | Leer over het bouwen van formulieren en het afhandelen van validatieroutines | [Formulieren](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Bankapp](./7-bank-project/solution/README.md) | Methoden om Data op te halen en te gebruiken | Hoe data in en uit je app stroomt, hoe je het kunt ophalen, opslaan en verwijderen | [Data](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Bankapp](./7-bank-project/solution/README.md) | Concepten van State Management | Leer hoe je app de staat behoudt en hoe je deze programmatisch kunt beheren | [State Management](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Browser/VScode Code](../../8-code-editor) | Werken met VScode | Leer hoe je een code-editor gebruikt | [Gebruik VScode Code Editor](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Assistenten](./9-chat-project/README.md) | Werken met AI | Leer hoe je je eigen AI-assistent bouwt | [AI Assistent project](./9-chat-project/README.md) | Chris |
| | Projectnaam | Behandelde Concepten | Leerdoelen | Gekoppelde Les | Auteur |
| :-: | :------------------------------------------------------: | :------------------------------------------------------------------------: | -------------------------------------------------------------------------------------------------------------------------------- | :-----------------------------------------------------------------------------------------------------------------------------: | :---------------------: |
| 01 | Aan de slag | Introductie in programmeren en tools van het vak | Leer de basisprincipes achter de meeste programmeertalen en over software die professionele ontwikkelaars helpt bij hun werk | [Introductie tot programmeertalen en tools van het vak](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Aan de slag | Basisprincipes van GitHub, inclusief samenwerken in team | Hoe je GitHub gebruikt in je project, hoe je samenwerkt met anderen aan een codebase | [Introductie tot GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Aan de slag | Toegankelijkheid | Leer de basisprincipes van webtoegankelijkheid | [Fundamentals toegankelijkheid](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS Basis | JavaScript-datatypen | De basis van JavaScript-datatypen | [Datatypes](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS Basis | Functies en methoden | Leer over functies en methoden om de logica van een applicatie te beheren | [Functies en methoden](./2-js-basics/2-functions-methods/README.md) | Jasmine en Christopher |
| 06 | JS Basis | Beslissingen maken met JS | Leer hoe je condities maakt in je code met beslissingsmethoden | [Beslissingen maken](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS Basis | Arrays en lussen | Werken met data met behulp van arrays en lussen in JavaScript | [Arrays en lussen](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML in de praktijk | Bouw de HTML voor een online terrarium, met focus op het bouwen van een layout | [Introductie tot HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS in de praktijk | Bouw de CSS om het online terrarium op te maken met focus op basisbeginselen van CSS, inclusief responsive maken van de pagina | [Introductie tot CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | JavaScript-closures, DOM-manipulatie | Bouw de JavaScript om het terrarium te laten functioneren als een sleep/plaats-interface, met focus op closures en DOM-manipulatie | [JavaScript-closures, DOM-manipulatie](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typeren Spel](./4-typing-game/solution/README.md) | Bouw een Typeren Spel | Leer hoe je toetsenbordgebeurtenissen gebruikt om de logica van je JavaScript-app te sturen | [Event-Driven Programming](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Werken met browsers | Leer hoe browsers werken, hun geschiedenis, en hoe je de eerste elementen van een browserextensie bouwt | [Over browsers](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Formulieren maken, API aanroepen en variabelen opslaan in lokale opslag | Bouw de JavaScript-elementen van je browserextensie om een API aan te roepen met variabelen opgeslagen in lokale opslag | [API's, formulieren en lokale opslag](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Achtergrondprocessen in de browser, webprestaties | Gebruik de achtergrondprocessen van de browser om het pictogram van de extensie te beheren; leer over webprestaties en optimalisaties | [Achtergrondtaken en prestaties](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | Gevorderde Spelontwikkeling met JavaScript | Leer over overerving met zowel Classes als Composition en het Pub/Sub-patroon, ter voorbereiding op het bouwen van een spel | [Introductie tot gevorderde spelontwikkeling](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Tekenen op canvas | Leer over de Canvas API, gebruikt om elementen op een scherm te tekenen | [Tekenen op canvas](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Elementen op het scherm verplaatsen | Ontdek hoe elementen beweging krijgen met behulp van cartesische coördinaten en de Canvas API | [Elementen verplaatsen](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Botsingsdetectie | Zorg dat elementen botsen en op elkaar reageren met behulp van toetsaanslagen en een cooldown-functie om de prestaties te garanderen | [Botsingsdetectie](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Score bijhouden | Voer wiskundige berekeningen uit op basis van de status en prestaties van het spel | [Score bijhouden](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Het spel beëindigen en herstarten | Leer over het beëindigen en herstarten van het spel, inclusief het opruimen van resources en het resetten van variabelen | [De eindvoorwaarde](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Bankapp](./7-bank-project/solution/README.md) | HTML-sjablonen en routes in een webapp | Leer hoe je het framework van een multipage website opbouwt met routing en HTML-sjablonen | [HTML-sjablonen en routes](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Bankapp](./7-bank-project/solution/README.md) | Bouw een inlog- en registratieformulier | Leer over het bouwen van formulieren en het afhandelen van validatieroutines | [Formulieren](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Bankapp](./7-bank-project/solution/README.md) | Methoden voor ophalen en gebruiken van data | Hoe data in en uit je app stroomt, hoe je het ophaalt, opslaat en verwijdert | [Data](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Bankapp](./7-bank-project/solution/README.md) | Concepten van state management | Leer hoe je app staat bijhoudt en hoe je deze programmatisch beheert | [State management](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Browser/VScode Code](../../8-code-editor) | Werken met VScode | Leer hoe je een code-editor gebruikt| [Gebruik VScode Code-editor](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Assistants](./9-chat-project/README.md) | Werken met AI | Leer hoe je je eigen AI-assistent bouwt | [AI Assistent project](./9-chat-project/README.md) | Chris |
## 🏫 Pedagogiek
Ons curriculum is ontworpen met twee belangrijke pedagogische principes in gedachten:
* projectgebaseerd leren
* projectgericht leren
* frequente quizzen
Het programma leert de basisprincipes van JavaScript, HTML en CSS, evenals de nieuwste tools en technieken die door hedendaagse webontwikkelaars worden gebruikt. Studenten krijgen de kans om praktische ervaring op te doen door een typingspel, virtueel terrarium, milieuvriendelijke browserextensie, ruimte-invader-stijl spel en een bankapp voor bedrijven te bouwen. Aan het einde van de serie hebben studenten een solide begrip van webontwikkeling opgedaan.
Het programma leert de basisprincipes van JavaScript, HTML en CSS, evenals de nieuwste tools en technieken die door hedendaagse webontwikkelaars worden gebruikt. Studenten krijgen de kans praktische ervaring op te doen door het bouwen van een typeringsspel, virtueel terrarium, milieuvriendelijke browserextensie, space-invader-stijl spel, en een bankapp voor bedrijven. Aan het einde van de serie hebben studenten een solide begrip van webontwikkeling opgedaan.
> 🎓 Je kunt de eerste paar lessen in dit curriculum volgen als een [Leerpad](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) op Microsoft Learn!
> 🎓 Je kunt de eerste paar lessen van dit curriculum volgen als een [Leerpad](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) op Microsoft Learn!
Door ervoor te zorgen dat de inhoud aansluit bij projecten, wordt het proces boeiender voor studenten en wordt het begrip van concepten versterkt. We hebben ook enkele startlessen in JavaScript-basisprincipes geschreven om concepten te introduceren, gekoppeld aan een video uit de "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)" collectie van videotutorials, waarvan sommige auteurs hebben bijgedragen aan dit curriculum.
Door ervoor te zorgen dat de inhoud aansluit bij projecten, wordt het proces boeiender voor studenten en wordt het vasthouden van concepten vergroot. We hebben ook meerdere starterlessen in JavaScript basics geschreven om concepten te introduceren, gekoppeld aan een video uit de "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)" collectie videotutorials, waarvan enkele auteurs een bijdrage hebben geleverd aan dit curriculum.
Daarnaast zorgt een laagdrempelige quiz voorafgaand aan een les ervoor dat de student zich richt op het leren van een onderwerp, terwijl een tweede quiz na de les verdere retentie garandeert. Dit curriculum is ontworpen om flexibel en leuk te zijn en kan in zijn geheel of gedeeltelijk worden gevolgd. De projecten beginnen klein en worden tegen het einde van de 12-weekse cyclus steeds complexer.
Daarnaast stelt een quiz met lage inzet voor de les de intentie van de student om een onderwerp te leren, terwijl een tweede quiz na de les verdere retentie verzekert. Dit curriculum is ontworpen om flexibel en leuk te zijn en kan in zijn geheel of gedeeltelijk worden gevolgd. De projecten beginnen klein en worden steeds complexer tegen het einde van de 12-weekse cyclus.
Hoewel we bewust hebben vermeden JavaScript-frameworks te introduceren om ons te concentreren op de basisvaardigheden die nodig zijn als webontwikkelaar voordat een framework wordt aangenomen, zou een goede volgende stap na het voltooien van dit curriculum zijn om meer te leren over Node.js via een andere collectie video's: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
Hoewel we er bewust voor hebben gekozen geen JavaScript-frameworks te introduceren om ons te concentreren op de basisvaardigheden die nodig zijn als webontwikkelaar voordat een framework wordt aangenomen, is een goede volgende stap na dit curriculum het leren over Node.js via een andere verzameling video's: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
> Bezoek onze [Gedragscode](CODE_OF_CONDUCT.md) en [Bijdragen](CONTRIBUTING.md) richtlijnen. We verwelkomen je constructieve feedback!
## 🧭 Offline toegang
Je kunt deze documentatie offline uitvoeren met behulp van [Docsify](https://docsify.js.org/#/). Fork deze repo, [installeer Docsify](https://docsify.js.org/#/quickstart) op je lokale machine, en typ vervolgens in de rootmap van deze repo `docsify serve`. De website wordt geserveerd op poort 3000 op je localhost: `localhost:3000`.
Je kunt deze documentatie offline gebruiken met [Docsify](https://docsify.js.org/#/). Fork deze repo, installeer [Docsify](https://docsify.js.org/#/quickstart) op je lokale machine en typ dan in de hoofdmap van deze repo `docsify serve`. De website wordt geserveerd op poort 3000 op je localhost: `localhost:3000`.
## 📘 PDF
Een PDF van alle lessen is te vinden [hier](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
Een PDF met alle lessen is te vinden [hier](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
## 🎒 Andere Cursussen
Ons team produceert andere cursussen! Bekijk:
Ons team maakt ook andere cursussen! Bekijk:
<!-- CO-OP TRANSLATOR OTHER COURSES START -->
### Azure / Edge / MCP / Agents
[![AZD voor Beginners](https://img.shields.io/badge/AZD%20voor%20Beginners-0078D4?style=for-the-badge&labelColor=E5E7EB&color=0078D4)](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Edge AI voor Beginners](https://img.shields.io/badge/Edge%20AI%20voor%20Beginners-00B8E4?style=for-the-badge&labelColor=E5E7EB&color=00B8E4)](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![MCP voor Beginners](https://img.shields.io/badge/MCP%20voor%20Beginners-009688?style=for-the-badge&labelColor=E5E7EB&color=009688)](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[![AI Agents voor Beginners](https://img.shields.io/badge/AI%20Agents%20voor%20Beginners-00C49A?style=for-the-badge&labelColor=E5E7EB&color=00C49A)](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
### LangChain
[![LangChain4j for Beginners](https://img.shields.io/badge/LangChain4j%20for%20Beginners-22C55E?style=for-the-badge&&labelColor=E5E7EB&color=0553D6)](https://aka.ms/langchain4j-for-beginners)
[![LangChain.js for Beginners](https://img.shields.io/badge/LangChain.js%20for%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=0553D6)](https://aka.ms/langchainjs-for-beginners?WT.mc_id=m365-94501-dwahlin)
---
### Generatieve AI Serie
[![Generatieve AI voor Beginners](https://img.shields.io/badge/Generative%20AI%20voor%20Beginners-8B5CF6?style=for-the-badge&labelColor=E5E7EB&color=8B5CF6)](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Generatieve AI (.NET)](https://img.shields.io/badge/Generative%20AI%20(.NET)-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[![Generatieve AI (Java)](https://img.shields.io/badge/Generative%20AI%20(Java)-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[![Generatieve AI (JavaScript)](https://img.shields.io/badge/Generative%20AI%20(JavaScript)-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
### Azure / Edge / MCP / Agents
[![AZD for Beginners](https://img.shields.io/badge/AZD%20for%20Beginners-0078D4?style=for-the-badge&labelColor=E5E7EB&color=0078D4)](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Edge AI for Beginners](https://img.shields.io/badge/Edge%20AI%20for%20Beginners-00B8E4?style=for-the-badge&labelColor=E5E7EB&color=00B8E4)](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![MCP for Beginners](https://img.shields.io/badge/MCP%20for%20Beginners-009688?style=for-the-badge&labelColor=E5E7EB&color=009688)](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[![AI Agents for Beginners](https://img.shields.io/badge/AI%20Agents%20for%20Beginners-00C49A?style=for-the-badge&labelColor=E5E7EB&color=00C49A)](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
---
### Kern Leren
[![ML voor Beginners](https://img.shields.io/badge/ML%20voor%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=22C55E)](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[![Data Science voor Beginners](https://img.shields.io/badge/Data%20Science%20voor%20Beginners-84CC16?style=for-the-badge&labelColor=E5E7EB&color=84CC16)](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[![AI voor Beginners](https://img.shields.io/badge/AI%20voor%20Beginners-A3E635?style=for-the-badge&labelColor=E5E7EB&color=A3E635)](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[![Cybersecurity voor Beginners](https://img.shields.io/badge/Cybersecurity%20voor%20Beginners-F97316?style=for-the-badge&labelColor=E5E7EB&color=F97316)](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[![Webontwikkeling voor Beginners](https://img.shields.io/badge/Web%20Dev%20voor%20Beginners-EC4899?style=for-the-badge&labelColor=E5E7EB&color=EC4899)](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[![IoT voor Beginners](https://img.shields.io/badge/IoT%20voor%20Beginners-14B8A6?style=for-the-badge&labelColor=E5E7EB&color=14B8A6)](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[![XR Ontwikkeling voor Beginners](https://img.shields.io/badge/XR%20Development%20voor%20Beginners-38BDF8?style=for-the-badge&labelColor=E5E7EB&color=38BDF8)](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
### Generatieve AI-serie
[![Generative AI for Beginners](https://img.shields.io/badge/Generative%20AI%20for%20Beginners-8B5CF6?style=for-the-badge&labelColor=E5E7EB&color=8B5CF6)](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[![Generative AI (.NET)](https://img.shields.io/badge/Generative%20AI%20(.NET)-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[![Generative AI (Java)](https://img.shields.io/badge/Generative%20AI%20(Java)-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[![Generative AI (JavaScript)](https://img.shields.io/badge/Generative%20AI%20(JavaScript)-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
---
### Kernleren
[![ML for Beginners](https://img.shields.io/badge/ML%20for%20Beginners-22C55E?style=for-the-badge&labelColor=E5E7EB&color=22C55E)](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[![Data Science for Beginners](https://img.shields.io/badge/Data%20Science%20for%20Beginners-84CC16?style=for-the-badge&labelColor=E5E7EB&color=84CC16)](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[![AI for Beginners](https://img.shields.io/badge/AI%20for%20Beginners-A3E635?style=for-the-badge&labelColor=E5E7EB&color=A3E635)](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[![Cybersecurity for Beginners](https://img.shields.io/badge/Cybersecurity%20for%20Beginners-F97316?style=for-the-badge&labelColor=E5E7EB&color=F97316)](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[![Web Dev for Beginners](https://img.shields.io/badge/Web%20Dev%20for%20Beginners-EC4899?style=for-the-badge&labelColor=E5E7EB&color=EC4899)](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[![IoT for Beginners](https://img.shields.io/badge/IoT%20for%20Beginners-14B8A6?style=for-the-badge&labelColor=E5E7EB&color=14B8A6)](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[![XR Development for Beginners](https://img.shields.io/badge/XR%20Development%20for%20Beginners-38BDF8?style=for-the-badge&labelColor=E5E7EB&color=38BDF8)](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
### Copilot Serie
[![Copilot voor AI Samen Programmeren](https://img.shields.io/badge/Copilot%20voor%20AI%20Samen%20Programmeren-FACC15?style=for-the-badge&labelColor=E5E7EB&color=FACC15)](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[![Copilot voor C#/.NET](https://img.shields.io/badge/Copilot%20voor%20C%23/.NET-FBBF24?style=for-the-badge&labelColor=E5E7EB&color=FBBF24)](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
[![Copilot Avontuur](https://img.shields.io/badge/Copilot%20Avontuur-FDE68A?style=for-the-badge&labelColor=E5E7EB&color=FDE68A)](https://github.com/microsoft/CopilotAdventures?WT.mc_id=academic-105485-koreyst)
---
### Copilot-serie
[![Copilot for AI Paired Programming](https://img.shields.io/badge/Copilot%20for%20AI%20Paired%20Programming-FACC15?style=for-the-badge&labelColor=E5E7EB&color=FACC15)](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[![Copilot for C#/.NET](https://img.shields.io/badge/Copilot%20for%20C%23/.NET-FBBF24?style=for-the-badge&labelColor=E5E7EB&color=FBBF24)](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
[![Copilot Adventure](https://img.shields.io/badge/Copilot%20Adventure-FDE68A?style=for-the-badge&labelColor=E5E7EB&color=FDE68A)](https://github.com/microsoft/CopilotAdventures?WT.mc_id=academic-105485-koreyst)
<!-- CO-OP TRANSLATOR OTHER COURSES END -->
## Hulp krijgen
## Hulp krijgen
Als je vastloopt of vragen hebt over het bouwen van AI-apps, sluit je dan aan bij medeleerlingen en ervaren ontwikkelaars in discussies over MCP. Het is een ondersteunende community waar vragen welkom zijn en kennis vrij wordt gedeeld.
Als je vastloopt of vragen hebt over het bouwen van AI-apps. Doe mee met mede-leerlingen en ervaren ontwikkelaars in discussies over MCP. Het is een ondersteunende community waar vragen welkom zijn en kennis vrij wordt gedeeld.
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
[![Microsoft Foundry Discord](https://dcbadge.limes.pink/api/server/nTYy5BXMWG)](https://discord.gg/nTYy5BXMWG)
Als je productfeedback hebt of fouten tegenkomt tijdens het bouwen, bezoek dan:
Als je productfeedback hebt of fouten tegenkomt tijdens het bouwen bezoek:
[![Microsoft Foundry Developer Forum](https://img.shields.io/badge/GitHub-Microsoft_Foundry_Developer_Forum-blue?style=for-the-badge&logo=github&color=000000&logoColor=fff)](https://aka.ms/foundry/forum)
[![Microsoft Foundry Developer Forum](https://img.shields.io/badge/GitHub-Microsoft_Foundry_Developer_Forum-blue?style=for-the-badge&logo=github&color=000000&logoColor=fff)](https://aka.ms/foundry/forum)
## Licentie
## Licentie
Deze repository is gelicentieerd onder de MIT-licentie. Zie het [LICENSE](../../LICENSE) bestand voor meer informatie.
Deze repository is gelicenseerd onder de MIT-licentie. Zie het [LICENSE](../../LICENSE) bestand voor meer informatie.
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Disclaimer**:
Dit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor kritieke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.
**Disclaimer**:
Dit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel wij streven naar nauwkeurigheid, dient u er rekening mee te houden dat automatische vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet als de gezaghebbende bron worden beschouwd. Voor cruciale informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor eventuele misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -42,10 +42,10 @@ Dit lesprogramma bevat importeerbare pakketten voor gangbare LMS-workflows.
- Moodle Cloud heeft beperkte ondersteuning voor Common Cartridge. Geef de voorkeur aan het bovenstaande Moodle-bestand, dat ook in Canvas kan worden geüpload.
- Controleer na import de modules, deadlines en quizinstellingen om aan te sluiten bij uw semesterschema.
![Moodle](../../translated_images/moodle.94eb93d714a50cb2c97435b408017dee224348b61bc86203ffd43a4f4e57b95f.nl.png)
![Moodle](../../translated_images/moodle.94eb93d714a50cb2.nl.png)
> Het lesprogramma in een Moodle-klas
![Canvas](../../translated_images/canvas.fbd605ff8e5b8aff567d398528ce113db304446b90b9cad55c654de3fdfcda34.nl.png)
![Canvas](../../translated_images/canvas.fbd605ff8e5b8aff.nl.png)
> Het lesprogramma in Canvas
### Gebruik de repository direct (zonder Classroom)

File diff suppressed because it is too large Load Diff

@ -1,25 +1,41 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "d0092f6533ae3ec3adad5b5ece68efaf",
"translation_date": "2025-10-23T22:15:52+00:00",
"original_hash": "672b0bb6e8b431075f3bdb7130590d2d",
"translation_date": "2026-01-07T00:19:14+00:00",
"source_file": "2-js-basics/1-data-types/README.md",
"language_code": "no"
}
-->
# Grunnleggende JavaScript: Datatyper
# JavaScript grunnleggende: Datatyper
![Grunnleggende JavaScript - Datatyper](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.no.png)
![JavaScript Basics - Data types](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
Datatyper er et av de grunnleggende konseptene i JavaScript som du vil møte i hvert program du skriver. Tenk på datatyper som arkivsystemet som gamle bibliotekarer i Alexandria brukte de hadde spesifikke steder for skriftruller som inneholdt poesi, matematikk og historiske opptegnelser. JavaScript organiserer informasjon på en lignende måte med ulike kategorier for forskjellige typer data.
```mermaid
journey
title Ditt JavaScript Datatyper Eventyr
section Grunnlag
Variabler & Konstanter: 5: You
Deklarasjonssyntaks: 4: You
Tildelelsekonsepter: 5: You
section Kjernetypene
Tall & Matematikk: 4: You
Strenger & Tekst: 5: You
Booleans & Logikk: 4: You
section Anvend Kunnskap
Typekonvertering: 4: You
Virkelige Eksempler: 5: You
Beste Praksis: 5: You
```
Datatyper er et av de grunnleggende konseptene i JavaScript som du vil møte i hvert program du skriver. Tenk på datatyper som arkivsystemet brukt av de gamle bibliotekarene i Alexandria de hadde spesifikke plasser for ruller som inneholdt poesi, matematikk og historiske opptegnelser. JavaScript organiserer informasjon på lignende måte med forskjellige kategorier for ulike typer data.
I denne leksjonen skal vi utforske de viktigste datatypene som gjør at JavaScript fungerer. Du vil lære hvordan du håndterer tall, tekst, sanne/falske verdier, og forstå hvorfor det er viktig å velge riktig type for programmene dine. Disse konseptene kan virke abstrakte i starten, men med øvelse vil de bli en naturlig del av programmeringen.
I denne leksjonen skal vi utforske de kjerne datatypene som gjør at JavaScript fungerer. Du vil lære hvordan du håndterer tall, tekst, true/false verdier, og forstå hvorfor det er viktig å velge riktig datatype for programmene dine. Disse konseptene kan virke abstrakte i starten, men med praksis blir de naturlige.
Å forstå datatyper vil gjøre alt annet i JavaScript mye klarere. Akkurat som arkitekter må forstå ulike byggematerialer før de konstruerer en katedral, vil disse grunnleggende prinsippene støtte alt du bygger fremover.
Å forstå datatyper vil gjøre alt annet i JavaScript mye klarere. Akkurat som arkitekter må forstå forskjellige byggematerialer før de konstruerer en katedral, vil disse grunnprinsippene støtte alt du bygger fremover.
## Quiz før leksjonen
[Quiz før leksjonen](https://ff-quizzes.netlify.app/web/)
## Forhåndsquiz
[Forhåndsquiz](https://ff-quizzes.netlify.app/web/)
Denne leksjonen dekker det grunnleggende i JavaScript, språket som gir interaktivitet på nettet.
@ -29,80 +45,138 @@ Denne leksjonen dekker det grunnleggende i JavaScript, språket som gir interakt
[![Datatyper i JavaScript](https://img.youtube.com/vi/AWfA95eLdq8/0.jpg)](https://youtube.com/watch?v=AWfA95eLdq8 "Datatyper i JavaScript")
> 🎥 Klikk på bildene ovenfor for videoer om variabler og datatyper
La oss begynne med variabler og datatypene som fyller dem!
> 🎥 Klikk på bildene over for videoer om variabler og datatyper
La oss starte med variabler og datatypene som fyller dem!
```mermaid
mindmap
root((JavaScript Data))
Variabler
let myVar
const PI = 3.14
var gammeldags
Primitive typer
tall
42
3.14
-5
streng
"Hallo"
'Verden'
`Mal`
boolsk
sant
usant
udefinert
null
Operasjoner
Aritmetikk
+ - * / %
Strengmetoder
sammenkobling
maltekster
Typekonvertering
implisitt
eksplisitt
```
## Variabler
Variabler er grunnleggende byggesteiner i programmering. Akkurat som merkede krukker som middelalderens alkymister brukte til å lagre ulike stoffer, lar variabler deg lagre informasjon og gi den et beskrivende navn slik at du kan referere til det senere. Trenger du å huske noens alder? Lagre det i en variabel kalt `age`. Vil du holde styr på en brukers navn? Lagre det i en variabel kalt `userName`.
Variabler er grunnleggende byggeklosser i programmering. Som de merkede krukkene som middelalderens alkymister brukte til å lagre forskjellige stoffer, lar variabler deg lagre informasjon og gi den et beskrivende navn slik at du kan referere til det senere. Trenger du å huske noen sin alder? Lagre det i en variabel kalt `age`. Vil du spore en brukers navn? Ha det i en variabel kalt `userName`.
Vi skal fokusere på den moderne tilnærmingen til å opprette variabler i JavaScript. Teknikken du lærer her representerer år med språkutvikling og beste praksis utviklet av programmeringssamfunnet.
Vi vil fokusere på den moderne tilnærmingen til å lage variabler i JavaScript. Teknikker du lærer her representerer års utvikling av språket og beste praksis utviklet av programmeringsmiljøet.
Å opprette og **deklarere** en variabel har følgende syntaks **[nøkkelord] [navn]**. Det består av to deler:
Å opprette og **deklarere** en variabel har følgende syntaks **[keyword] [name]**. Den består av to deler:
- **Nøkkelord**. Bruk `let` for variabler som kan endres, eller `const` for verdier som forblir de samme.
- **Variabelnavnet**, dette er et beskrivende navn du velger selv.
✅ Nøkkelordet `let` ble introdusert i ES6 og gir variabelen din en såkalt _blokk-scope_. Det anbefales at du bruker `let` eller `const` i stedet for det eldre nøkkelordet `var`. Vi vil dekke blokk-scope mer i dybden i fremtidige deler.
✅ Nøkkelordet `let` ble introdusert i ES6 og gir variabelen din det som kalles _blokksområde_. Det anbefales at du bruker `let` eller `const` i stedet for det eldre nøkkelordet `var`. Vi vil gå mer i dybden på blokksområder i fremtidige deler.
### Oppgave - arbeid med variabler
### Oppgave - jobbe med variabler
1. **Deklarer en variabel**. La oss starte med å opprette vår første variabel:
1. **Deklarer en variabel**. La oss starte med å lage vår første variabel:
```javascript
let myVariable;
```
**Hva dette oppnår:**
**Hva dette gjør:**
- Dette forteller JavaScript å opprette et lagringssted kalt `myVariable`
- JavaScript tildeler plass i minnet for denne variabelen
- JavaScript allokerer plass i minnet for denne variabelen
- Variabelen har foreløpig ingen verdi (undefined)
2. **Gi den en verdi**. La oss nå legge noe inn i variabelen vår:
2. **Gi den en verdi**. Nå setter vi noe i variabelen vår:
```javascript
myVariable = 123;
```
**Hvordan tildeling fungerer:**
- Operatoren `=` tildeler verdien 123 til variabelen vår
- Operatoren `=` tildeler verdien 123 til vår variabel
- Variabelen inneholder nå denne verdien i stedet for å være undefined
- Du kan referere til denne verdien gjennom hele koden din ved å bruke `myVariable`
- Du kan referere til denne verdien gjennom koden din med `myVariable`
> Merk: bruken av `=` i denne leksjonen betyr at vi bruker en "tildelingsoperator", brukt for å sette en verdi til en variabel. Det betyr ikke likhet.
> Merk: Bruken av `=` i denne leksjonen betyr at vi bruker en "tildelingsoperator", brukt til å sette en verdi til en variabel. Det betyr ikke likhet.
3. **Gjør det på den smarte måten**. Faktisk, la oss kombinere de to trinnene:
3. **Gjør det på den smarte måten**. Faktisk, la oss kombinere disse to stegene:
```javascript
let myVariable = 123;
```
**Denne tilnærmingen er mer effektiv:**
- Du deklarerer variabelen og tildeler en verdi i én setning
- Du deklarerer variabelen og tildeler verdi i en og samme setning
- Dette er standard praksis blant utviklere
- Det reduserer kodelengden samtidig som det opprettholder klarhet
- Det reduserer kodelengde samtidig som det opprettholder klarhet
4. **Endre mening**. Hva om vi vil lagre et annet tall?
4. **Ombestem deg**. Hva om vi vil lagre et annet tall?
```javascript
myVariable = 321;
```
**Forstå omfordeling:**
**Forstå omtildeling:**
- Variabelen inneholder nå 321 i stedet for 123
- Den forrige verdien er erstattet variabler lagrer bare én verdi om gangen
- Denne mutabiliteten er en nøkkelfunksjon for variabler deklarert med `let`
- Den tidligere verdien erstattes variabler lagrer bare én verdi om gangen
- Denne mutabiliteten er kjennetegnet til variabler deklarert med `let`
✅ Prøv det! Du kan skrive JavaScript rett i nettleseren din. Åpne Developer Tools i nettleseren. I konsollen vil du finne en prompt; skriv `let myVariable = 123`, trykk enter, så skriv `myVariable`. Hva skjer? Du vil lære mer om disse konseptene i kommende leksjoner.
### 🧠 **Variabler mestringssjekk: Bli komfortabel**
✅ Prøv det! Du kan skrive JavaScript direkte i nettleseren din. Åpne et nettleservindu og naviger til utviklerverktøy. I konsollen finner du en prompt; skriv `let myVariable = 123`, trykk enter, og skriv deretter `myVariable`. Hva skjer? Merk, du vil lære mer om disse konseptene i senere leksjoner.
**La oss se hvordan du føler deg om variabler:**
- Kan du forklare forskjellen mellom å deklarere og tildele en variabel?
- Hva skjer hvis du prøver å bruke en variabel før du deklarerer den?
- Når ville du velge `let` over `const` for en variabel?
```mermaid
stateDiagram-v2
[*] --> Declared: let myVar
Declared --> Assigned: myVar = 123
Assigned --> Reassigned: myVar = 456
Assigned --> [*]: Variabel klar!
Reassigned --> [*]: Oppdatert verdi
note right of Declared
Variabel eksisterer men
har ingen verdi (undefined)
end note
note right of Assigned
Variabel inneholder
verdien 123
end note
```
> **Raskt tips**: Tenk på variabler som merkede oppbevaringsbokser. Du lager boksen (`let`), legger noe i den (`=`), og kan senere erstatte innholdet om nødvendig!
## Konstanter
Noen ganger trenger du å lagre informasjon som aldri skal endres under programutførelsen. Tenk på konstanter som de matematiske prinsippene som Euklid etablerte i det gamle Hellas når de først er bevist og dokumentert, forblir de faste for all fremtidig referanse.
Noen ganger trenger du å lagre informasjon som aldri skal endres under programkjøringen. Tenk på konstanter som de matematiske prinsippene Euclid etablerte i det gamle Hellas når de var bevist og dokumentert, forble de faste for all fremtid.
Konstanter fungerer på samme måte som variabler, men med en viktig begrensning: når du har tildelt verdien deres, kan den ikke endres. Denne uforanderligheten hjelper til med å forhindre utilsiktede endringer av kritiske verdier i programmet ditt.
Konstanter fungerer likt som variabler, men med en viktig begrensning: når du har gitt dem en verdi, kan den ikke endres. Denne uforanderligheten bidrar til å forhindre utilsiktede endringer av kritiske verdier i programmet ditt.
Deklarasjon og initialisering av en konstant følger de samme prinsippene som en variabel, med unntak av nøkkelordet `const`. Konstanter blir vanligvis deklarert med store bokstaver.
Deklarasjon og initialisering av en konstant følger de samme prinsippene som en variabel, med unntak av nøkkelordet `const`. Konstanter deklareres vanligvis med store bokstaver.
```javascript
const MY_VARIABLE = 123;
@ -110,13 +184,13 @@ const MY_VARIABLE = 123;
**Dette gjør koden:**
- **Oppretter** en konstant kalt `MY_VARIABLE` med verdien 123
- **Bruker** store bokstaver som navnekonvensjon for konstanter
- **Forhindrer** fremtidige endringer av denne verdien
- **Bruker** navnekonvensjon med store bokstaver for konstanter
- **Forhindrer** fremtidige endringer i denne verdien
Konstanter har to hovedregler:
- **Du må gi dem en verdi med en gang** ingen tomme konstanter er tillatt!
- **Du kan aldri endre den verdien** JavaScript vil gi en feil hvis du prøver. La oss se hva jeg mener:
- **Du må gi dem en verdi med én gang** ingen tomme konstanter tillatt!
- **Du kan aldri endre den verdien** JavaScript vil kaste en feil hvis du prøver. La oss se hva jeg mener:
**Enkel verdi** - Følgende er IKKE tillatt:
@ -126,10 +200,10 @@ Konstanter har to hovedregler:
```
**Hva du må huske:**
- **Forsøk** på å tilordne en ny verdi til en konstant vil føre til en feil
- **Beskytter** viktige verdier mot utilsiktede endringer
- **Sikrer** at verdien forblir konsistent gjennom hele programmet
- **Forsøk** på å tilordne konstanten på nytt vil forårsake en feil
- **Beskytter** viktige verdier fra utilsiktede endringer
- **Sikrer** at verdien forblir konsekvent gjennom programmet
**Objektreferanse er beskyttet** - Følgende er IKKE tillatt:
```javascript
@ -149,65 +223,103 @@ Konstanter har to hovedregler:
obj.a = 5; // tillatt
```
**Hva som skjer her:**
**Forklaring på hva som skjer her:**
- **Endrer** egenskapsverdien inne i objektet
- **Beholder** den samme objektreferansen
- **Viser** at objektinnhold kan endres mens referansen forblir konstant
- **Beholder** samme objektreferanse
- **Demonstrerer** at objektinnhold kan endres mens referansen forblir konstant
> Merk, en `const` betyr at referansen er beskyttet mot omfordeling. Verdien er derimot ikke _uforanderlig_ og kan endres, spesielt hvis det er en kompleks konstruksjon som et objekt.
> Merk at `const` betyr at referansen er beskyttet mot ny tildeling. Verdien er ikke _uforanderlig_ og kan endres, spesielt hvis det er en kompleks konstruksjon som et objekt.
## Datatyper
JavaScript organiserer informasjon i ulike kategorier kalt datatyper. Dette konseptet speiler hvordan gamle lærde kategoriserte kunnskap Aristoteles skilte mellom ulike typer resonnement, og visste at logiske prinsipper ikke kunne brukes likt på poesi, matematikk og naturfilosofi.
JavaScript organiserer informasjon i forskjellige kategorier kalt datatyper. Dette konseptet speiler hvordan gamle lærde kategoriserte kunnskap Aristoteles skilte mellom ulike typer resonnement, vel vitende om at logiske prinsipper ikke kunne anvendes ensartet på poesi, matematikk og naturfilosofi.
Datatyper er viktige fordi ulike operasjoner fungerer med ulike typer informasjon. Akkurat som du ikke kan utføre aritmetikk på en persons navn eller alfabetisere en matematisk ligning, krever JavaScript riktig datatype for hver operasjon. Å forstå dette forhindrer feil og gjør koden din mer pålitelig.
Datatyper er viktige fordi ulike operasjoner fungerer med ulike typer informasjon. Akkurat som du ikke kan utføre aritmetikk på en persons navn eller alfabetisere en matematisk likning, krever JavaScript riktig datatype for hver operasjon. Å forstå dette forhindrer feil og gjør koden din mer pålitelig.
Variabler kan lagre mange forskjellige typer verdier, som tall og tekst. Disse ulike typene verdier er kjent som **datatyper**. Datatyper er en viktig del av programvareutvikling fordi det hjelper utviklere med å ta beslutninger om hvordan koden skal skrives og hvordan programvaren skal fungere. Videre har noen datatyper unike egenskaper som hjelper til med å transformere eller hente ut tilleggsinformasjon fra en verdi.
Variabler kan lagre mange forskjellige typer verdier, som tall og tekst. Disse forskjellige verditypene kalles **datatypen**. Datatyper er en viktig del av programvareutvikling fordi det hjelper utviklere å ta beslutninger om hvordan koden skal skrives og hvordan programvaren skal kjøre. Videre har noen datatyper unike egenskaper som hjelper til å transformere eller trekke ut ekstra informasjon fra en verdi.
✅ Datatyper kalles også JavaScript data-primitiver, da de er de laveste nivå datatypene som tilbys av språket. Det finnes 7 primitive datatyper: string, number, bigint, boolean, undefined, null og symbol. Ta et øyeblikk til å visualisere hva hver av disse primitivene kan representere. Hva er en `zebra`? Hva med `0`? `true`?
✅ Datatyper kalles også JavaScript-dataprimitiver, ettersom de er de laveste nivåene datatyper språket tilbyr. Det finnes 7 primitive datatyper: string, number, bigint, boolean, undefined, null og symbol. Ta et øyeblikk og visualiser hva hver av disse primitivene kan representere. Hva er en `zebra`? Hva med `0`? `true`?
### Tall
Tall er den mest rett frem datatypen i JavaScript. Enten du jobber med hele tall som 42, desimaltall som 3.14, eller negative tall som -5, håndterer JavaScript dem på en enhetlig måte.
Tall er den mest direkte datatypen i JavaScript. Enten du jobber med hele tall som 42, desimaler som 3.14, eller negative tall som -5, håndterer JavaScript dem ensartet.
Husker du variabelen vår fra tidligere? Den 123 vi lagret var faktisk en tall-datatype:
Husker du variabelen vår fra tidligere? Den 123 vi lagret var faktisk av typen tall:
```javascript
let myVariable = 123;
```
**Viktige egenskaper:**
**Viktige kjennetegn:**
- JavaScript gjenkjenner automatisk numeriske verdier
- Du kan utføre matematiske operasjoner med disse variablene
- Ingen eksplisitt typeerklæring er nødvendig
- Ingen eksplisitt typedeklarasjon er påkrevd
Variabler kan lagre alle typer tall, inkludert desimaltall eller negative tall. Tall kan også brukes med aritmetiske operatorer, dekket i [neste seksjon](../../../../2-js-basics/1-data-types).
Variabler kan lagre alle typer tall, inkludert desimaler eller negative tall. Tall kan også brukes med aritmetiske operatorer, som vi tar for oss i [neste seksjon](../../../../2-js-basics/1-data-types).
### Aritmetiske operatorer
```mermaid
flowchart LR
A["🔢 Tall"] --> B[" Addisjon"]
A --> C[" Subtraksjon"]
A --> D["✖️ Multiplikasjon"]
A --> E["➗ Divisjon"]
A --> F["📊 Rest %"]
B --> B1["1 + 2 = 3"]
C --> C1["5 - 3 = 2"]
D --> D1["4 * 3 = 12"]
E --> E1["10 / 2 = 5"]
F --> F1["7 % 3 = 1"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
### Aritmetiske Operatorer
Aritmetiske operatorer lar deg utføre matematiske beregninger i JavaScript. Disse operatorene følger de samme prinsippene som matematikere har brukt i århundrer de samme symbolene som dukket opp i verkene til lærde som Al-Khwarizmi, som utviklet algebraisk notasjon.
Operatorene fungerer som du forventer fra tradisjonell matematikk: pluss for addisjon, minus for subtraksjon, og så videre.
Operatorene fungerer slik du forventer fra tradisjonell matematikk: pluss for addisjon, minus for subtraksjon, og så videre.
Det finnes flere typer operatorer å bruke når du utfører aritmetiske funksjoner, og noen er listet her:
Det finnes flere typer operatorer for aritmetiske funksjoner, noen av dem listet her:
| Symbol | Beskrivelse | Eksempel |
| ------ | ------------------------------------------------------------------------ | --------------------------------- |
| `+` | **Addisjon**: Beregner summen av to tall | `1 + 2 //forventet svar er 3` |
| `-` | **Subtraksjon**: Beregner differansen mellom to tall | `1 - 2 //forventet svar er -1` |
| `*` | **Multiplikasjon**: Beregner produktet av to tall | `1 * 2 //forventet svar er 2` |
| `/` | **Divisjon**: Beregner kvotienten av to tall | `1 / 2 //forventet svar er 0.5` |
| `%` | **Rest**: Beregner resten fra divisjonen av to tall | `1 % 2 //forventet svar er 1` |
| Symbol | Beskrivelse | Eksempel |
| ------ | --------------------------------------------------------------------- | ------------------------------- |
| `+` | **Addisjon**: Kalkulerer summen av to tall | `1 + 2 //forventet svar er 3` |
| `-` | **Subtraksjon**: Kalkulerer differansen mellom to tall | `1 - 2 //forventet svar er -1` |
| `*` | **Multiplikasjon**: Kalkulerer produktet av to tall | `1 * 2 //forventet svar er 2` |
| `/` | **Divisjon**: Kalkulerer kvotienten av to tall | `1 / 2 //forventet svar er 0.5` |
| `%` | **Restverdi**: Kalkulerer resten fra divisjon av to tall | `1 % 2 //forventet svar er 1` |
✅ Prøv det! Prøv en aritmetisk operasjon i nettleserens konsoll. Overrasker resultatene deg?
### 🧮 **Mattekunnskap sjekk: Beregne med selvtillit**
**Test din forståelse av aritmetikk:**
- Hva er forskjellen mellom `/` (divisjon) og `%` (rest)?
- Kan du forutsi hva `10 % 3` er? (Hint: det er ikke 3.33...)
- Hvorfor kan restenoperatoren være nyttig i programmering?
```mermaid
pie title "Bruk av JavaScript-talloperasjoner"
"Addisjon (+)" : 35
"Subtraksjon (-)" : 20
"Multiplikasjon (*)" : 20
"Divisjon (/)" : 15
"Rest (%)" : 10
```
> **Innsikt fra virkeligheten**: Restoperatoren (%) er supernyttig for å sjekke om tall er partall/oddetall, lage mønstre eller sykle gjennom arrays!
### Strenger
I JavaScript representeres tekstdata som strenger. Begrepet "streng" kommer fra konseptet med tegn som er strukket sammen i en sekvens, omtrent som måten skrivere i middelalderklostre koblet bokstaver sammen for å danne ord og setninger i sine manuskripter.
I JavaScript representeres tekstlig data som strenger. Begrepet "streng" kommer fra konseptet med tegn som er satt sammen i sekvens, på samme måte som skrivere i middelalderklostre koblet bokstaver for å danne ord og setninger i sine manuskripter.
Strenger er grunnleggende for webutvikling. Hver tekstbit som vises på et nettsted brukernavn, knappetekster, feilmeldinger, innhold håndteres som strengdata. Å forstå strenger er avgjørende for å lage funksjonelle brukergrensesnitt.
Strenger er grunnleggende for webutvikling. Hver tekstbit som vises på et nettsted brukernavn, knappetiketter, feilmeldinger, innhold håndteres som strengdata. Å forstå strenger er essensielt for å lage funksjonelle brukergrensesnitt.
Strenger er sett med tegn som er plassert mellom enkelt- eller dobbeltanførselstegn.
Strenger er sett med tegn som er plassert mellom enkle eller doble anførselstegn.
```javascript
'This is a string'
@ -216,108 +328,291 @@ let myString = 'This is a string value stored in a variable';
```
**Forstå disse konseptene:**
- **Bruker** enten enkeltanførselstegn `'` eller dobbeltanførselstegn `"` for å definere strenger
- **Bruker** enten enkle `'` eller doble `"` anførselstegn for å definere strenger
- **Lagrer** tekstdata som kan inkludere bokstaver, tall og symboler
- **Tildeler** strengverdier til variabler for senere bruk
- **Krever** anførselstegn for å skille tekst fra variabelnavn
Husk å bruke anførselstegn når du skriver en streng, ellers vil JavaScript anta at det er et variabelnavn.
### Formatering av strenger
Husk å bruke anførselstegn når du skriver en streng, ellers antar JavaScript at det er et variabelnavn.
Strengmanipulering lar deg kombinere tekstelementer, inkludere variabler og lage dynamisk innhold som reagerer på programtilstanden. Denne teknikken gjør det mulig å konstruere tekst programmessig.
```mermaid
flowchart TD
A["📝 Strenger"] --> B["Enkeltsitater"]
A --> C["Dobbelt Sitater"]
A --> D["Maler Literaler"]
B --> B1["'Hello World'"]
C --> C1["\"Hello World\""]
D --> D1["`Hello \${name}`"]
E["Streng Operasjoner"] --> F["Sammenkobling"]
E --> G["Mal Innssetting"]
E --> H["Lengde & Metoder"]
F --> F1["'Hello' + ' ' + 'World'"]
G --> G1["`Hello \${firstName} \${lastName}`"]
H --> H1["myString.length"]
style A fill:#e3f2fd
style E fill:#fff3e0
style D fill:#e8f5e8
style G fill:#e8f5e8
```
### Formatering av Strenger
Ofte trenger du å slå sammen flere strenger denne prosessen kalles sammenkobling.
Strengmanipulasjon lar deg kombinere tekst-elementer, inkorporere variabler og skape dynamisk innhold som reagerer på programtilstand. Denne teknikken gjør det mulig å bygge tekst programmessig.
For å **sammenkoble** to eller flere strenger, eller slå dem sammen, bruk operatoren `+`.
Ofte må du slå sammen flere strenger denne prosessen kalles konkatenasjon.
For å **sammenkoble** to eller flere strenger, eller koble dem sammen, bruk `+` operatoren.
```javascript
let myString1 = "Hello";
let myString2 = "World";
myString1 + myString2 + "!"; //HelloWorld!
myString1 + " " + myString2 + "!"; //Hello World!
myString1 + ", " + myString2 + "!"; //Hello, World!
myString1 + myString2 + "!"; //HalloVerden!
myString1 + " " + myString2 + "!"; //Hei Verden!
myString1 + ", " + myString2 + "!"; //Hei, Verden!
```
**Trinn for trinn, her er hva som skjer:**
- **Kombinerer** flere strenger ved hjelp av operatoren `+`
**Steg for steg, dette skjer:**
- **Kombinerer** flere strenger ved bruk av `+` operatoren
- **Slår sammen** strenger direkte uten mellomrom i det første eksempelet
- **Legger til** mellomrom `" "` mellom strenger for lesbarhet
- **Setter inn** tegnsetting som komma for å lage riktig formatering
- **Legger til** mellomroms-tegn `" "` mellom strengene for lesbarhet
- **Setter inn** skilletegn som komma for å lage riktig formatering
✅ Hvorfor er `1 + 1 = 2` i JavaScript, men `'1' + '1' = 11?` Tenk over det. Hva med `'1' + 1`?
✅ Hvorfor blir `1 + 1 = 2` i JavaScript, men `'1' + '1' = 11`? Tenk over det. Hva med `'1' + 1`?
**Maluttrykk** er en annen måte å formatere strenger på, bortsett fra at det brukes baktegn i stedet for anførselstegn. Alt som ikke er ren tekst må plasseres inne i plassholdere `${ }`. Dette inkluderer eventuelle variabler som kan være strenger.
**Malmelitteraler** er en annen måte å formatere strenger på, bortsett fra at man bruker backtick i stedet for anførselstegn. Alt som ikke er ren tekst må plasseres inn i plassholdere `${ }`. Dette inkluderer variabler som kan være strenger.
```javascript
let myString1 = "Hello";
let myString2 = "World";
`${myString1} ${myString2}!` //Hello World!
`${myString1}, ${myString2}!` //Hello, World!
`${myString1} ${myString2}!` //Hei Verden!
`${myString1}, ${myString2}!` //Hei, Verden!
```
**La oss forstå hver del:**
- **Bruker** baktegn `` ` `` i stedet for vanlige anførselstegn for å lage maluttrykk
- **Inkluderer** variabler direkte ved hjelp av `${}` plassholder-syntaks
- **Bevarer** mellomrom og formatering akkurat som skrevet
- **Gir** en mer elegant måte å lage komplekse strenger med variabler
Du kan oppnå dine formateringsmål med begge metoder, men mal-litteraler vil respektere alle mellomrom og linjeskift.
✅ Når bør du bruke en mal-litteral kontra en vanlig streng?
- **Bruker** backticks `` ` `` i stedet for vanlige anførselstegn for å lage malmelitteraler
- **Innebygger** variabler direkte ved bruk av `${}`-plassholder syntaks
- **Bevarer** mellomrom og formatering nøyaktig som skrevet
- **Gir** en renere måte å lage komplekse strenger med variabler på
Du kan oppnå formateringsmålene dine med begge metodene, men malmelitteraler respekterer eventuelle mellomrom og linjeskift.
✅ Når ville du brukt en malmelitteral i stedet for en vanlig streng?
### 🔤 **Strengmestrings-sjekk: Selvsikkerhet i Tekstmanipulasjon**
**Evaluer dine strengferdigheter:**
- Kan du forklare hvorfor `'1' + '1'` blir `'11'` i stedet for `2`?
- Hvilken strengmetode synes du er mest lesbar: sammenkobling eller malmelitteraler?
- Hva skjer hvis du glemmer anførselstegn rundt en streng?
```mermaid
stateDiagram-v2
[*] --> PlainText: "Hallo"
[*] --> Variable: navn = "Alice"
PlainText --> Concatenated: + " " + navn
Variable --> Concatenated
PlainText --> Template: `Hallo ${navn}`
Variable --> Template
Concatenated --> Result: "Hallo Alice"
Template --> Result
note right of Concatenated
Tradisjonell metode
Mer ordrik
end note
note right of Template
Moderne ES6-syntaks
Renere og mer lesbar
end note
```
> **Proff tips**: Malmelitteraler foretrekkes vanligvis for kompleks strengbygging fordi de er mer lesbare og håndterer flerslinje-strenger på en flott måte!
### Booleske verdier
### Booleans
Booleske verdier representerer den enkleste formen for data: de kan bare ha én av to verdier `true` eller `false`. Dette binære logikksystemet stammer fra arbeidet til George Boole, en matematiker fra 1800-tallet som utviklet boolsk algebra.
Booleans representerer den enkleste formen for data: de kan bare ha en av to verdier `true` eller `false`. Dette binære logikksystemet stammer fra arbeidet til George Boole, en matematiker fra 1800-tallet som utviklet boolsk algebra.
Til tross for sin enkelhet er booleske verdier essensielle for programlogikk. De gjør det mulig for koden din å ta avgjørelser basert på betingelser om en bruker er logget inn, om en knapp ble klikket, eller om visse kriterier er oppfylt.
Til tross for sin enkelhet er booleans essensielle for programlogikk. De gjør det mulig for koden din å ta beslutninger basert på betingelser om en bruker er logget inn, om en knapp ble klikket, eller om visse kriterier er oppfylt.
Booleske verdier kan bare ha to verdier: `true` eller `false`. Booleske verdier kan hjelpe med å avgjøre hvilke linjer med kode som skal kjøres når visse betingelser er oppfylt. I mange tilfeller hjelper [operatorer](../../../../2-js-basics/1-data-types) med å sette verdien til en boolsk variabel, og du vil ofte legge merke til og skrive variabler som blir initialisert eller oppdatert med en operator.
Booleans kan kun ha to verdier: `true` eller `false`. Booleans hjelper med å bestemme hvilke kodeblokker som skal kjøres når visse betingelser er oppfylt. I mange tilfeller hjelper [operatorer](../../../../2-js-basics/1-data-types) med å sette verdien til en Boolean, og du vil ofte se og skrive variabler som initieres eller får oppdatert verdi med en operator.
```javascript
let myTrueBool = true;
let myFalseBool = false;
```
**I eksempelet ovenfor har vi:**
- **Opprettet** en variabel som lagrer den boolske verdien `true`
- **Demonstrert** hvordan man lagrer den boolske verdien `false`
- **Brukt** de eksakte nøkkelordene `true` og `false` (ingen anførselstegn nødvendig)
**I eksempelet over har vi:**
- **Opprettet** en variabel som lagrer Boolean-verdien `true`
- **Vist** hvordan man lagrer Boolean-verdien `false`
- **Brukt** nøkkelordene `true` og `false` nøyaktig (ingen anførselstegn nødvendig)
- **Forberedt** disse variablene for bruk i betingede utsagn
✅ En variabel kan anses som 'truthy' hvis den evalueres til en boolsk `true`. Interessant nok, i JavaScript er [alle verdier truthy med mindre de er definert som falsy](https://developer.mozilla.org/docs/Glossary/Truthy).
✅ En variabel kan anses som 'truthy' hvis den evalueres til en boolean `true`. Interessant nok er [alle verdier sannhetsverdier med mindre definert som falsy](https://developer.mozilla.org/docs/Glossary/Truthy) i JavaScript.
```mermaid
flowchart LR
A["🔘 Boolske verdier"] --> B["true"]
A --> C["false"]
D["Sanne verdier"] --> D1["'hei'"]
D --> D2["42"]
D --> D3["[]"]
D --> D4["{}"]
E["Usanne verdier"] --> E1["false"]
E --> E2["0"]
E --> E3["''"]
E --> E4["null"]
E --> E5["undefined"]
E --> E6["NaN"]
style B fill:#e8f5e8
style C fill:#ffebee
style D fill:#e3f2fd
style E fill:#fff3e0
```
### 🎯 **Boolean Logikk Sjekk: Ferdigheter i Beslutningstaking**
**Test din forståelse av boolean:**
- Hvorfor tror du JavaScript har "truthy" og "falsy" verdier utover bare `true` og `false`?
- Kan du forutsi hvilken av disse som er falsy: `0`, `"0"`, `[]`, `"false"`?
- Hvordan kan booleans være nyttige ved styring av programflyt?
```mermaid
pie title "Vanlige bruksområder for boolske verdier"
"Betingelseslogikk" : 40
"Brukertilstand" : 25
"Funksjonsbrytere" : 20
"Validering" : 15
```
> **Husk**: I JavaScript er det bare 6 verdier som er falsy: `false`, `0`, `""`, `null`, `undefined`, og `NaN`. Alt annet er truthy!
---
## 📊 **Oppsummering av verktøykassen for datatyper**
```mermaid
graph TD
A["🎯 JavaScript Datatyper"] --> B["📦 Variabler"]
A --> C["🔢 Tall"]
A --> D["📝 Strenger"]
A --> E["🔘 Booleanske verdier"]
B --> B1["let muterbar"]
B --> B2["const umuterbar"]
C --> C1["42, 3.14, -5"]
C --> C2["+ - * / %"]
D --> D1["'anførselstegn' eller \\\"anførselstegn\\\""]
D --> D2["`maltekster`"]
E --> E1["true eller false"]
E --> E2["sannhetsverdi vs falskhet"]
F["⚡ Nøkkelkonsepter"] --> F1["Type er viktig for operasjoner"]
F --> F2["JavaScript er dynamisk typet"]
F --> F3["Variabler kan endre type"]
F --> F4["Navngivning skiller mellom store og små bokstaver"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
## GitHub Copilot Agent Challenge 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Lag en personlig informasjonsbehandler som demonstrerer alle JavaScript-datatypene du har lært i denne leksjonen, samtidig som den håndterer realistiske datascenarier.
**Beskrivelse:** Lag en personlig informasjonsbehandler som demonstrerer alle JavaScript-datatypene du har lært i denne leksjonen, samtidig som den håndterer virkelige datasituasjoner.
**Oppgave:** Lag et JavaScript-program som oppretter et brukerprofilobjekt som inneholder: en persons navn (streng), alder (nummer), studentstatus (boolsk), favorittfarger som en array, og et adresseobjekt med egenskaper for gate, by og postnummer. Inkluder funksjoner for å vise profilinformasjon og oppdatere individuelle felt. Sørg for å demonstrere strengsammenkobling, mal-litteraler, aritmetiske operasjoner med alder, og boolsk logikk for studentstatus.
**Oppgave:** Bygg et JavaScript-program som lager et brukerprofil-objekt som inneholder: en persons navn (streng), alder (nummer), status som student (boolean), favorittfarger som en array, og et adresse-objekt med gate, by og postnummer-egenskaper. Inkluder funksjoner for å vise profilinformasjonen og oppdatere individuelle felt. Sørg for å demonstrere strengsammenkobling, malmelitteraler, aritmetiske operasjoner med alder, og boolsk logikk for studentstatus.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Les mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
JavaScript har noen oppførselstrekk som kan overraske utviklere. Her er et klassisk eksempel å utforske: prøv å skrive dette i nettleserkonsollen din: `let age = 1; let Age = 2; age == Age` og observer resultatet. Det returnerer `false` kan du finne ut hvorfor?
JavaScript har noen oppførsler som kan overraske utviklere. Her er et klassisk eksempel å utforske: prøv å skrive dette i nettleserkonsollen din: `let age = 1; let Age = 2; age == Age` og se resultatet. Det returnerer `false` kan du finne ut hvorfor?
Dette representerer en av mange JavaScript-oppførselstrekk som er verdt å forstå. Kjennskap til disse særegenhetene vil hjelpe deg med å skrive mer pålitelig kode og feilsøke problemer mer effektivt.
Dette er en av flere JavaScript-atferder det er verdt å forstå. Kjennskap til disse særegenhetene vil hjelpe deg å skrive mer pålitelig kode og feilsøke problemer mer effektivt.
## Quiz etter leksjonen
[Quiz etter leksjonen](https://ff-quizzes.netlify.app)
## Post-forelesningsquiz
[Post-forelesningsquiz](https://ff-quizzes.netlify.app)
## Gjennomgang & Selvstudium
## Gjennomgang og Selvstudium
Ta en titt på [denne listen over JavaScript-øvelser](https://css-tricks.com/snippets/javascript/) og prøv en. Hva lærte du?
Ta en titt på [denne listen med JavaScript-øvelser](https://css-tricks.com/snippets/javascript/) og prøv en. Hva lærte du?
## Oppgave
[Øv på datatyper](assignment.md)
[Datatyper Øvelse](assignment.md)
## 🚀 Din JavaScript Datatype-Mestrings Tidslinje
### ⚡ **Hva Du Kan Gjøre Innen 5 Minutter**
- [ ] Åpne nettleserkonsollen din og lag 3 variabler med forskjellige datatyper
- [ ] Prøv utfordringen: `let age = 1; let Age = 2; age == Age` og finn ut hvorfor det er false
- [ ] Øv på strengsammenkobling med navnet ditt og favorittnummeret ditt
- [ ] Test hva som skjer når du legger et tall til en streng
### 🎯 **Hva Du Kan Få Til Denne Timen**
- [ ] Fullfør post-leksjonsquiz og gå gjennom eventuelle forvirrende konsepter
- [ ] Lag en mini kalkulator som legger til, trekker fra, multipliserer og dividerer to tall
- [ ] Lag en enkel navneformatterer ved bruk av malmelitteraler
- [ ] Utforsk forskjellene mellom `==` og `===` sammenligningsoperatorer
- [ ] Øv på å konvertere mellom forskjellige datatyper
### 📅 **Din JavaScript-uke**
- [ ] Fullfør oppgaven med selvtillit og kreativitet
- [ ] Lag en personlig profil-objekt med alle lærte datatyper
- [ ] Øv med [JavaScript-øvelser fra CSS-Tricks](https://css-tricks.com/snippets/javascript/)
- [ ] Bygg en enkel skjema-validator med boolsk logikk
- [ ] Eksperimenter med array- og objekt-datatyper (forhåndsvisning av kommende leksjoner)
- [ ] Bli med i et JavaScript-fellesskap og stille spørsmål om datatyper
### 🌟 **Din Månedslange Transformasjon**
- [ ] Integrer kunnskap om datatyper i større programmeringsprosjekter
- [ ] Forstå når og hvorfor man skal bruke hver datatype i virkelige applikasjoner
- [ ] Hjelp andre nybegynnere å forstå JavaScripts grunnprinsipper
- [ ] Bygg en liten applikasjon som håndterer forskjellige typer brukerdata
- [ ] Utforsk avanserte datatypeteknikker som typekoersjon og streng likhet
- [ ] Bidra til open source JavaScript-prosjekter med dokumentasjonsforbedringer
### 🧠 **Siste Datatype Mestrings-Sjekk**
**Feire din JavaScript-grunnmur:**
- Hvilken datatype overrasket deg mest med sin oppførsel?
- Hvor komfortabel føler du deg med å forklare variabler vs. konstanter til en venn?
- Hva er den mest interessante tingen du oppdaget om JavaScripts typesystem?
- Hvilken virkelighetsapplikasjon kan du forestille deg å bygge med disse grunnleggende konseptene?
```mermaid
journey
title Din JavaScript-tillitsreise
section I dag
Forvirret: 3: You
Nysgjerrig: 4: You
Spent: 5: You
section Denne uken
Øver: 4: You
Forstår: 5: You
Bygger: 5: You
section Neste måned
Problemløsing: 5: You
Lærer andre: 5: You
Ekte prosjekter: 5: You
```
> 💡 **Du har bygd fundamentet!** Å forstå datatyper er som å lære alfabetet før du skriver historier. Hvert JavaScript-program du noen gang skriver vil bruke disse grunnleggende konseptene. Du har nå byggeklossene til å lage interaktive nettsider, dynamiske applikasjoner, og løse virkelige problemer med kode. Velkommen til den fantastiske verden av JavaScript! 🎉
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved bruk av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på dets morsmål skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,55 +1,103 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "ec43b53e8e015cdabfd3ad877b3c28e5",
"translation_date": "2025-10-23T22:16:28+00:00",
"original_hash": "71f7d7dafa1c7194d79ddac87f669ff9",
"translation_date": "2026-01-07T00:17:50+00:00",
"source_file": "2-js-basics/2-functions-methods/README.md",
"language_code": "no"
}
-->
# Grunnleggende JavaScript: Metoder og Funksjoner
# JavaScript Grunnleggende: Metoder og Funksjoner
![Grunnleggende JavaScript - Funksjoner](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b7605c36330ac42eeb5cd8ed02bcdd60fdac778174d6cb865.no.png)
![JavaScript Basics - Functions](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
## Quiz før forelesning
[Quiz før forelesning](https://ff-quizzes.netlify.app)
```mermaid
journey
title Ditt JavaScript Funksjoner Eventyr
section Grunnlag
Funksjonssyntaks: 5: You
Kalle Funksjoner: 4: You
Parametere & Argumenter: 5: You
section Avanserte Konsepter
Returverdier: 4: You
Standardparametere: 5: You
Funksjonssammensetning: 4: You
section Moderne JavaScript
Pilesfunksjoner: 5: You
Anonyme Funksjoner: 4: You
Høyere-ordens Funksjoner: 5: You
```
## Pre-forelesningsquiz
[Pre-lecture quiz](https://ff-quizzes.netlify.app)
Å skrive den samme koden gjentatte ganger er en av de mest frustrerende aspektene ved programmering. Funksjoner løser dette problemet ved å la deg pakke kode inn i gjenbrukbare blokker. Tenk på funksjoner som de standardiserte delene som gjorde Henry Fords samlebånd revolusjonerende når du har laget en pålitelig komponent, kan du bruke den hvor som helst uten å bygge den opp fra bunnen av.
Å skrive den samme koden gjentatte ganger er en av programmeringens vanligste frustrasjoner. Funksjoner løser dette problemet ved å la deg pakke kode inn i gjenbrukbare blokker. Tenk på funksjoner som de standardiserte delene som gjorde Henry Fords samlebånd revolusjonerende når du oppretter en pålitelig komponent, kan du bruke den hvor som helst uten å bygge den opp fra bunnen av igjen.
Funksjoner lar deg samle deler av koden slik at du kan gjenbruke dem gjennom hele programmet. I stedet for å kopiere og lime inn den samme logikken overalt, kan du lage en funksjon én gang og kalle den når det trengs. Denne tilnærmingen holder koden din organisert og gjør oppdateringer mye enklere.
Funksjoner lar deg samle kodebiter slik at du kan bruke dem på nytt gjennom hele programmet ditt. I stedet for å kopiere og lime inn samme logikk overalt, kan du lage en funksjon én gang og kalle den når du trenger det. Denne tilnærmingen holder koden din organisert og gjør oppdateringer mye enklere.
I denne leksjonen vil du lære hvordan du lager dine egne funksjoner, sender informasjon til dem, og får nyttige resultater tilbake. Du vil oppdage forskjellen mellom funksjoner og metoder, lære moderne syntaksmetoder, og se hvordan funksjoner kan fungere med andre funksjoner. Vi bygger opp disse konseptene steg for steg.
I denne leksjonen vil du lære hvordan du lager dine egne funksjoner, sender informasjon til dem og får nyttige resultater tilbake. Du vil oppdage forskjellen mellom funksjoner og metoder, lære moderne syntaksmetoder, og se hvordan funksjoner kan jobbe sammen med andre funksjoner. Vi bygger opp disse konseptene steg for steg.
[![Metoder og Funksjoner](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Metoder og Funksjoner")
[![Metoder og Funksjoner](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Methods and Functions")
> 🎥 Klikk på bildet over for en video om metoder og funksjoner.
> Du kan ta denne leksjonen på [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-functions/?WT.mc_id=academic-77807-sagibbon)!
```mermaid
mindmap
root((JavaScript Funksjoner))
Grunnleggende Konsepter
Deklarasjon
Tradisjonell syntaks
Pilfunksjon syntaks
Anrop
Bruke parenteser
Parenteser påkrevd
Parametere
Inndata Verdier
Flere parametere
Standardverdier
Argumenter
Verdier sendt inn
Kan være hvilken som helst type
Returverdier
Utdata
return-setning
Avslutte funksjon
Bruke Resultater
Lagre i variabler
Kjede funksjoner
Avanserte Mønstre
Høyere-Ordens
Funksjoner som parametere
Tilbakekallinger
Anonyme
Ikke nødvendig med navn
Inline definisjon
```
## Funksjoner
En funksjon er en selvstendig kodeblokk som utfører en spesifikk oppgave. Den kapsler inn logikk som du kan utføre når det trengs.
En funksjon er en selvstendig blokk med kode som utfører en spesifikk oppgave. Den kapsler inn logikk som du kan kjøre når som helst.
I stedet for å skrive den samme koden flere ganger gjennom programmet ditt, kan du pakke den inn i en funksjon og kalle den når du trenger det. Denne tilnærmingen holder koden din ryddig og gjør oppdateringer mye enklere. Tenk på vedlikeholdsutfordringen hvis du måtte endre logikk som var spredt over 20 forskjellige steder i kodebasen din.
I stedet for å skrive den samme koden flere ganger gjennom programmet ditt, kan du pakke den inn i en funksjon og kalle funksjonen når du trenger det. Denne tilnærmingen holder koden din ryddig og gjør oppdateringer mye enklere. Tenk på vedlikeholdsutfordringen hvis du måtte endre logikk som var spredt over 20 forskjellige steder i kodebasen din.
Det er viktig å gi funksjonene dine beskrivende navn. En godt navngitt funksjon kommuniserer tydelig formålet sitt når du ser `cancelTimer()`, forstår du umiddelbart hva den gjør, akkurat som en tydelig merket knapp forteller deg nøyaktig hva som vil skje når du klikker på den.
Å gi funksjonene dine beskrivende navn er essensielt. En godt navngitt funksjon formidler klart hva den gjør når du ser `cancelTimer()`, forstår du umiddelbart hva den gjør, akkurat som en tydelig merket knapp forteller deg nøyaktig hva som skjer når du klikker på den.
## Lage og kalle en funksjon
La oss se på hvordan man lager en funksjon. Syntaksen følger et konsistent mønster:
La oss se på hvordan man lager en funksjon. Syntaksen følger et konsekvent mønster:
```javascript
function nameOfFunction() { // function definition
// function definition/body
function nameOfFunction() { // funksjonsdefinisjon
// funksjonsdefinisjon/-kropp
}
```
La oss bryte dette ned:
- Nøkkelordet `function` forteller JavaScript "Hei, jeg lager en funksjon!"
- `nameOfFunction` er der du gir funksjonen din et beskrivende navn
- Parentesene `()` er der du kan legge til parametere (vi kommer til det snart)
- Krøllparentesene `{}` inneholder den faktiske koden som kjører når du kaller funksjonen
- Nøkkelordet `function` sier til JavaScript "Hei, jeg lager en funksjon!"
- `nameOfFunction` er hvor du gir funksjonen et beskrivende navn
- Parentesene `()` er hvor du kan legge til parametere (det kommer vi til snart)
- Krøllparentesene `{}` inneholder selve koden som kjører når du kaller funksjonen
La oss lage en enkel hilsningsfunksjon for å se dette i praksis:
@ -59,34 +107,57 @@ function displayGreeting() {
}
```
Denne funksjonen skriver "Hello, world!" til konsollen. Når du har definert den, kan du bruke den så mange ganger du trenger.
Denne funksjonen skriver ut "Hello, world!" til konsollen. Når du har definert den, kan du bruke den så mange ganger du trenger.
For å utføre (eller "kalle") funksjonen din, skriver du navnet etterfulgt av parenteser. JavaScript lar deg definere funksjonen din før eller etter at du kaller den JavaScript-motoren vil håndtere rekkefølgen på utførelsen.
For å kjøre (eller "kalle") funksjonen skriver du navnet etterfulgt av parenteser. JavaScript lar deg definere funksjonen før eller etter du kaller den JavaScript-motoren tar seg av kjørselsrekkefølgen.
```javascript
// calling our function
// kaller vår funksjon
displayGreeting();
```
Når du kjører denne linjen, utføres all koden inne i `displayGreeting`-funksjonen din, og "Hello, world!" vises i nettleserens konsoll. Du kan kalle denne funksjonen gjentatte ganger.
> **Merk:** Du har brukt **metoder** gjennom disse leksjonene. `console.log()` er en metode i hovedsak en funksjon som tilhører `console`-objektet. Den viktigste forskjellen er at metoder er knyttet til objekter, mens funksjoner står uavhengig. Mange utviklere bruker disse begrepene om hverandre i uformelle samtaler.
Når du kjører denne linjen, utfører den all koden inne i `displayGreeting`-funksjonen, og viser "Hello, world!" i nettleserens konsoll. Du kan kalle denne funksjonen gjentatte ganger.
### 🧠 **Grunnleggende funksjonskontroll: Lage dine første funksjoner**
**La oss se hvordan du forstår grunnleggende funksjoner:**
- Kan du forklare hvorfor vi bruker krøllparenteser `{}` i funksjonsdefinisjoner?
- Hva skjer hvis du skriver `displayGreeting` uten parentesene?
- Hvorfor kan det være lurt å kalle samme funksjon flere ganger?
```mermaid
flowchart TD
A["✏️ Definer Funksjon"] --> B["📦 Pakk Kode"]
B --> C["🏷️ Gi det et Navn"]
C --> D["📞 Kall Når Trengs"]
D --> E["🔄 Gjenbruk Overalt"]
F["💡 Fordeler"] --> F1["Ingen kodegjentakelse"]
F --> F2["Enkelt å vedlikeholde"]
F --> F3["Klar organisering"]
F --> F4["Enklere testing"]
style A fill:#e3f2fd
style E fill:#e8f5e8
style F fill:#fff3e0
```
> **Merk:** Du har brukt **metoder** gjennom disse leksjonene. `console.log()` er en metode i praksis en funksjon som tilhører `console`-objektet. Hovedforskjellen er at metoder er knyttet til objekter, mens funksjoner står fritt. Mange utviklere bruker disse begrepene om hverandre i uformelle samtaler.
### Beste praksis for funksjoner
Her er noen tips for å hjelpe deg med å skrive gode funksjoner:
Her er noen tips som hjelper deg å skrive gode funksjoner:
- Gi funksjonene dine klare, beskrivende navn din fremtidige selv vil takke deg!
- Bruk **camelCasing** for navn med flere ord (som `calculateTotal` i stedet for `calculate_total`)
- Gi funksjonene dine klare, beskrivende navn ditt fremtidige jeg vil takke deg!
- Bruk **camelCase** for flersordsnavn (som `calculateTotal` i stedet for `calculate_total`)
- Hold hver funksjon fokusert på å gjøre én ting godt
## Sende informasjon til en funksjon
## Å sende informasjon til en funksjon
Vår `displayGreeting`-funksjon er begrenset den kan bare vise "Hello, world!" for alle. Parametere lar oss gjøre funksjoner mer fleksible og nyttige.
Vår `displayGreeting`-funksjon er begrenset den kan bare vise "Hello, world!" til alle. Parametere lar oss gjøre funksjoner mer fleksible og nyttige.
**Parametere** fungerer som plassholdere der du kan sette inn forskjellige verdier hver gang du bruker funksjonen. På denne måten kan den samme funksjonen fungere med ulik informasjon ved hver kall.
**Parametere** fungerer som plassholdere hvor du kan sette inn forskjellige verdier hver gang du bruker funksjonen. På denne måten kan den samme funksjonen jobbe med forskjellig informasjon ved hver kall.
Du lister opp parametere inne i parentesene når du definerer funksjonen, og skiller flere parametere med komma:
Du lister opp parametere inni parentesene når du definerer funksjonen, og skiller flere parametere med komma:
```javascript
function name(param, param2, param3) {
@ -94,9 +165,9 @@ function name(param, param2, param3) {
}
```
Hver parameter fungerer som en plassholder når noen kaller funksjonen din, gir de faktiske verdier som settes inn på disse plassene.
Hver parameter fungerer som en plassholder når noen kaller funksjonen, gir de faktiske verdier som settes inn på disse plassene.
La oss oppdatere hilsningsfunksjonen vår til å akseptere noens navn:
La oss oppdatere hilsningsfunksjonen til å ta imot navnet til en person:
```javascript
function displayGreeting(name) {
@ -105,22 +176,44 @@ function displayGreeting(name) {
}
```
Legg merke til hvordan vi bruker backticks (`` ` ``) og `${}` for å sette inn navnet direkte i meldingen vår dette kalles en mal-literal, og det er en veldig praktisk måte å bygge strenger med variabler blandet inn.
Legg merke til hvordan vi bruker backticks (`` ` ``) og `${}` for å sette inn navnet direkte i meldingen dette kalles en mal-literal, og er en veldig praktisk måte å bygge strenger med variabler i.
når vi kaller funksjonen vår, kan vi sende inn hvilket som helst navn:
Nå kan vi sende inn hvilket som helst navn når vi kaller funksjonen:
```javascript
displayGreeting('Christopher');
// displays "Hello, Christopher!" when run
// viser "Hallo, Christopher!" når den kjøres
```
JavaScript tar strengen `'Christopher'`, tilordner den til parameteren `name`, og lager den personlige meldingen "Hello, Christopher!"
JavaScript tar strengen `'Christopher'`, tilordner den til `name`-parameteren, og lager den personlige meldingen "Hello, Christopher!"
```mermaid
flowchart LR
A["🎯 Funksjonskall"] --> B["📥 Parametre"]
B --> C["⚙️ Funksjonskropp"]
C --> D["📤 Resultat"]
A1["displayGreeting('Alice')"] --> A
B1["navn = 'Alice'"] --> B
C1["Maltekst\n\`Hei, \${navn}!\`"] --> C
D1["'Hei, Alice!'"] --> D
E["🔄 Parametertyper"] --> E1["Strenger"]
E --> E2["Tall"]
E --> E3["Boolske verdier"]
E --> E4["Objekter"]
E --> E5["Funksjoner"]
style A fill:#e3f2fd
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#f3e5f5
```
## Standardverdier
Hva om vi vil gjøre noen parametere valgfrie? Det er her standardverdier kommer til nytte!
Hva hvis vi vil gjøre noen parametere valgfrie? Det er her standardverdier kommer til nytte!
La oss si at vi vil at folk skal kunne tilpasse hilsningsordet, men hvis de ikke spesifiserer ett, bruker vi bare "Hello" som en reserve. Du kan sette opp standardverdier ved å bruke likhetstegnet, akkurat som når du setter en variabel:
La oss si at vi vil at folk skal kunne tilpasse hilsningsordet, men hvis de ikke oppgir ett, bruker vi bare "Hello" som reserve. Du kan sette opp standardverdier ved å bruke likhetstegn, akkurat som når du setter en variabel:
```javascript
function displayGreeting(name, salutation='Hello') {
@ -128,35 +221,63 @@ function displayGreeting(name, salutation='Hello') {
}
```
Her er `name` fortsatt nødvendig, men `salutation` har en reserveverdi på `'Hello'` hvis ingen gir en annen hilsen.
Her er `name` fortsatt påkrevd, men `salutation` har en reserveverdi `'Hello'` hvis ingen gir en annen hilsen.
Nå kan vi kalle denne funksjonen på to forskjellige måter:
```javascript
displayGreeting('Christopher');
// displays "Hello, Christopher"
// viser "Hei, Christopher"
displayGreeting('Christopher', 'Hi');
// displays "Hi, Christopher"
// viser "Hei, Christopher"
```
I den første kallet bruker JavaScript standardverdien "Hello" siden vi ikke spesifiserte en hilsen. I det andre kallet bruker den vår tilpassede "Hi" i stedet. Denne fleksibiliteten gjør funksjoner tilpasningsdyktige til ulike scenarier.
I det første kallet bruker JavaScript standard "Hello" siden vi ikke spesifiserte en hilsen. I det andre kallet bruker den vår egen "Hi". Denne fleksibiliteten gjør funksjonene tilpasningsdyktige i ulike situasjoner.
### 🎛️ **Parametermesterskap: Gjøre funksjoner fleksible**
**Test kunnskapen din om parametere:**
- Hva er forskjellen mellom en parameter og et argument?
- Hvorfor er standardverdier nyttige i ekte programmering?
- Kan du forutsi hva som skjer hvis du sender flere argumenter enn parametere?
```mermaid
stateDiagram-v2
[*] --> NoParams: function greet() {}
[*] --> WithParams: function greet(name) {}
[*] --> WithDefaults: function greet(name, greeting='Hi') {}
NoParams --> Static: Samme utdata alltid
WithParams --> Dynamic: Endres med input
WithDefaults --> Flexible: Valgfri tilpasning
Static --> [*]
Dynamic --> [*]
Flexible --> [*]
note right of WithDefaults
Mest fleksible tilnærming
Bakoverkompatibel
end note
```
> **Profftips**: Standardparametere gjør funksjonene dine mer brukervennlige. Brukere kan komme raskt i gang med fornuftige standarder, men tilpasse ved behov!
## Returneringsverdier
## Returnere verdier
Funksjonene våre så langt har bare skrevet meldinger til konsollen, men hva om du vil at en funksjon skal beregne noe og gi deg tilbake resultatet?
Så langt har funksjonene våre bare skrevet ut meldinger til konsollen, men hva om du vil at en funksjon skal regne ut noe og gi deg resultatet tilbake?
Det er her **returneringsverdier** kommer inn. I stedet for bare å vise noe, kan en funksjon gi deg tilbake en verdi som du kan lagre i en variabel eller bruke i andre deler av koden din.
Der kommer **returverdier** inn i bildet. I stedet for bare å vise noe, kan en funksjon gi deg tilbake en verdi som du kan lagre i en variabel eller bruke andre steder i koden.
For å sende en verdi tilbake, bruker du nøkkelordet `return` etterfulgt av det du vil returnere:
For å sende en verdi tilbake, bruker du `return`-nøkkelordet etterfulgt av det du vil returnere:
```javascript
return myVariable;
```
Her er noe viktig: når en funksjon treffer en `return`-setning, stopper den umiddelbart å kjøre og sender den verdien tilbake til den som kalte den.
Noe viktig: Når en funksjon treffer en `return`-setning, slutter den umiddelbart å kjøre og sender denne verdien tilbake til den som kalte funksjonen.
La oss endre hilsningsfunksjonen vår til å returnere meldingen i stedet for å skrive den ut:
La oss endre hilsningsfunksjonen til å returnere meldingen i stedet for å skrive den ut:
```javascript
function createGreetingMessage(name) {
@ -165,43 +286,81 @@ function createGreetingMessage(name) {
}
```
, i stedet for å skrive ut hilsningen, lager denne funksjonen meldingen og gir den tilbake til oss.
Nå lager denne funksjonen meldingen og gir den tilbake til oss i stedet for å skrive den ut.
For å bruke den returnerte verdien, kan vi lagre den i en variabel akkurat som enhver annen verdi:
For å bruke den returnerte verdien kan vi lagre den i en variabel, akkurat som med andre verdier:
```javascript
const greetingMessage = createGreetingMessage('Christopher');
```
Nå inneholder `greetingMessage` "Hello, Christopher", og vi kan bruke den hvor som helst i koden vår for å vise den på en nettside, inkludere den i en e-post, eller sende den til en annen funksjon.
Nå inneholder `greetingMessage` "Hello, Christopher" og vi kan bruke den hvor som helst i koden vise den på en nettside, inkludere den i en epost, eller sende den til en annen funksjon.
```mermaid
flowchart TD
A["🔧 Funksjonsbehandling"] --> B{"returutsagn?"}
B -->|Ja| C["📤 Returner verdi"]
B -->|Nei| D["📭 Returner udefinert"]
C --> E["💾 Lagre i variabel"]
C --> F["🔗 Bruk i uttrykk"]
C --> G["📞 Send til funksjon"]
D --> H["⚠️ Vanligvis ikke nyttig"]
I["📋 Bruk av returverdi"] --> I1["Beregn resultater"]
I --> I2["Valider input"]
I --> I3["Transformer data"]
I --> I4["Opprett objekter"]
style C fill:#e8f5e8
style D fill:#ffebee
style I fill:#e3f2fd
```
### 🔄 **Returverdier - sjekk: Få resultater tilbake**
**Vurder kunnskapen din om returverdier:**
- Hva skjer med kode som kommer etter en `return`-setning i en funksjon?
- Hvorfor er det ofte bedre å returnere verdier enn bare å skrive ut i konsollen?
- Kan en funksjon returnere ulike typer verdier (streng, tall, boolsk)?
```mermaid
pie title "Vanlige returverdityper"
"Strenger" : 30
"Tall" : 25
"Objekter" : 20
"Booleaner" : 15
"Tabeller" : 10
```
> **Viktig innsikt**: Funksjoner som returnerer verdier er mer allsidige fordi den som kaller funksjonen bestemmer hva som skal gjøres med resultatet. Dette gjør koden mer modulær og gjenbrukbar!
## Funksjoner som parametere for funksjoner
## Funksjoner som parametere til funksjoner
Funksjoner kan sendes som parametere til andre funksjoner. Selv om dette konseptet kan virke komplekst i starten, er det en kraftig funksjon som muliggjør fleksible programmeringsmønstre.
Funksjoner kan sendes som parametere til andre funksjoner. Selv om dette kan virke komplekst i starten, er det en kraftfull egenskap som muliggjør fleksible programmeringsmønstre.
Dette mønsteret er veldig vanlig når du vil si "når noe skjer, gjør denne andre tingen." For eksempel, "når timeren er ferdig, kjør denne koden" eller "når brukeren klikker på knappen, kall denne funksjonen."
Dette mønsteret er veldig vanlig når du vil si "når noe skjer, gjør dette andre". For eksempel, "når timeren er ferdig, kjør denne koden" eller "når brukeren klikker på knappen, kall denne funksjonen."
La oss se på `setTimeout`, som er en innebygd funksjon som venter en viss tid og deretter kjører noe kode. Vi må fortelle den hvilken kode den skal kjøre perfekt brukstilfelle for å sende en funksjon!
La oss se på `setTimeout`, som er en innebygd funksjon som venter en viss tid og så kjører noe kode. Vi må fortelle den hvilken kode den skal kjøre perfekt bruk av å sende inn en funksjon!
Prøv denne koden etter 3 sekunder vil du se en melding:
Prøv denne koden etter 3 sekunder ser du en melding:
```javascript
function displayDone() {
console.log('3 seconds has elapsed');
}
// timer value is in milliseconds
// tidsverdi er i millisekunder
setTimeout(displayDone, 3000);
```
Legg merke til hvordan vi sender `displayDone` (uten parenteser) til `setTimeout`. Vi kaller ikke funksjonen selv vi gir den videre til `setTimeout` og sier "kall denne om 3 sekunder."
Legg merke til at vi sender `displayDone` (uten parenteser) til `setTimeout`. Vi kaller ikke funksjonen selv vi gir den til `setTimeout` og sier "kall denne om 3 sekunder."
### Anonyme funksjoner
Noen ganger trenger du en funksjon for bare én ting og vil ikke gi den et navn. Tenk på det hvis du bare bruker en funksjon én gang, hvorfor fylle opp koden din med et ekstra navn?
Noen ganger trenger du en funksjon til bare én ting og vil ikke gi den noe navn. Tenk på det hvis du bare bruker en funksjon én gang, hvorfor kaste bort koden med et ekstra navn?
JavaScript lar deg lage **anonyme funksjoner** funksjoner uten navn som du kan definere akkurat der du trenger dem.
JavaScript lar deg lage **anonyme funksjoner** funksjoner uten navn som du kan definere rett der du trenger dem.
Slik kan vi skrive om timer-eksempelet vårt ved hjelp av en anonym funksjon:
Slik kan vi skrive om timer-eksemplet vårt med en anonym funksjon:
```javascript
setTimeout(function() {
@ -209,15 +368,15 @@ setTimeout(function() {
}, 3000);
```
Dette oppnår samme resultat, men funksjonen er definert direkte innenfor `setTimeout`-kallet, noe som eliminerer behovet for en separat funksjonsdeklarasjon.
Dette oppnår samme resultat, men funksjonen defineres direkte inni `setTimeout`-kallet, og vi slipper en egen funksjonsdefinisjon.
### Fat arrow-funksjoner
### Piler (Arrow) funksjoner
Moderne JavaScript har en enda kortere måte å skrive funksjoner på, kalt **arrow functions**. De bruker `=>` (som ser ut som en pil skjønner?) og er veldig populære blant utviklere.
Moderne JavaScript har en enda kortere måte å skrive funksjoner på kalt **arrow functions**. De bruker `=>` (som ser ut som en pil skjønner du?) og er veldig populære blant utviklere.
Arrow functions lar deg hoppe over nøkkelordet `function` og skrive mer konsis kode.
Arrow-funksjoner lar deg droppe `function`-nøkkelordet og skrive mer kompakt kode.
Her er timer-eksempelet vårt med en arrow function:
Her er timer-eksemplet vårt med en arrow-funksjon:
```javascript
setTimeout(() => {
@ -225,11 +384,64 @@ setTimeout(() => {
}, 3000);
```
Parentesene `()` er der parametere ville gått (tomt i dette tilfellet), deretter kommer pilen `=>`, og til slutt funksjonskroppen i krøllparenteser. Dette gir samme funksjonalitet med mer konsis syntaks.
### Når skal du bruke hver strategi?
Når bør du bruke hver tilnærming? En praktisk retningslinje: Hvis du vil bruke funksjonen flere ganger, gi den et navn og definer den separat. Hvis den er for én spesifikk bruk, vurder en anonym funksjon. Både arrow functions og tradisjonell syntaks er gyldige valg, selv om arrow functions er utbredt i moderne JavaScript-kodebaser.
`()` er hvor parametere ville stått (tomt her), så kommer pilen `=>`, og til slutt funksjonskroppen i krøllparenteser. Dette gir samme funksjonalitet med mer konsis syntaks.
```mermaid
flowchart LR
A["📝 Funksjonsstiler"] --> B["Tradisjonell"]
A --> C["Pil"]
A --> D["Anonym"]
B --> B1["funksjon navn() {}"]
B --> B2["Hevet"]
B --> B3["Navngitt"]
C --> C1["const navn = () => {}"]
C --> C2["Konsis syntaks"]
C --> C3["Moderne stil"]
D --> D1["funksjon() {}"]
D --> D2["Ingen navn"]
D --> D3["Engangsbruk"]
E["⏰ Når du skal bruke"] --> E1["Tradisjonell: Gjenbrukbare funksjoner"]
E --> E2["Pil: Korte tilbakeringinger"]
E --> E3["Anonym: Hendelsesbehandlere"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
```
### Når bruke hvilken strategi
Når bør du bruke hver tilnærming? En praktisk regel: hvis du skal bruke funksjonen flere ganger, gi den et navn og definer den separat. Hvis det er for et helt spesifikt formål, vurder en anonym funksjon. Både arrow-funksjoner og tradisjonell syntaks er gyldige valg, men arrow-funksjoner er utbredt i moderne JavaScript-kodebaser.
### 🎨 **Funksjonsstiler - mestrings-sjekk: Velge riktig syntaks**
**Test forståelsen din av syntaks:**
- Når kan det være bedre å bruke arrow-funksjoner enn tradisjonell funksjonssyntaks?
- Hva er hovedfordelen med anonyme funksjoner?
- Kan du tenke deg en situasjon hvor en navngitt funksjon er bedre enn en anonym?
```mermaid
quadrantChart
title Funksjonsvalg beslutningsmatrise
x-axis Enkel --> Kompleks
y-axis Engangsbruk --> Gjenbrukbar
quadrant-1 Pilfunksjoner
quadrant-2 Navngitte funksjoner
quadrant-3 Anonyme funksjoner
quadrant-4 Tradisjonelle funksjoner
Event Handlers: [0.3, 0.2]
Utility Functions: [0.7, 0.8]
Callbacks: [0.2, 0.3]
Class Methods: [0.8, 0.7]
Mathematical Operations: [0.4, 0.6]
```
> **Moderne trend**: Arrow-funksjoner blir standardvalget for mange utviklere på grunn av deres kompakte syntaks, men tradisjonelle funksjoner har fortsatt sin plass!
---
@ -237,35 +449,136 @@ Når bør du bruke hver tilnærming? En praktisk retningslinje: Hvis du vil bruk
## 🚀 Utfordring
Kan du forklare forskjellen mellom funksjoner og metoder i én setning? Prøv!
Kan du formulere i én setning forskjellen mellom funksjoner og metoder? Prøv deg!
## GitHub Copilot Agent Utfordring 🚀
## GitHub Copilot Agent-utfordring 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
Bruk Agent-modus for å løse følgende utfordring:
**Beskrivelse:** Lag et verktøybibliotek med matematiske funksjoner som demonstrerer ulike funksjonskonsepter dekket i denne leksjonen, inkludert parametere, standardverdier, returneringsverdier og arrow functions.
**Beskrivelse:** Lag et verktøybibliotek med matematiske funksjoner som demonstrerer ulike funksjonskonsepter dekket i denne leksjonen, inkludert parametere, standardverdier, returverdier og arrow-funksjoner.
**Oppgave:** Lag en JavaScript-fil kalt `mathUtils.js` som inneholder følgende funksjoner:
1. En funksjon `add` som tar to parametere og returnerer summen av dem
2. En funksjon `multiply` med standardverdier for parametere (andre parameter har standardverdi 1)
3. En arrow function `square` som tar et tall og returnerer kvadratet av det
4. En funksjon `calculate` som aksepterer en annen funksjon som parameter og to tall, og deretter bruker funksjonen på disse tallene
5. Demonstrer kall til hver funksjon med passende testtilfeller
**Prompt:** Lag en JavaScript-fil kalt `mathUtils.js` som inneholder følgende funksjoner:
1. En funksjon `add` som tar to parametere og returnerer summen deres
2. En funksjon `multiply` med standardparameterverdier (andre parameter standard til 1)
3. En arrow-funksjon `square` som tar et tall og returnerer kvadratet av det
4. En funksjon `calculate` som aksepterer en annen funksjon som parameter og to tall, og bruker funksjonen på disse tallene
5. Demonstrer å kalle hver funksjon med passende testtilfeller
Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app)
## Post-forelesningsquiz
[Post-lecture quiz](https://ff-quizzes.netlify.app)
## Gjennomgang og selvstudium
## Gjennomgang og Selvstudium
Det er verdt [å lese litt mer om arrow functions](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), da de i økende grad brukes i kodebaser. Øv på å skrive en funksjon, og skriv den deretter om med denne syntaksen.
Det er verdt å [lese litt mer om arrow-funksjoner](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), da de brukes mer og mer i kodebaser. Øv på å skrive en funksjon, og deretter omskrive den med denne syntaksen.
## Oppgave
[Moro med Funksjoner](assignment.md)
[Fun with Functions](assignment.md)
---
## 🧰 **Ditt JavaScript Funksjonsverktøykitt Sammendrag**
```mermaid
graph TD
A["🎯 JavaScript-funksjoner"] --> B["📋 Funksjonsdeklarasjon"]
A --> C["📥 Parametere"]
A --> D["📤 Returverdier"]
A --> E["🎨 Moderne syntaks"]
B --> B1["function name() {}"]
B --> B2["Beskrivende navn"]
B --> B3["Gjenbrukbare kodeblokker"]
C --> C1["Inndata"]
C --> C2["Standardverdier"]
C --> C3["Flere parametere"]
D --> D1["return-setning"]
D --> D2["Forlat funksjon"]
D --> D3["Send data tilbake"]
E --> E1["Pilfunksjoner: () =>"]
E --> E2["Anonyme funksjoner"]
E --> E3["Høyereordensfunksjoner"]
F["⚡ Nøkkelfordeler"] --> F1["Kodegjenbruk"]
F --> F2["Bedre organisering"]
F --> F3["Enklere testing"]
F --> F4["Modulær design"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
---
## 🚀 Din JavaScript Funksjonsmestring Tidslinje
### ⚡ **Hva du kan gjøre i løpet av de neste 5 minuttene**
- [ ] Skriv en enkel funksjon som returnerer ditt favorittnummer
- [ ] Lag en funksjon med to parametere som legger dem sammen
- [ ] Prøv å konvertere en tradisjonell funksjon til pilfunksjon-syntaks
- [ ] Øv på utfordringen: forklar forskjellen mellom funksjoner og metoder
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør quiz etter leksjonen og gå gjennom eventuelle forvirrende konsepter
- [ ] Bygg matematikkverktøybiblioteket fra GitHub Copilot-utfordringen
- [ ] Lag en funksjon som bruker en annen funksjon som parameter
- [ ] Øv på å skrive funksjoner med standardparametere
- [ ] Eksperimenter med template literals i funksjonsreturverdier
### 📅 **Din uke-lange funksjonsmestring**
- [ ] Fullfør oppgaven "Moro med funksjoner" med kreativitet
- [ ] Refaktorer noe repeterende kode du har skrevet til gjenbrukbare funksjoner
- [ ] Bygg en liten kalkulator ved bare å bruke funksjoner (ingen globale variabler)
- [ ] Øv på pilfunksjoner med array-metoder som `map()` og `filter()`
- [ ] Lag en samling med hjelpefunksjoner for vanlige oppgaver
- [ ] Studer høyereordensfunksjoner og funksjonell programmeringskonsepter
### 🌟 **Din måned-lange transformasjon**
- [ ] Mestre avanserte funksjonskonsepter som closures og scope
- [ ] Bygg et prosjekt som i stor grad bruker funksjonskomposisjon
- [ ] Bidra til open source ved å forbedre funksjonsdokumentasjon
- [ ] Lær bort til noen andre om funksjoner og ulike syntaksstiler
- [ ] Utforsk funksjonell programmering i JavaScript
- [ ] Lag et personlig bibliotek av gjenbrukbare funksjoner for fremtidige prosjekter
### 🏆 **Sluttkontroll for funksjonsmester**
**Feir funksjonsmestringen din:**
- Hva er den mest nyttige funksjonen du har laget så langt?
- Hvordan har det å lære om funksjoner endret måten du tenker på kodeorganisering?
- Hvilken funksjonssyntaks foretrekker du og hvorfor?
- Hvilket reelt problem ville du løst ved å skrive en funksjon?
```mermaid
journey
title Din Funksjons Tillitsutvikling
section I dag
Forvirret av syntaks: 3: You
Forståelse av grunnleggende: 4: You
Skriving av enkle funksjoner: 5: You
section Denne uken
Bruk av parametere: 4: You
Returnere verdier: 5: You
Moderne syntaks: 5: You
section Neste måned
Funksjonssammensetning: 5: You
Avanserte mønstre: 5: You
Lære andre: 5: You
```
> 🎉 **Du har mestret et av programmeringens kraftigste konsepter!** Funksjoner er byggesteinene i større programmer. Enhver applikasjon du noensinne bygger vil bruke funksjoner for å organisere, gjenbruke og strukturere kode. Du forstår nå hvordan du pakker logikk inn i gjenbrukbare komponenter, noe som gjør deg til en mer effektiv og dyktig programmerer. Velkommen til verden av modulær programmering! 🚀
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på originalspråket skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,43 +1,91 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "90a3c32c3377f83ab750c2447c77ab98",
"translation_date": "2025-10-23T22:17:28+00:00",
"original_hash": "c688385d15dd3645e924ea0ffee8967f",
"translation_date": "2026-01-07T00:20:53+00:00",
"source_file": "2-js-basics/3-making-decisions/README.md",
"language_code": "no"
}
-->
# Grunnleggende JavaScript: Ta avgjørelser
# JavaScript Grunnleggende: Ta Beslutninger
![Grunnleggende JavaScript - Ta avgjørelser](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0b1cb2f8adaff3ed2a77c4f91db96d8a0594132a353fa189a.no.png)
![JavaScript Basics - Making decisions](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
Har du noen gang lurt på hvordan applikasjoner tar smarte avgjørelser? Som hvordan et navigasjonssystem velger den raskeste ruten, eller hvordan en termostat bestemmer når den skal slå på varmen? Dette er det grunnleggende konseptet med beslutningstaking i programmering.
```mermaid
journey
title Din JavaScript Beslutningsreise
section Grunnlag
Boolean Values: 5: You
Comparison Operators: 4: You
Logical Thinking: 5: You
section Grunnleggende Beslutninger
If Statements: 4: You
If-Else Logic: 5: You
Switch Statements: 4: You
section Avansert Logikk
Logical Operators: 5: You
Complex Conditions: 4: You
Ternary Expressions: 5: You
```
Har du noen gang lurt på hvordan applikasjoner tar smarte beslutninger? Som hvordan et navigasjonssystem velger den raskeste ruten, eller hvordan en termostat bestemmer når den skal slå på varmen? Dette er det grunnleggende konseptet med beslutningstaking i programmering.
Akkurat som Charles Babbages Analytical Engine ble designet for å følge ulike sekvenser av operasjoner basert på betingelser, må moderne JavaScript-programmer ta valg basert på varierende omstendigheter. Denne evnen til å forgrene seg og ta avgjørelser er det som forvandler statisk kode til responsive, intelligente applikasjoner.
Akkurat som Charles Babbages Analytical Engine var designet for å følge forskjellige operasjonssekvenser basert på betingelser, trenger moderne JavaScript-programmer å ta valg basert på varierende omstendigheter. Denne evnen til å forgrene og ta beslutninger er det som forvandler statisk kode til responsive, intelligente applikasjoner.
I denne leksjonen vil du lære hvordan du implementerer betinget logikk i programmene dine. Vi skal utforske betingede utsagn, sammenligningsoperatorer og logiske uttrykk som lar koden din evaluere situasjoner og reagere deretter.
I denne leksjonen vil du lære hvordan du implementerer betinget logikk i programmene dine. Vi skal utforske betingede utsagn, sammenligningsoperatorer og logiske uttrykk som lar koden din evaluere situasjoner og svare hensiktsmessig.
## Quiz før leksjonen
## Forhåndsforelesnings-quiz
[Quiz før leksjonen](https://ff-quizzes.netlify.app/web/quiz/11)
[Forhåndsforelesnings-quiz](https://ff-quizzes.netlify.app/web/quiz/11)
Evnen til å ta avgjørelser og kontrollere programflyten er en grunnleggende del av programmering. Denne delen dekker hvordan du kan kontrollere utførelsesbanen til JavaScript-programmene dine ved hjelp av boolske verdier og betinget logikk.
Evnen til å ta beslutninger og kontrollere programflyt er et grunnleggende aspekt ved programmering. Denne delen dekker hvordan du styrer utførelsesbanen til JavaScript-programmene dine ved hjelp av boolske verdier og betinget logikk.
[![Ta avgjørelser](https://img.youtube.com/vi/SxTp8j-fMMY/0.jpg)](https://youtube.com/watch?v=SxTp8j-fMMY "Ta avgjørelser")
[![Making Decisions](https://img.youtube.com/vi/SxTp8j-fMMY/0.jpg)](https://youtube.com/watch?v=SxTp8j-fMMY "Making Decisions")
> 🎥 Klikk på bildet over for en video om å ta avgjørelser.
> 🎥 Klikk på bildet over for en video om å ta beslutninger.
> Du kan ta denne leksjonen på [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-if-else/?WT.mc_id=academic-77807-sagibbon)!
## En kort oppsummering om boolske verdier
```mermaid
mindmap
root((Beslutningstaking))
Boolean Logikk
sann/usann
Sammenligningsresultater
Logiske uttrykk
Betingede Utsagn
hvis-setninger
Enkel betingelse
Kodeutførelse
hvis-ellers
To veier
Alternative handlinger
bytt
Flere valg
Ren struktur
Operatører
Sammenligning
=== !== < > <= >=
Verdi-relasjoner
Logisk
&& || !
Kombiner betingelser
Avanserte Mønstre
Ternær
? : syntaks
Inline beslutninger
Kompleks Logikk
Nestede betingelser
Flere kriterier
```
## En Kort Oppsummering av Boolske Verdier
Før vi utforsker beslutningstaking, la oss ta en titt på boolske verdier fra vår forrige leksjon. Oppkalt etter matematikeren George Boole, representerer disse verdiene binære tilstander enten `true` eller `false`. Det er ingen tvetydighet, ingen mellomting.
Før vi utforsker beslutningstaking, la oss repetere boolske verdier fra vår forrige leksjon. Oppkalt etter matematikeren George Boole, representerer disse verdiene binære tilstander enten `true` eller `false`. Det er ingen tvetydighet, ingen mellomting.
Disse binære verdiene utgjør grunnlaget for all beregningslogikk. Hver avgjørelse programmet ditt tar, reduseres til slutt til en boolsk evaluering.
Disse binære verdiene danner grunnlaget for all beregningslogikk. Hver beslutning programmet ditt tar, reduseres til en boolsk evaluering.
Å opprette boolske variabler er enkelt:
Å lage boolske variabler er enkelt:
```javascript
let myTrueBool = true;
@ -46,38 +94,91 @@ let myFalseBool = false;
Dette oppretter to variabler med eksplisitte boolske verdier.
✅ Boolske verdier er oppkalt etter den engelske matematikeren, filosofen og logikeren George Boole (18151864).
✅ Boolske er oppkalt etter den engelske matematikeren, filosofen og logikeren George Boole (18151864).
## Sammenligningsoperatorer og boolske verdier
## Sammenligningsoperatorer og Boolske
I praksis vil du sjelden sette boolske verdier manuelt. I stedet genererer du dem ved å evaluere betingelser: "Er dette tallet større enn det andre?" eller "Er disse verdiene like?"
I praksis setter du sjelden boolske verdier manuelt. I stedet genererer du dem ved å evaluere betingelser: "Er dette tallet større enn det andre?" eller "Er disse verdiene like?"
Sammenligningsoperatorer muliggjør disse evalueringene. De sammenligner verdier og returnerer boolske resultater basert på forholdet mellom operandene.
| Symbol | Beskrivelse | Eksempel |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `<` | **Mindre enn**: Sammenligner to verdier og returnerer `true` hvis verdien på venstre side er mindre enn høyre | `5 < 6 // true` |
| `<=` | **Mindre enn eller lik**: Sammenligner to verdier og returnerer `true` hvis verdien på venstre side er mindre enn eller lik høyre | `5 <= 6 // true` |
| `>` | **Større enn**: Sammenligner to verdier og returnerer `true` hvis verdien på venstre side er større enn høyre | `5 > 6 // false` |
| `>=` | **Større enn eller lik**: Sammenligner to verdier og returnerer `true` hvis verdien på venstre side er større enn eller lik høyre | `5 >= 6 // false` |
| `===` | **Streng likhet**: Sammenligner to verdier og returnerer `true` hvis verdiene på høyre og venstre er like OG har samme datatyper | `5 === 6 // false` |
| `!==` | **Ulikhet**: Sammenligner to verdier og returnerer det motsatte boolske resultatet av hva en streng likhetsoperator ville returnere | `5 !== 6 // true` |
✅ Test kunnskapen din ved å skrive noen sammenligninger i nettleserens konsoll. Er det noen returnerte data som overrasker deg?
| `<` | **Mindre enn**: Sammenligner to verdier og returnerer den boolske typen `true` hvis verdien på venstre side er mindre enn på høyre side | `5 < 6 // true` |
| `<=` | **Mindre enn eller lik**: Sammenligner to verdier og returnerer den boolske typen `true` hvis verdien på venstre side er mindre enn eller lik høyre side | `5 <= 6 // true` |
| `>` | **Større enn**: Sammenligner to verdier og returnerer den boolske typen `true` hvis verdien på venstre side er større enn på høyre side | `5 > 6 // false` |
| `>=` | **Større enn eller lik**: Sammenligner to verdier og returnerer den boolske typen `true` hvis verdien på venstre side er større enn eller lik høyre side | `5 >= 6 // false` |
| `===` | **Streng likhet**: Sammenligner to verdier og returnerer den boolske typen `true` hvis verdiene på høyre og venstre side er like OG har samme datatype | `5 === 6 // false` |
| `!==` | **Ulikhet**: Sammenligner to verdier og returnerer det motsatte boolske resultatet av det en streng likhetsoperator ville returnert | `5 !== 6 // true` |
✅ Test kunnskapen din ved å skrive noen sammenligninger i nettleserens konsoll. Overrasker noen av de returnerte dataene deg?
```mermaid
flowchart LR
A["🔢 Verdier"] --> B["⚖️ Sammenligning"]
B --> C["✅ Boolsk resultat"]
D["5"] --> E["< 6"]
E --> F["sant"]
G["10"] --> H["=== '10'"]
H --> I["usant"]
J["'hei'"] --> K["!== 'verden'"]
K --> L["sant"]
M["📋 Operator-typer"] --> M1["Likhet: === !=="]
M --> M2["Relasjon: < > <= >="]
M --> M3["Streng vs Løs"]
style A fill:#e3f2fd
style C fill:#e8f5e8
style M fill:#fff3e0
```
### 🧠 **Sammenligningskontroll: Forstå boolsk logikk**
**Test forståelsen av sammenligninger:**
- Hvorfor tror du `===` (streng likhet) generelt foretrekkes fremfor `==` (løs likhet)?
- Kan du forutsi hva `5 === '5'` returnerer? Hva med `5 == '5'`?
- Hva er forskjellen mellom `!==` og `!=`?
```mermaid
stateDiagram-v2
[*] --> Comparison: To verdier
Comparison --> StrictEqual: === eller !==
Comparison --> Relational: < > <= >=
StrictEqual --> TypeCheck: Sjekk type OG verdi
Relational --> NumberCompare: Konverter til tall
TypeCheck --> BooleanResult: true eller false
NumberCompare --> BooleanResult
note right of StrictEqual
Foretrukket tilnærming
Ingen typekonvertering
end note
note right of Relational
Nyttig for områder
Numeriske sammenligninger
end note
```
> **Proff-tips**: Bruk alltid `===` og `!==` for likhetssjekker med mindre du spesielt trenger typekonvertering. Dette hindrer uventet oppførsel!
## If-setning
`if`-setningen er som å stille et spørsmål i koden din. "Hvis denne betingelsen er sann, gjør denne tingen." Det er sannsynligvis det viktigste verktøyet du vil bruke for å ta avgjørelser i JavaScript.
`if`-setningen er som å stille et spørsmål i koden din. "Hvis denne betingelsen er sann, så gjør dette." Det er sannsynligvis det viktigste verktøyet du vil bruke for å ta beslutninger i JavaScript.
Slik fungerer det:
```javascript
if (condition) {
// Condition is true. Code in this block will run.
// Betingelsen er sann. Koden i denne blokken vil kjøre.
}
```
Betingelsen går inn i parentesene, og hvis den er `true`, kjører JavaScript koden inne i krøllparentesene. Hvis den er `false`, hopper JavaScript over hele blokken.
Betingelsen går inni parentesene, og hvis den er `true`, kjører JavaScript koden inne i krøllparentesene. Hvis den er `false`, hopper JavaScript over hele blokken.
Du vil ofte bruke sammenligningsoperatorer for å lage disse betingelsene. La oss se et praktisk eksempel:
@ -86,64 +187,109 @@ let currentMoney = 1000;
let laptopPrice = 800;
if (currentMoney >= laptopPrice) {
// Condition is true. Code in this block will run.
// Betingelsen er sann. Koden i denne blokken vil kjøre.
console.log("Getting a new laptop!");
}
```
Siden `1000 >= 800` evalueres til `true`, utføres koden inne i blokken, og "Kjøper en ny laptop!" vises i konsollen.
## If..Else-setning
Siden `1000 >= 800` evalueres til `true`, kjører koden innenfor blokken og viser "Getting a new laptop!" i konsollen.
```mermaid
flowchart TD
A["🚀 Programstart"] --> B{"💰 currentMoney >= laptopPrice?"}
B -->|true| C["🎉 'Får en ny laptop!'"]
B -->|false| D["⏭️ Hopp over kodeblokk"]
C --> E["📋 Fortsett programmet"]
D --> E
F["📊 Struktur for if-setning"] --> F1["if (betingelse) {"]
F1 --> F2[" // kode som kjøres hvis sant"]
F2 --> F3["}"]
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#ffebee
style F fill:#e3f2fd
```
## If..Else Setning
Men hva om du vil at programmet ditt skal gjøre noe annet når betingelsen er falsk? Det er her `else` kommer inn det er som å ha en backup-plan.
`else`-setningen gir deg en måte å si "hvis denne betingelsen ikke er sann, gjør denne andre tingen i stedet."
`else`-setningen gir deg en måte å si "hvis denne betingelsen ikke er sann, gjør dette i stedet."
```javascript
let currentMoney = 500;
let laptopPrice = 800;
if (currentMoney >= laptopPrice) {
// Condition is true. Code in this block will run.
// Betingelsen er sann. Koden i denne blokken vil kjøre.
console.log("Getting a new laptop!");
} else {
// Condition is false. Code in this block will run.
// Betingelsen er usann. Koden i denne blokken vil kjøre.
console.log("Can't afford a new laptop, yet!");
}
```
Nå, siden `500 >= 800` er `false`, hopper JavaScript over den første blokken og kjører `else`-blokken i stedet. Du vil se "Har ikke råd til en ny laptop, ennå!" i konsollen.
✅ Test forståelsen din av denne koden og den følgende koden ved å kjøre den i en nettleserkonsoll. Endre verdiene til variablene currentMoney og laptopPrice for å endre den returnerte `console.log()`.
Nå, siden `500 >= 800` er `false`, hopper JavaScript over den første blokken og kjører `else`-blokken i stedet. Du vil se "Can't afford a new laptop, yet!" i konsollen.
✅ Test forståelsen av denne koden og den følgende ved å kjøre den i nettleserens konsoll. Endre verdiene til variablene currentMoney og laptopPrice for å endre det returnerte `console.log()`.
### 🎯 **If-Else Logikk Sjekk: Forgreningsvalg**
**Evaluer forståelsen av betinget logikk:**
- Hva skjer hvis `currentMoney` er nøyaktig lik `laptopPrice`?
- Kan du tenke på en virkelighetsnær situasjon hvor if-else logikk ville være nyttig?
- Hvordan kan du utvide dette for å håndtere flere prisklasser?
```mermaid
flowchart TD
A["🔍 Evaluer Vilkår"] --> B{"Vilkår Sant?"}
B -->|Ja| C["📤 Utfør HVIS-blokk"]
B -->|Nei| D["📥 Utfør ELLERS-blokk"]
C --> E["✅ Én vei tatt"]
D --> E
F["🌐 Virkelige Eksempler"] --> F1["Bruker påloggingsstatus"]
F --> F2["Aldersbekreftelse"]
F --> F3["Skjemavalidering"]
F --> F4["Spilltilstandsendringer"]
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#e3f2fd
style F fill:#f3e5f5
```
> **Viktig innsikt**: If-else sikrer at akkurat én sti tas. Dette garanterer at programmet ditt alltid har en respons på enhver betingelse!
## Switch-setning
Noen ganger må du sammenligne én verdi med flere alternativer. Selv om du kan lenke flere `if..else`-setninger, blir denne tilnærmingen tungvint. `switch`-setningen gir en mer ryddig struktur for å håndtere flere diskrete verdier.
Noen ganger trenger du å sammenligne én verdi mot flere alternativer. Selv om du kunne lenke flere `if..else`-setninger, blir denne tilnærmingen tungvint. `switch`-setningen gir en ryddigere struktur for å håndtere flere diskrete verdier.
Konseptet ligner de mekaniske koblingssystemene som ble brukt i tidlige telefonsentraler én inngangsverdi bestemmer hvilken spesifikk vei utførelsen følger.
Konseptet ligner på de mekaniske brytersystemene som ble brukt i tidlige telefonvekslinger én input-verdi bestemmer hvilken spesifikk vei utførelsen følger.
```javascript
switch (expression) {
case x:
// code block
// kodeblokk
break;
case y:
// code block
// kodeblokk
break;
default:
// code block
// kodeblokk
}
```
Slik er den strukturert:
- JavaScript evaluerer uttrykket én gang
- Den ser gjennom hver `case` for å finne en match
- Når den finner en match, kjører den den kodeblokken
- `break` forteller JavaScript å stoppe og avslutte switch
- Hvis ingen cases matcher, kjører den `default`-blokken (hvis du har en)
- Det ser gjennom hver `case` for å finne et treff
- Når det finner et treff, kjører det den kodeblokken
- `break` sier til JavaScript å stoppe og gå ut av switchen
- Hvis ingen cases matcher, kjører den `default` blokken (hvis du har en)
```javascript
// Program using switch statement for day of week
// Program som bruker switch-setning for ukedag
let dayNumber = 2;
let dayName;
@ -164,72 +310,168 @@ switch (dayNumber) {
console.log(`Today is ${dayName}`);
```
I dette eksempelet ser JavaScript at `dayNumber` er `2`, finner den matchende `case 2`, setter `dayName` til "Tirsdag", og bryter deretter ut av switch. Resultatet? "I dag er det tirsdag" logges til konsollen.
I dette eksemplet ser JavaScript at `dayNumber` er `2`, finner den matchende `case 2`, setter `dayName` til "Tuesday", og bryter ut av switchen. Resultatet? "Today is Tuesday" logges i konsollen.
```mermaid
flowchart TD
A["📥 switch(uttrykk)"] --> B["🔍 Evaluer én gang"]
B --> C{"Matcher sak 1?"}
C -->|Ja| D["📋 Utfør sak 1"]
C -->|Nei| E{"Matcher sak 2?"}
E -->|Ja| F["📋 Utfør sak 2"]
E -->|Nei| G{"Matcher sak 3?"}
G -->|Ja| H["📋 Utfør sak 3"]
G -->|Nei| I["📋 Utfør standard"]
D --> J["🛑 stopp"]
F --> K["🛑 stopp"]
H --> L["🛑 stopp"]
J --> M["✅ Gå ut av switch"]
K --> M
L --> M
I --> M
style A fill:#e3f2fd
style B fill:#fff3e0
style M fill:#e8f5e8
```
✅ Test forståelsen av denne koden og den følgende ved å kjøre den i nettleserens konsoll. Endre verdien til variabelen a for å endre det returnerte `console.log()`.
✅ Test forståelsen din av denne koden og den følgende koden ved å kjøre den i en nettleserkonsoll. Endre verdiene til variabelen a for å endre den returnerte `console.log()`.
### 🔄 **Switch-setningens Mestring: Flere Alternativer**
## Logiske operatorer og boolske verdier
**Test forståelsen av switch:**
- Hva skjer hvis du glemmer en `break`-setning?
- Når ville du brukt `switch` i stedet for flere `if-else`-setninger?
- Hvorfor er `default`-tilfellet nyttig selv om du tror du har dekket alle muligheter?
Komplekse avgjørelser krever ofte evaluering av flere betingelser samtidig. Akkurat som boolsk algebra lar matematikere kombinere logiske uttrykk, gir programmering logiske operatorer for å koble sammen flere boolske betingelser.
```mermaid
pie title "Når du skal bruke hver beslutningsstruktur"
"Enkel hvis-ellers" : 40
"Komplekse hvis-ellers-kjeder" : 25
"Switch-setninger" : 20
"Ternære operatorer" : 15
```
> **Beste praksis**: Bruk `switch` når du sammenligner én variabel mot flere spesifikke verdier. Bruk `if-else` for rekkeviddekontroller eller komplekse betingelser!
## Logiske Operatorer og Boolske
Komplekse beslutninger krever ofte evaluering av flere betingelser samtidig. Akkurat som boolsk algebra lar matematikere kombinere logiske uttrykk, tilbyr programmering logiske operatorer for å koble flere boolske betingelser.
Disse operatorene muliggjør sofistikert betinget logikk ved å kombinere enkle true/false-evalueringer.
| Symbol | Beskrivelse | Eksempel |
| ------ | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `&&` | **Logisk OG**: Sammenligner to boolske uttrykk. Returnerer true **kun** hvis begge sider er sanne | `(5 > 3) && (5 < 10) // Begge sider er sanne. Returnerer true` |
| `\|\|` | **Logisk ELLER**: Sammenligner to boolske uttrykk. Returnerer true hvis minst én side er sann | `(5 > 10) \|\| (5 < 10) // Én side er falsk, den andre er sann. Returnerer true` |
| `!` | **Logisk IKKE**: Returnerer den motsatte verdien av et boolsk uttrykk | `!(5 > 10) // 5 er ikke større enn 10, så "!" gjør det sant` |
| `&&` | **Logisk OG**: Sammenligner to boolske uttrykk. Returnerer `true` **kun** hvis begge sider er sanne | `(5 > 3) && (5 < 10) // Begge sider er sanne. Returnerer true` |
| `\|\|` | **Logisk ELLER**: Sammenligner to boolske uttrykk. Returnerer `true` hvis minst én side er sann | `(5 > 10) \|\| (5 < 10) // Én side er usann, den andre sann. Returnerer true` |
| `!` | **Logisk IKKE**: Returnerer motsatt verdi av et boolsk uttrykk | `!(5 > 10) // 5 er ikke større enn 10, så "!" gjør det sant` |
Disse operatorene lar deg kombinere betingelser på nyttige måter:
- OG (`&&`) betyr at begge betingelsene må være sanne
- ELLER (`||`) betyr at minst én betingelse må være sann
- IKKE (`!`) snur sann til falsk (og omvendt)
## Betingelser og avgjørelser med logiske operatorer
- IKKE (`!`) snur sann til usann (og omvendt)
```mermaid
flowchart LR
A["🔗 Logiske operatorer"] --> B["&& OG"]
A --> C["|| ELLER"]
A --> D["! IKKE"]
B --> B1["Begge må være sanne"]
B --> B2["sann && sann = sann"]
B --> B3["sann && usann = usann"]
C --> C1["Minst én sann"]
C --> C2["sann || usann = sann"]
C --> C3["usann || usann = usann"]
D --> D1["Snur verdien"]
D --> D2["!sann = usann"]
D --> D3["!usann = sann"]
E["🌍 Virkelige eksempler"] --> E1["Alder >= 18 && harLisens"]
E --> E2["erHelg || erHelligdag"]
E --> E3["!erInnlogget"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
```
## Betingelser og Beslutninger med Logiske Operatorer
La oss se disse logiske operatorene i aksjon med et mer realistisk eksempel:
```javascript
let currentMoney = 600;
let laptopPrice = 800;
let laptopDiscountPrice = laptopPrice - (laptopPrice * 0.2); // Laptop price at 20 percent off
let laptopDiscountPrice = laptopPrice - (laptopPrice * 0.2); // Bærbar pris med 20 prosent rabatt
if (currentMoney >= laptopPrice || currentMoney >= laptopDiscountPrice) {
// Condition is true. Code in this block will run.
// Tilstanden er sann. Koden i denne blokken vil kjøre.
console.log("Getting a new laptop!");
} else {
// Condition is false. Code in this block will run.
// Tilstanden er usann. Koden i denne blokken vil kjøre.
console.log("Can't afford a new laptop, yet!");
}
```
I dette eksempelet: vi beregner en 20% rabattpris (640), og evaluerer deretter om våre tilgjengelige midler dekker enten full pris ELLER rabattert pris. Siden 600 oppfyller den rabatterte prisgrensen på 640, evalueres betingelsen til sann.
I dette eksemplet: Vi kalkulerer en 20% rabattpris (640), og evaluerer deretter om tilgjengelige midler dekker enten fullpris ELLER rabattert pris. Siden 600 møter rabattpriskravet på 640, evalueres betingelsen til sann.
### 🧮 **Logiske Operatorer Sjekk: Kombiner Betingelser**
**Test forståelsen av logiske operatorer:**
- I uttrykket `A && B`, hva skjer hvis A er usann? Blir B evaluert i det hele tatt?
- Kan du tenke deg en situasjon hvor du trenger alle tre operatorene (&&, ||, !) sammen?
- Hva er forskjellen mellom `!user.isActive` og `user.isActive !== true`?
```mermaid
stateDiagram-v2
[*] --> EvaluateA: A && B
EvaluateA --> CheckB: A er sann
EvaluateA --> ReturnFalse: A er usann
CheckB --> ReturnTrue: B er sann
CheckB --> ReturnFalse: B er usann
[*] --> EvaluateC: A || B
EvaluateC --> ReturnTrue: A er sann
EvaluateC --> CheckD: A er usann
CheckD --> ReturnTrue: B er sann
CheckD --> ReturnFalse: B er usann
note right of EvaluateA
Kortslutningsevaluering:
Hvis A er usann, blir ikke B sjekket
end note
```
> **Ytelsestips**: JavaScript bruker "short-circuit evaluation" - i `A && B`, hvis A er usann, evalueres ikke B. Bruk dette til din fordel!
### Negasjonsoperator
Noen ganger er det lettere å tenke på når noe IKKE er sant. Som i stedet for å spørre "Er brukeren logget inn?", kan du spørre "Er brukeren IKKE logget inn?" Utropstegnet (`!`) snur logikken for deg.
Noen ganger er det enklere å tenke på når noe IKKE er sant. Som i stedet for å spørre "Er brukeren logget inn?", vil du kanskje spørre "Er brukeren IKKE logget inn?" Utropstegnet (`!`) snur logikken for deg.
```javascript
if (!condition) {
// runs if condition is false
// kjører hvis betingelsen er usann
} else {
// runs if condition is true
// kjører hvis betingelsen er sann
}
```
`!`-operatoren er som å si "det motsatte av..." hvis noe er `true`, gjør `!` det til `false`, og omvendt.
`!` operatoren er som å si "det motsatte av..." hvis noe er `true`, gjør `!` det til `false`, og omvendt.
### Ternære uttrykk
For enkle betingede tildelinger gir JavaScript **ternær operator**. Denne konsise syntaksen lar deg skrive et betinget uttrykk på én linje, nyttig når du trenger å tildele én av to verdier basert på en betingelse.
For enkle betingede tildelinger tilbyr JavaScript **ternær operator**. Denne konsise syntaksen lar deg skrive et betinget uttrykk på én linje, nyttig når du trenger å tildele én av to verdier basert på en betingelse.
```javascript
let variable = condition ? returnThisIfTrue : returnThisIfFalse;
```
Det leses som et spørsmål: "Er denne betingelsen sann? Hvis ja, bruk denne verdien. Hvis nei, bruk den andre verdien."
Det leses som et spørsmål: "Er denne betingelsen sann? Hvis ja, bruk denne verdien. Hvis nei, bruk den verdien."
Nedenfor er et mer konkret eksempel:
Nedenfor er et mer håndfast eksempel:
```javascript
let firstNumber = 20;
@ -237,11 +479,11 @@ let secondNumber = 10;
let biggestNumber = firstNumber > secondNumber ? firstNumber : secondNumber;
```
✅ Ta et øyeblikk til å lese denne koden noen ganger. Forstår du hvordan disse operatorene fungerer?
✅ Ta et øyeblikk til å lese denne koden flere ganger. Forstår du hvordan disse operatorene fungerer?
Her sier denne linjen: "Er `firstNumber` større enn `secondNumber`? Hvis ja, sett `firstNumber` i `biggestNumber`. Hvis nei, sett `secondNumber` i `biggestNumber`."
Denne linjen sier: "Er `firstNumber` større enn `secondNumber`? Hvis ja, sett `firstNumber` i `biggestNumber`. Hvis nei, sett `secondNumber` i `biggestNumber`."
Den ternære operatoren er bare en kortere måte å skrive denne tradisjonelle `if..else`-setningen:
Den ternære operatoren er bare en kortere måte å skrive denne tradisjonelle `if..else`-setningen:
```javascript
let biggestNumber;
@ -252,23 +494,46 @@ if (firstNumber > secondNumber) {
}
```
Begge tilnærmingene gir identiske resultater. Den ternære operatoren gir konsishet, mens den tradisjonelle if-else-strukturen kan være mer lesbar for komplekse betingelser.
Begge tilnærminger gir identiske resultater. Den ternære operatoren tilbyr korthet, mens den tradisjonelle if-else-strukturen kan være mer lesbar for komplekse betingelser.
```mermaid
flowchart LR
A["🤔 Ternær operator"] --> B["betingelse ?"]
B --> C["verdiHvisSann :"]
C --> D["verdiHvisUsann"]
E["📝 Tradisjonell If-Else"] --> F["hvis (betingelse) {"]
F --> G[" returner verdiHvisSann"]
G --> H["} ellers {"]
H --> I[" returner verdiHvisUsann"]
I --> J["}"]
K["⚡ Når å bruke"] --> K1["Enkle tildelinger"]
K --> K2["Korte betingelser"]
K --> K3["Inline beslutninger"]
K --> K4["Returner setninger"]
style A fill:#e3f2fd
style E fill:#fff3e0
style K fill:#e8f5e8
```
---
## 🚀 Utfordring
Lag et program som først er skrevet med logiske operatorer, og deretter skriv det om ved hjelp av et ternært uttrykk. Hvilken syntaks foretrekker du?
Lag et program som først er skrevet med logiske operatorer, og deretter skriv det om ved å bruke et ternært uttrykk. Hva er din foretrukne syntaks?
---
## GitHub Copilot Agent Challenge 🚀
## GitHub Copilot Agent Utfordring 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
Bruk Agent-modus for å løse følgende utfordring:
**Beskrivelse:** Lag en omfattende karakterkalkulator som demonstrerer flere beslutningstakingskonsepter fra denne leksjonen, inkludert if-else-setninger, switch-setninger, logiske operatorer og ternære uttrykk.
**Beskrivelse:** Lag en omfattende karakterskala som demonstrerer flere beslutningskonsepter fra denne leksjonen, inkludert if-else setninger, switch-setninger, logiske operatorer og ternære uttrykk.
**Oppgave:** Skriv et JavaScript-program som tar en students numeriske poengsum (0-100) og bestemmer deres bokstavkarakter ved hjelp av følgende kriterier:
**Prompt:** Skriv et JavaScript-program som tar en students numeriske poengsum (0-100) og bestemmer deres bokstavkarakter ved å bruke følgende kriterier:
- A: 90-100
- B: 80-89
- C: 70-79
@ -276,25 +541,26 @@ Bruk Agent-modus for å fullføre følgende utfordring:
- F: Under 60
Krav:
1. Bruk en if-else-setning for å bestemme bokstavkarakteren
2. Bruk logiske operatorer for å sjekke om studenten består (karakter >= 60) OG har utmerkelse (karakter >= 90)
3. Bruk en switch-setning for å gi spesifikke tilbakemeldinger for hver bokstavkarakter
1. Bruk en if-else setning for å bestemme bokstavkarakteren
2. Bruk logiske operatorer for å sjekke om studenten består (karakter >= 60) OG har utmerkelser (karakter >= 90)
3. Bruk en switch-setning for å gi spesifikk tilbakemelding for hver bokstavkarakter
4. Bruk en ternær operator for å avgjøre om studenten er kvalifisert for neste kurs (karakter >= 70)
5. Inkluder inputvalidering for å sikre at poengsummen er mellom 0 og 100
5. Inkluder input-validering for å sikre at poengsummen er mellom 0 og 100
Test programmet ditt med forskjellige poengsummer inkludert grenseverdier som 59, 60, 89, 90 og ugyldige input.
Test programmet ditt med ulike poengsummer, inkludert grensesaker som 59, 60, 89, 90 og ugyldige inndata.
Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Les mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## Quiz etter leksjonen
## Post-forelesningsquiz
[Quiz etter leksjonen](https://ff-quizzes.netlify.app/web/quiz/12)
[Post-forelesningsquiz](https://ff-quizzes.netlify.app/web/quiz/12)
## Gjennomgang og selvstudium
## Gjennomgang & Selvstudium
Les mer om de mange tilgjengelige operatorene [på MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Les mer om de mange operatorene som er tilgjengelige for brukeren [på MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Gå gjennom Josh Comeaus fantastiske [operator lookup](https://joshwcomeau.com/operator-lookup/)!
Gå gjennom Josh Comeaus flotte [operator lookup](https://joshwcomeau.com/operator-lookup/)!
## Oppgave
@ -302,5 +568,105 @@ Gå gjennom Josh Comeaus fantastiske [operator lookup](https://joshwcomeau.com/o
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på dets opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
## 🧠 **Ditt beslutningsverktøy-sammendrag**
```mermaid
graph TD
A["🎯 JavaScript Beslutninger"] --> B["🔍 Boolsk Logikk"]
A --> C["📊 Betingede Utsagn"]
A --> D["🔗 Logiske Operatorer"]
A --> E["⚡ Avanserte Mønstre"]
B --> B1["sanne/usanne verdier"]
B --> B2["Sammenligningsoperatorer"]
B --> B3["Konsepter for sannhetsverdi"]
C --> C1["if-setninger"]
C --> C2["if-else kjeder"]
C --> C3["switch-setninger"]
D --> D1["&& (OG)"]
D --> D2["|| (ELLER)"]
D --> D3["! (IKKE)"]
E --> E1["Ternær operator"]
E --> E2["Kortslutningsvurdering"]
E --> E3["Komplekse betingelser"]
F["💡 Viktige Prinsipper"] --> F1["Klare lesbare betingelser"]
F --> F2["Konsistent sammenligningsstil"]
F --> F3["Riktig operatorrekkefølge"]
F --> F4["Effektiv vurderingsrekkefølge"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
---
## 🚀 Din tidslinje for JavaScript beslutningsmestring
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Øv på sammenligningsoperatorer i nettleserkonsollen din
- [ ] Skriv en enkel if-else-setning som sjekker alderen din
- [ ] Prøv utfordringen: skriv om en if-else med en ternær operator
- [ ] Test hva som skjer med forskjellige "truthy" og "falsy" verdier
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør post-leksjonsquizen og gjennomgå eventuelle forvirrende konsepter
- [ ] Bygg den omfattende karakterkalkulatoren fra GitHub Copilot-utfordringen
- [ ] Lag et enkelt beslutningstre for et virkelighetsnært scenario (som å velge hva du skal ha på deg)
- [ ] Øv på å kombinere flere betingelser med logiske operatorer
- [ ] Eksperimenter med switch-setninger for forskjellige brukstilfeller
### 📅 **Din ukelange logikkmestring**
- [ ] Fullfør oppgaven om operatorer med kreative eksempler
- [ ] Bygg en mini quiz-applikasjon ved bruk av ulike betingelsesstrukturer
- [ ] Lag en formvaliderer som sjekker flere inndataforhold
- [ ] Øv på Josh Comeaus [operator lookup](https://joshwcomeau.com/operator-lookup/) øvelser
- [ ] Refaktorer eksisterende kode for å bruke mer passende betingelsesstrukturer
- [ ] Studer short-circuit evaluering og ytelseskonsekvenser
### 🌟 **Din månedslange transformasjon**
- [ ] Mestre komplekse nestede betingelser og oppretthold lesbar kode
- [ ] Bygg en applikasjon med sofistikert beslutningslogikk
- [ ] Bidra til open source ved å forbedre betingelseslogikken i eksisterende prosjekter
- [ ] Lær bort til noen andre om ulike betingelsesstrukturer og når de skal brukes
- [ ] Utforsk funksjonelle programmeringstilnærminger til betingelseslogikk
- [ ] Lag en personlig referanseguide for beste praksis i betingelser
### 🏆 **Siste sjekk for beslutningsmesterskap**
**Feire din mestring av logisk tenkning:**
- Hva er den mest komplekse beslutningslogikken du har implementert med suksess?
- Hvilken betingelsesstruktur føles mest naturlig for deg og hvorfor?
- Hvordan har det å lære om logiske operatorer endret måten du løser problemer på?
- Hvilken virkelighetsapplikasjon kan ha nytte av sofistikert beslutningslogikk?
```mermaid
journey
title Din logiske tenkning utvikling
section I dag
Boolsk forvirring: 3: Du
Forståelse av Hvis-Ellers: 4: Du
Gjenkjenning av operatorer: 5: Du
section Denne uken
Komplekse betingelser: 4: Du
Mestring av Switch: 5: Du
Logiske kombinasjoner: 5: Du
section Neste måned
Avanserte mønstre: 5: Du
Ytelsesbevissthet: 5: Du
Lære andre: 5: Du
```
> 🧠 **Du har mestret kunsten å ta digitale beslutninger!** Hver interaktiv applikasjon er avhengig av betingelseslogikk for å reagere intelligent på brukerhandlinger og skiftende forhold. Du forstår nå hvordan du får programmene dine til å tenke, evaluere og velge passende svar. Dette logiske grunnlaget vil drive alle dynamiske applikasjoner du bygger! 🎉
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på originalspråket skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,226 +1,401 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "9197f8af0fef9be6e81d4dbda23c7e7d",
"translation_date": "2025-10-23T22:16:55+00:00",
"original_hash": "1710a50a519a6e4a1b40a5638783018d",
"translation_date": "2026-01-07T00:22:40+00:00",
"source_file": "2-js-basics/4-arrays-loops/README.md",
"language_code": "no"
}
-->
# Grunnleggende JavaScript: Arrays og Løkker
# JavaScript Grunnleggende: Arrays og Løkker
![Grunnleggende JavaScript - Arrays](../../../../translated_images/webdev101-js-arrays.439d7528b8a294558d0e4302e448d193f8ad7495cc407539cc81f1afe904b470.no.png)
![JavaScript Basics - Arrays](../../../../translated_images/webdev101-js-arrays.439d7528b8a29455.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
## Quiz før forelesning
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/13)
```mermaid
journey
title Dine Arrays & Løkker Eventyr
section Grunnleggende om Arrays
Lage Arrays: 5: Du
Tilgang til Elementer: 4: Du
Array Metoder: 5: Du
section Løkke Mestring
For Løkker: 4: Du
While Løkker: 5: Du
Moderne Syntaks: 4: Du
section Databehandling
Array + Løkker: 5: Du
Virkelige Applikasjoner: 4: Du
Ytelsesoptimalisering: 5: Du
```
## Forhåndsforelesning Quiz
[Forhåndsforelesning quiz](https://ff-quizzes.netlify.app/web/quiz/13)
Har du noen gang lurt på hvordan nettsider holder styr på varer i handlekurven eller viser vennelisten din? Det er her arrays og løkker kommer inn. Arrays er som digitale beholdere som lagrer flere informasjonsbiter, mens løkker lar deg jobbe med all denne dataen effektivt uten å måtte skrive repetitiv kode.
Har du noen gang lurt på hvordan nettsider holder oversikt over handlekurvartikler eller viser vennelisten din? Det er her arrays og løkker kommer inn. Arrays er som digitale beholdere som holder flere informasjonsbiter, mens løkker lar deg jobbe med all den dataen effektivt uten gjentakende kode.
Sammen utgjør disse to konseptene grunnlaget for å håndtere informasjon i programmene dine. Du vil lære å gå fra å manuelt skrive ut hvert enkelt trinn til å lage smart, effektiv kode som kan behandle hundrevis eller til og med tusenvis av elementer raskt.
Sammen danner disse to konseptene grunnlaget for å håndtere informasjon i programmene dine. Du vil lære å gå fra manuelt å skrive ut hvert eneste steg til å lage smart, effektiv kode som kan behandle hundrevis eller til og med tusenvis av elementer raskt.
Ved slutten av denne leksjonen vil du forstå hvordan du kan utføre komplekse databehandlingsoppgaver med bare noen få linjer kode. La oss utforske disse essensielle programmeringskonseptene.
slutten av denne leksjonen vil du forstå hvordan du kan utføre komplekse databehandlingsoppgaver med bare noen få kodelinjer. La oss utforske disse essensielle programmeringskonseptene.
[![Arrays](https://img.youtube.com/vi/1U4qTyq02Xw/0.jpg)](https://youtube.com/watch?v=1U4qTyq02Xw "Arrays")
[![Løkker](https://img.youtube.com/vi/Eeh7pxtTZ3k/0.jpg)](https://www.youtube.com/watch?v=Eeh7pxtTZ3k "Løkker")
[![Loops](https://img.youtube.com/vi/Eeh7pxtTZ3k/0.jpg)](https://www.youtube.com/watch?v=Eeh7pxtTZ3k "Løkker")
> 🎥 Klikk på bildene ovenfor for videoer om arrays og løkker.
> Du kan ta denne leksjonen på [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-arrays/?WT.mc_id=academic-77807-sagibbon)!
```mermaid
mindmap
root((Databehandling))
Arrays
Struktur
Firkantede parenteser syntaks
Nullindeksering
Dynamisk størrelse
Operasjoner
push/pop
shift/unshift
indexOf/includes
Typer
Tallrekkefølge
Tekstrekke
Blandet typer
Løkker
For-løkker
Telle iterasjoner
Array-behandling
Forutsigbar flyt
While-løkker
Betingelsesbasert
Ukjent antall iterasjoner
Brukerinndata
Moderne syntaks
for...of
forEach
Funksjonelle metoder
Anvendelser
Dataanalyse
Statistikk
Filtrering
Transformasjoner
Brukergrensesnitt
Lister
Menyer
Gallerier
```
## Arrays
Tenk på arrays som et digitalt arkivskap - i stedet for å lagre ett dokument per skuff, kan du organisere flere relaterte elementer i en enkelt, strukturert beholder. I programmering lar arrays deg lagre flere informasjonsbiter i én organisert pakke.
Tenk på arrays som et digitalt arkivskap i stedet for å lagre ett dokument per skuff, kan du organisere flere relaterte elementer i en enkelt, strukturert beholder. I programmeringsspråk lar arrays deg lagre flere biter informasjon i én organisert pakke.
Enten du bygger et fotogalleri, administrerer en oppgaveliste eller holder styr på poengsummer i et spill, gir arrays grunnlaget for dataorganisering. La oss se hvordan de fungerer.
Enten du bygger et fotogalleri, administrerer en oppgaveliste, eller holder oversikt over høyeste poeng i et spill, gir arrays grunnlaget for dataorganisering. La oss se hvordan de fungerer.
✅ Arrays er overalt! Kan du komme på et eksempel fra virkeligheten, som en solcellepanel-array?
✅ Arrays finnes overalt rundt oss! Kan du tenke deg et virkelig eksempel på en array, som et solcellepanel-array?
### Opprette Arrays
### Lage Arrays
Å opprette en array er superenkelt - bruk bare firkantede parenteser!
Å lage et array er superenkelt bare bruk firkantede parenteser!
```javascript
// Empty array - like an empty shopping cart waiting for items
// Tom matrise - som en tom handlekurv som venter på varer
const myArray = [];
```
**Hva skjer her?**
Du har nettopp opprettet en tom beholder ved hjelp av de firkantede parentesene `[]`. Tenk på det som en tom bokhylle - den er klar til å holde hvilke som helst bøker du vil organisere der.
Du har nettopp laget en tom beholder ved å bruke de firkantede parentesene `[]`. Tenk på det som en tom bibliotekshylle den er klar til å holde hvilke som helst bøker du vil organisere der.
Du kan også fylle arrayen med startverdier med en gang:
Du kan også fylle arrayen din med startverdier med en gang:
```javascript
// Your ice cream shop's flavor menu
// Smakemenyen i iskrembutikken din
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
// A user's profile info (mixing different types of data)
// En brukers profilinformasjon (blanding av forskjellige datatyper)
const userData = ["John", 25, true, "developer"];
// Test scores for your favorite class
// Testresultater for din favorittklasse
const scores = [95, 87, 92, 78, 85];
```
**Kule ting å merke seg:**
**Kule ting å legge merke til:**
- Du kan lagre tekst, tall eller til og med sann/usann-verdier i samme array
- Bare skill hvert element med et komma - enkelt!
- Arrays er perfekte for å holde relatert informasjon samlet
- Bare skil hvert element med et komma enkelt!
- Arrays er perfekte for å holde relaterte opplysninger samlet
```mermaid
flowchart LR
A["📦 Arrays"] --> B["Opprett [ ]"]
A --> C["Lagre flere elementer"]
A --> D["Tilgang etter indeks"]
B --> B1["const arr = []"]
B --> B2["const arr = [1,2,3]"]
C --> C1["Tall"]
C --> C2["Strenger"]
C --> C3["Boolsk"]
C --> C4["Blandet type"]
D --> D1["arr[0] = første"]
D --> D2["arr[1] = andre"]
D --> D3["arr[2] = tredje"]
E["📊 Array-indeks"] --> E1["Indeks 0: Første"]
E --> E2["Indeks 1: Andre"]
E --> E3["Indeks 2: Tredje"]
E --> E4["Indeks n-1: Siste"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
```
### Array-indeksering
Her er noe som kanskje virker uvanlig i starten: arrays nummererer elementene sine fra 0, ikke 1. Denne nullbaserte indekseringen har sine røtter i hvordan dataminne fungerer - det har vært en programmeringskonvensjon siden de tidlige dagene av programmeringsspråk som C. Hver plass i arrayen får sitt eget adressenummer kalt en **indeks**.
Her er noe som kan virke uvanlig i starten: arrays nummererer elementene sine fra 0, ikke 1. Denne nullindekseringen har sin opprinnelse i hvordan datamaskinens minne fungerer det har vært en programmeringskonvensjon siden de tidlige dagene av programmeringsspråk som C. Hvert sted i arrayen får sitt eget adressenummer kalt en **indeks**.
| Indeks | Verdi | Beskrivelse |
|--------|-------|-------------|
| 0 | "Sjokolade" | Første element |
| 1 | "Jordbær" | Andre element |
| 2 | "Vanilje" | Tredje element |
| 3 | "Pistasj" | Fjerde element |
|-------|-------|-------------|
| 0 | "Chocolate" | Første element |
| 1 | "Strawberry" | Andre element |
| 2 | "Vanilla" | Tredje element |
| 3 | "Pistachio" | Fjerde element |
| 4 | "Rocky Road" | Femte element |
✅ Overrasker det deg at arrays starter på nullindeks? I noen programmeringsspråk starter indekser på 1. Det finnes en interessant historie rundt dette, som du kan [lese på Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
✅ Overrasker det deg at arrays starter på indeks null? I noen programmeringsspråk starter indeksene på 1. Det finnes en interessant historie rundt dette, som du kan [lese om på Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
**Tilgang til Array-elementer:**
**Tilgang til array-elementer:**
```javascript
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
// Access individual elements using bracket notation
console.log(iceCreamFlavors[0]); // "Chocolate" - first element
console.log(iceCreamFlavors[2]); // "Vanilla" - third element
console.log(iceCreamFlavors[4]); // "Rocky Road" - last element
// Få tilgang til individuelle elementer ved hjelp av klammeparentesnotasjon
console.log(iceCreamFlavors[0]); // "Sjokolade" - første element
console.log(iceCreamFlavors[2]); // "Vanilje" - tredje element
console.log(iceCreamFlavors[4]); // "Rocky Road" - siste element
```
**Hva skjer her:**
- **Bruker** firkantet parentesnotasjon med indeksnummer for å få tilgang til elementer
- **Returnerer** verdien lagret på den spesifikke posisjonen i arrayen
- **Starter** tellingen fra 0, som gjør det første elementet indeks 0
**Bryter ned hva som skjer her:**
- **Bruker** firkantede parenteser med indeksnummer for å hente elementer
- **Returnerer** verdien som er lagret på den spesifikke posisjonen i arrayen
- **Starter** tellingen fra 0, noe som gjør første element til indeks 0
**Endring av Array-elementer:**
**Endre array-elementer:**
```javascript
// Change an existing value
// Endre en eksisterende verdi
iceCreamFlavors[4] = "Butter Pecan";
console.log(iceCreamFlavors[4]); // "Butter Pecan"
console.log(iceCreamFlavors[4]); // "Smør Pecan"
// Add a new element at the end
// Legg til et nytt element på slutten
iceCreamFlavors[5] = "Cookie Dough";
console.log(iceCreamFlavors[5]); // "Cookie Dough"
console.log(iceCreamFlavors[5]); // "Deig til kjeks"
```
**I eksempelet ovenfor har vi:**
- **Endret** elementet på indeks 4 fra "Rocky Road" til "Butter Pecan"
- **Lagt til** et nytt element "Cookie Dough" på indeks 5
- **Utvidet** arrayens lengde automatisk når vi legger til utover nåværende grenser
- **Utvidet** arrayens lengde automatisk når vi legger til utenfor gjeldende grenser
### Array-lengde og vanlige metoder
Arrays kommer med innebygde egenskaper og metoder som gjør det mye enklere å jobbe med data.
**Finne Array-lengde:**
**Finne array-lengde:**
```javascript
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
console.log(iceCreamFlavors.length); // 5
// Length updates automatically as array changes
// Lengden oppdateres automatisk når arrayet endres
iceCreamFlavors.push("Mint Chip");
console.log(iceCreamFlavors.length); // 6
```
**Viktige punkter å huske:**
- **Returnerer** det totale antallet elementer i arrayen
- **Returnerer** totalt antall elementer i arrayen
- **Oppdateres** automatisk når elementer legges til eller fjernes
- **Gir** en dynamisk telling som er nyttig for løkker og validering
- **Gir** dynamisk telling som er nyttig for løkker og validering
**Essensielle Array-metoder:**
**Viktige array-metoder:**
```javascript
const fruits = ["apple", "banana", "orange"];
// Add elements
fruits.push("grape"); // Adds to end: ["apple", "banana", "orange", "grape"]
fruits.unshift("strawberry"); // Adds to beginning: ["strawberry", "apple", "banana", "orange", "grape"]
// Legg til elementer
fruits.push("grape"); // Legger til på slutten: ["apple", "banana", "orange", "grape"]
fruits.unshift("strawberry"); // Legger til i begynnelsen: ["strawberry", "apple", "banana", "orange", "grape"]
// Remove elements
const lastFruit = fruits.pop(); // Removes and returns "grape"
const firstFruit = fruits.shift(); // Removes and returns "strawberry"
// Fjern elementer
const lastFruit = fruits.pop(); // Fjerner og returnerer "grape"
const firstFruit = fruits.shift(); // Fjerner og returnerer "strawberry"
// Find elements
const index = fruits.indexOf("banana"); // Returns 1 (position of "banana")
const hasApple = fruits.includes("apple"); // Returns true
// Finn elementer
const index = fruits.indexOf("banana"); // Returnerer 1 (posisjonen til "banana")
const hasApple = fruits.includes("apple"); // Returnerer sant
```
**Forstå disse metodene:**
- **Legger til** elementer med `push()` (slutt) og `unshift()` (start)
- **Fjerner** elementer med `pop()` (slutt) og `shift()` (start)
- **Lokaliserer** elementer med `indexOf()` og sjekker eksistens med `includes()`
- **Legger til** elementer med `push()` (på slutten) og `unshift()` (i begynnelsen)
- **Fjerner** elementer med `pop()` (på slutten) og `shift()` (i begynnelsen)
- **Finnes** elementer med `indexOf()` og sjekker eksistens med `includes()`
- **Returnerer** nyttige verdier som fjernede elementer eller posisjonsindekser
✅ Prøv det selv! Bruk nettleserens konsoll for å opprette og manipulere en array du lager selv.
✅ Prøv det selv! Bruk nettleserens konsoll for å opprette og manipulere et array du lager.
### 🧠 **Grunnleggende Array-sjekk: Organiser dataene dine**
**Test din forståelse av arrays:**
- Hvorfor tror du arrays starter å telle fra 0 i stedet for 1?
- Hva skjer om du prøver å få tilgang til en indeks som ikke finnes (som `arr[100]` i et array med 5 elementer)?
- Kan du tenke på tre virkelige situasjoner hvor arrays ville være nyttige?
```mermaid
stateDiagram-v2
[*] --> EmptyArray: const arr = []
EmptyArray --> WithItems: Legg til elementer
WithItems --> Accessing: Bruk indekser
Accessing --> Modifying: Endre verdier
Modifying --> Processing: Bruk metoder
WithItems --> WithItems: push(), unshift()
Processing --> Processing: pop(), shift()
note right of Accessing
Indeksering fra null
arr[0] = første element
end note
note right of Processing
Innebygde metoder
Dynamiske operasjoner
end note
```
> **Virkelighetsinnsikt**: Arrays finnes overalt i programmering! Sosiale medier-feed, handlekurver, fotogallerier, spillelister alle er arrays bak kulissene!
## Løkker
Tenk på den berømte straffen fra Charles Dickens' romaner der elever måtte skrive linjer gjentatte ganger på en tavle. Tenk om du bare kunne instruere noen til "skriv denne setningen 100 ganger" og få det gjort automatisk. Det er akkurat det løkker gjør for koden din.
Løkker er som å ha en utrettelig assistent som kan gjenta oppgaver uten feil. Enten du trenger å sjekke hvert element i en handlekurv eller vise alle bildene i et album, håndterer løkker repetisjonen effektivt.
JavaScript tilbyr flere typer løkker å velge mellom. La oss undersøke hver av dem og forstå når de skal brukes.
Tenk på den kjente straffen i Charles Dickens romaner hvor elever måtte skrive linjer gjentatte ganger på en tavle. Tenk om du bare kunne si til noen «skriv denne setningen 100 ganger» og få det gjort automatisk. Det er akkurat det løkker gjør for koden din.
Løkker er som å ha en utholdende assistent som kan gjenta oppgaver uten feil. Enten du må sjekke hvert element i en handlekurv eller vise alle bildene i et album, håndterer løkker repetisjonen effektivt.
JavaScript tilbyr flere typer løkker å velge mellom. La oss se nærmere på hver av dem og forstå når du bør bruke dem.
```mermaid
flowchart TD
A["🔄 Løkketyper"] --> B["For-løkke"]
A --> C["While-løkke"]
A --> D["For...of-løkke"]
A --> E["forEach-metode"]
B --> B1["Kjente iterasjoner"]
B --> B2["Tellerbasert"]
B --> B3["for(init; betingelse; inkrement)"]
C --> C1["Ukjente iterasjoner"]
C --> C2["Betingelsesbasert"]
C --> C3["while(betingelse)"]
D --> D1["Moderne ES6+"]
D --> D2["Array-iterasjon"]
D --> D3["for(element av array)"]
E --> E1["Funksjonell stil"]
E --> E2["Array-metode"]
E --> E3["array.forEach(callback)"]
F["⏰ Når bruke"] --> F1["For: Telling, indekser"]
F --> F2["While: Brukerinput, søking"]
F --> F3["For...of: Enkel iterasjon"]
F --> F4["forEach: Funksjonell programmering"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
### For-løkke
`for`-løkka er som å sette en timer - du vet nøyaktig hvor mange ganger du vil at noe skal skje. Den er superorganisert og forutsigbar, noe som gjør den perfekt når du jobber med arrays eller trenger å telle ting.
`for`-løkka er som å sette en timer du vet nøyaktig hvor mange ganger du vil at noe skal skje. Den er superorganisert og forutsigbar, noe som gjør den perfekt når du jobber med arrays eller trenger å telle ting.
**Struktur for For-løkke:**
**For-løkkestruktur:**
| Komponent | Formål | Eksempel |
|-----------|--------|----------|
|-----------|---------|----------|
| **Initialisering** | Setter startpunkt | `let i = 0` |
| **Betingelse** | Når den skal fortsette | `i < 10` |
| **Inkrement** | Hvordan oppdatere | `i++` |
| **Inkrement** | Hvordan den oppdateres | `i++` |
```javascript
// Counting from 0 to 9
// Telling fra 0 til 9
for (let i = 0; i < 10; i++) {
console.log(`Count: ${i}`);
}
// More practical example: processing scores
// Mer praktisk eksempel: behandle poengsummer
const testScores = [85, 92, 78, 96, 88];
for (let i = 0; i < testScores.length; i++) {
console.log(`Student ${i + 1}: ${testScores[i]}%`);
}
```
**Trinn for trinn, her er hva som skjer:**
**Steg for steg, her skjer dette:**
- **Initialiserer** tellevariabelen `i` til 0 i starten
- **Sjekker** betingelsen `i < 10` før hver iterasjon
- **Sjekker** betingelsen `i < 10` før hver gjennomgang
- **Utfører** kodeblokken når betingelsen er sann
- **Inkrementerer** `i` med 1 etter hver iterasjon med `i++`
- **Øker** `i` med 1 etter hver gjennomgang med `i++`
- **Stopper** når betingelsen blir usann (når `i` når 10)
✅ Kjør denne koden i en nettleserkonsoll. Hva skjer når du gjør små endringer i telleren, betingelsen eller iterasjonsuttrykket? Kan du få den til å kjøre baklengs, som en nedtelling?
✅ Kjør denne koden i nettleserkonsollen. Hva skjer om du gjør små endringer i tellevariabelen, betingelsen eller inkrementuttrykket? Kan du få den til å gå baklengs, og lage en nedtelling?
### 🗓️ **For-løkke mestringssjekk: Kontrollert repetisjon**
**Evaluer din for-løkke-forståelse:**
- Hva er de tre delene av en for-løkke, og hva gjør hver del?
- Hvordan kan du gå gjennom et array baklengs?
- Hva skjer hvis du glemmer inkrementdelen (`i++`)?
```mermaid
flowchart TD
A["🚀 Start For-løkke"] --> B["Initialiser: let i = 0"]
B --> C{"Betingelse: i < array.length?"}
C -->|true| D["Utfør kodeblokk"]
D --> E["Øk: i++"]
E --> C
C -->|false| F["✅ Avslutt løkke"]
G["📋 Vanlige mønstre"] --> G1["for(let i=0; i<n; i++)"]
G --> G2["for(let i=n-1; i>=0; i--)"]
G --> G3["for(let i=0; i<arr.length; i+=2)"]
style A fill:#e3f2fd
style F fill:#e8f5e8
style G fill:#fff3e0
```
> **Løkkens visdom**: For-løkker er perfekte når du vet nøyaktig hvor mange ganger du må gjenta noe. De er det vanligste valget for arraybehandling!
### While-løkke
`while`-løkka er som å si "fortsett med dette til..." - du vet kanskje ikke nøyaktig hvor mange ganger den vil kjøre, men du vet når den skal stoppe. Den er perfekt for ting som å be en bruker om input til de gir deg det du trenger, eller søke gjennom data til du finner det du leter etter.
`while`-løkka er som å si «fortsett å gjøre dette til...» du vet kanskje ikke akkurat hvor mange ganger den skal kjøre, men du vet når den skal stoppe. Den er perfekt for ting som å spørre en bruker om inndata til de gir deg det du trenger, eller søke gjennom data til du finner det du leter etter.
**Kjennetegn ved While-løkke:**
**Egenskaper ved while-løkke:**
- **Fortsetter** å kjøre så lenge betingelsen er sann
- **Krever** manuell håndtering av eventuelle tellevariabler
- **Sjekker** betingelsen før hver iterasjon
- **Risikerer** uendelige løkker hvis betingelsen aldri blir usann
- **Krever** manuell håndtering av tellevariabler
- **Sjekker** betingelsen før hver gjennomgang
- **Risikerer** evige løkker hvis betingelsen aldri blir usann
```javascript
// Basic counting example
// Grunnleggende telleeksempel
let i = 0;
while (i < 10) {
console.log(`While count: ${i}`);
i++; // Don't forget to increment!
i++; // Ikke glem å inkrementere!
}
// More practical example: processing user input
// Mer praktisk eksempel: behandle brukerinput
let userInput = "";
let attempts = 0;
const maxAttempts = 3;
@ -236,81 +411,139 @@ if (attempts >= maxAttempts) {
```
**Forstå disse eksemplene:**
- **Håndterer** tellevariabelen `i` manuelt inne i løkkens kropp
- **Inkrementerer** telleren for å forhindre uendelige løkker
- **Demonstrerer** praktisk bruk med brukerinput og begrensning av forsøk
- **Inkluderer** sikkerhetsmekanismer for å forhindre endeløs kjøring
- **Håndterer** telling manuelt inne i løkka
- **Øker** tellevariabelen for å forhindre evige løkker
- **Demonstrerer** praktisk bruk med brukerinput og forsøkstallbegrensning
- **Inkluderer** sikkerhetsmekanismer for å unngå uendelig kjøring
### ♾️ **While-løkke visdomssjekk: Betingelsesbasert repetisjon**
**Test din forståelse av while-løkker:**
- Hva er den største faren ved å bruke while-løkker?
- Når ville du velge en while-løkke over en for-løkke?
- Hvordan kan du forhindre evige løkker?
```mermaid
flowchart LR
A["🔄 While vs For"] --> B["While-løkke"]
A --> C["For-løkke"]
B --> B1["Ukjent antall iterasjoner"]
B --> B2["Betingelsesdrevet"]
B --> B3["Brukerinput, søking"]
B --> B4["⚠️ Risiko: uendelige løkker"]
C --> C1["Kjent antall iterasjoner"]
C --> C2["Tellerdrevet"]
C --> C3["Array-behandling"]
C --> C4["✅ Trygt: forutsigbar slutt"]
D["🛡️ Sikkerhetstips"] --> D1["Endre alltid betingelsesvariabel"]
D --> D2["Inkluder fluktbetingelser"]
D --> D3["Sett maksimumsgrense for iterasjoner"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#ffebee
```
> **Sikkerhet først**: While-løkker er kraftige, men krever nøye styring av betingelsene. Sørg alltid for at løkkebetingelsen til slutt blir usann!
### Moderne løkkealternativer
JavaScript tilbyr moderne løkkesyntaks som kan gjøre koden din mer lesbar og mindre feilutsatt.
**For...of-løkke (ES6+):**
**For...of løkke (ES6+):**
```javascript
const colors = ["red", "green", "blue", "yellow"];
// Modern approach - cleaner and safer
// Moderne tilnærming - renere og sikrere
for (const color of colors) {
console.log(`Color: ${color}`);
}
// Compare with traditional for loop
// Sammenlign med tradisjonell for-løkke
for (let i = 0; i < colors.length; i++) {
console.log(`Color: ${colors[i]}`);
}
```
**Viktige fordeler med for...of:**
- **Eliminerer** indeksstyring og potensielle feil med én avvik
- **Fjerner** behovet for indeksbehandling og potensielle avvik av én-feil
- **Gir** direkte tilgang til array-elementer
- **Forbedrer** kodelesbarhet og reduserer syntakskompleksitet
- **Forbedrer** lesbarheten og reduserer syntakskomplisitet
**forEach-metode:**
**forEach-metoden:**
```javascript
const prices = [9.99, 15.50, 22.75, 8.25];
// Using forEach for functional programming style
// Bruke forEach for funksjonell programmeringsstil
prices.forEach((price, index) => {
console.log(`Item ${index + 1}: $${price.toFixed(2)}`);
});
// forEach with arrow functions for simple operations
// forEach med pilfunksjoner for enkle operasjoner
prices.forEach(price => console.log(`Price: $${price}`));
```
**Hva du trenger å vite om forEach:**
- **Utfører** en funksjon for hvert array-element
**Det du må vite om forEach:**
- **Kjører** en funksjon for hvert array-element
- **Gir** både elementverdi og indeks som parametere
- **Kan ikke** stoppes tidlig (i motsetning til tradisjonelle løkker)
- **Returnerer** undefined (lager ikke en ny array)
✅ Hvorfor ville du valgt en for-løkke kontra en while-løkke? 17K lesere hadde det samme spørsmålet på StackOverflow, og noen av meningene [kan være interessante for deg](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
- **Returnerer** undefined (lager ikke et nytt array)
✅ Hvorfor ville du velge en for-løkke fremfor en while-løkke? 17 000 besøkende stilte det samme spørsmålet på StackOverflow, og noen av meningene [kan være interessante for deg](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
### 🎨 **Moderne løkkesyntaks-sjekk: Omfavner ES6+**
**Vurder din moderne JavaScript-forståelse:**
- Hva er fordelene med `for...of` i forhold til tradisjonelle for-løkker?
- Når kan du fortsatt foretrekke tradisjonelle for-løkker?
- Hva er forskjellen mellom `forEach` og `map`?
```mermaid
quadrantChart
title Veiledning for valg av løkker
x-axis Tradisjonell --> Moderne
y-axis Enkel --> Kompleks
quadrant-1 Moderne Kompleks
quadrant-2 Tradisjonell Kompleks
quadrant-3 Tradisjonell Enkel
quadrant-4 Moderne Enkel
Tradisjonell For: [0.2, 0.7]
While-løkke: [0.3, 0.6]
For...of: [0.8, 0.3]
forEach: [0.9, 0.4]
Array-metoder: [0.8, 0.8]
```
> **Moderne trend**: ES6+-syntaks som `for...of` og `forEach` er i ferd med å bli foretrukket til array-iterasjon fordi det er renere og mindre feilutsatt!
## Løkker og Arrays
Å kombinere arrays med løkker skaper kraftige databehandlingsmuligheter. Denne kombinasjonen er grunnleggende for mange programmeringsoppgaver, fra å vise lister til å beregne statistikk.
Å kombinere arrays med løkker gir kraftige muligheter for databehandling. Denne kombinasjonen er grunnleggende for mange programmeringsoppgaver, fra visning av lister til å kalkulere statistikk.
**Tradisjonell Array-behandling:**
**Tradisjonell array-behandling:**
```javascript
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
// Classic for loop approach
// Klassisk for-løkke tilnærming
for (let i = 0; i < iceCreamFlavors.length; i++) {
console.log(`Flavor ${i + 1}: ${iceCreamFlavors[i]}`);
}
// Modern for...of approach
// Moderne for...of tilnærming
for (const flavor of iceCreamFlavors) {
console.log(`Available flavor: ${flavor}`);
}
```
**La oss forstå hver tilnærming:**
- **Bruker** arrayens lengdeegenskap for å bestemme løkkens grense
- **Får tilgang til** elementer via indeks i tradisjonelle for-løkker
- **Bruker** array-lengdeegenskap for å bestemme løkkens grense
- **Tilgår** elementer via indeks i tradisjonelle for-løkker
- **Gir** direkte elementtilgang i for...of-løkker
- **Behandler** hvert array-element nøyaktig én gang
@ -322,7 +555,7 @@ let total = 0;
let highestGrade = studentGrades[0];
let lowestGrade = studentGrades[0];
// Process all grades with a single loop
// Behandle alle karakterer med en enkelt løkke
for (let i = 0; i < studentGrades.length; i++) {
const grade = studentGrades[i];
total += grade;
@ -343,45 +576,175 @@ console.log(`Lowest: ${lowestGrade}`);
```
**Slik fungerer denne koden:**
- **Initialiserer** sporingsvariabler for sum og ytterpunkter
- **Behandler** hver karakter med en enkelt effektiv løkke
- **Akkumulerer** totalen for gjennomsnittsberegning
- **Sporer** høyeste og laveste verdier under iterasjon
- **Beregner** endelige statistikker etter løkkens fullføring
✅ Eksperimenter med å iterere over en array du lager selv i nettleserens konsoll.
- **Initialiserer** variabler for sum og ytterpunkter
- **Behandler** hver karakter med en enkel effektiv løkke
- **Akkumulerer** totalen for gjennomsnittskalkulering
- **Sporer** høyeste og laveste verdi under gjennomgangen
- **Beregner** endelig statistikk etter at løkken er fullført
✅ Eksperimenter med å løpe gjennom et array du lager selv i nettleserkonsollen.
```mermaid
flowchart TD
A["📦 Array-data"] --> B["🔄 Løkkeprosessering"]
B --> C["📈 Resultater"]
A1["[85, 92, 78, 96, 88]"] --> A
B --> B1["Beregn total"]
B --> B2["Finn min/maks"]
B --> B3["Tell betingelser"]
B --> B4["Transformer data"]
C --> C1["Gjennomsnitt: 87.8"]
C --> C2["Høyest: 96"]
C --> C3["Bestått: 5/5"]
C --> C4["Bokstavkarakterer"]
D["⚡ Prosesseringsmønstre"] --> D1["Akkumulering (sum)"]
D --> D2["Sammenligning (min/maks)"]
D --> D3["Filtrering (betingelser)"]
D --> D4["Kartlegging (transformasjon)"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#f3e5f5
```
---
## GitHub Copilot Agent-utfordring 🚀
## GitHub Copilot Agent Utfordring 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Bygg en omfattende databehandlingsfunksjon som kombinerer arrays og løkker for å analysere et datasett og generere meningsfulle innsikter.
**Prompt:** Lag en funksjon kalt `analyzeGrades` som tar en array av studentkarakterobjekter (hver inneholder navn og score-egenskaper) og returnerer et objekt med statistikk inkludert høyeste score, laveste score, gjennomsnittsscore, antall studenter som bestod (score >= 70), og en array av studentnavn som scoret over gjennomsnittet. Bruk minst to forskjellige løkketyper i løsningen din.
**Oppgave:** Lag en funksjon kalt `analyzeGrades` som tar et array av studentkarakter-objekter (hvert med egenskapene navn og poengsum) og returnerer et objekt med statistikk inkludert høyeste poengsum, laveste poengsum, gjennomsnittlig poengsum, antall studenter som besto (poengsum >= 70), og et array av navn på studenter som fikk over gjennomsnittet. Bruk minst to forskjellige løkketyper i løsningen din.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Lær mer om [agent modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
JavaScript tilbyr flere moderne array-metoder som kan erstatte tradisjonelle løkker for spesifikke oppgaver. Utforsk [forEach](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), [for-of](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for...of), [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map), [filter](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), og [reduce](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
**Din utfordring:** Refaktorer eksempelet med studentkarakterer ved å bruke minst tre forskjellige array-metoder. Legg merke til hvor mye renere og mer lesbar koden blir med moderne JavaScript-syntaks.
**Din utfordring:** Omstrukturer elevkarakter-eksemplet ved å bruke minst tre forskjellige array-metoder. Legg merke til hvor mye renere og mer lesbart koden blir med moderne JavaScript-syntaks.
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/14)
## Post-forelesningsquiz
[Post-forelesningsquiz](https://ff-quizzes.netlify.app/web/quiz/14)
## Gjennomgang og selvstudium
## Gjennomgang & Selvstudium
Arrays i JavaScript har mange metoder knyttet til seg, som er ekstremt nyttige for datamanipulering. [Les om disse metodene](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) og prøv noen av dem (som push, pop, slice og splice) på en array du lager selv.
Arrays i JavaScript har mange tilknyttede metoder som er ekstremt nyttige for datamanipulering. [Les om disse metodene](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) og prøv noen av dem (som push, pop, slice og splice) på et array du lager.
## Oppgave
[Iterer en Array](assignment.md)
[Loop an Array](assignment.md)
---
## 📊 **Ditt sammendrag av Arrays & Løkker-verktøykassen**
```mermaid
graph TD
A["🎯 Mestring av tabeller og løkker"] --> B["📦 Grunnleggende tabeller"]
A --> C["🔄 Løkketyper"]
A --> D["🔗 Databehandling"]
A --> E["🎨 Moderne teknikker"]
B --> B1["Opprettelse: [ ]"]
B --> B2["Indeksering: arr[0]"]
B --> B3["Metoder: push, pop"]
B --> B4["Egenskaper: length"]
C --> C1["For: Kjente iterasjoner"]
C --> C2["While: Betingelsesbasert"]
C --> C3["For...of: Direkte tilgang"]
C --> C4["forEach: Funksjonell"]
D --> D1["Statistikkberegning"]
D --> D2["Datatransformasjon"]
D --> D3["Filtrering & søk"]
D --> D4["Sanntidsbehandling"]
E --> E1["Pilerfunksjoner"]
E --> E2["Metodekjedning"]
E --> E3["Destrukturering"]
E --> E4["Mal-literal"]
F["💡 Viktige fordeler"] --> F1["Effektiv datahåndtering"]
F --> F2["Redusert kodegjentakelse"]
F --> F3["Skalerbare løsninger"]
F --> F4["Renere syntaks"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
---
## 🚀 Din tidslinje for mestring av Arrays & Løkker
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Lag et array av dine favorittfilmer og få tilgang til spesifikke elementer
- [ ] Skriv en for-løkke som teller fra 1 til 10
- [ ] Prøv utfordringen med moderne array-metoder fra leksjonen
- [ ] Øv på array-indeksering i nettleserkonsollen din
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør post-leksjonsquizen og gå gjennom eventuelle utfordrende konsepter
- [ ] Bygg den omfattende karakteranalysatoren fra GitHub Copilot-utfordringen
- [ ] Lag en enkel handlekurv som legger til og fjerner elementer
- [ ] Øv på å konvertere mellom forskjellige løkketyper
- [ ] Eksperimenter med array-metoder som `push`, `pop`, `slice` og `splice`
### 📅 **Din ukeslange reise innen databehandling**
- [ ] Fullfør oppgaven "Loop an Array" med kreative forbedringer
- [ ] Bygg en gjøremålsliste-applikasjon som bruker arrays og løkker
- [ ] Lag en enkel statistikk-kalkulator for numeriske data
- [ ] Øv på [MDN array-metoder](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
- [ ] Lag et fotogalleri eller musikkspillelistegrensesnitt
- [ ] Utforsk funksjonell programmering med `map`, `filter` og `reduce`
### 🌟 **Din månedslange transformasjon**
- [ ] Mestre avanserte array-operasjoner og ytelsesoptimalisering
- [ ] Bygg et komplett dashbord for datavisualisering
- [ ] Bidra til open source-prosjekter som involverer databehandling
- [ ] Lær bort til andre om arrays og løkker med praktiske eksempler
- [ ] Lag et personlig bibliotek med gjenbrukbare funksjoner for databehandling
- [ ] Utforsk algoritmer og datastrukturer basert på arrays
### 🏆 **Siste sjekkpunkt for databehandlingsmester**
**Feir din mestring av arrays og løkker:**
- Hva er den mest nyttige array-operasjonen du har lært for virkelige anvendelser?
- Hvilken løkketype føles mest naturlig for deg, og hvorfor?
- Hvordan har forståelsen av arrays og løkker endret din tilnærming til å organisere data?
- Hvilken kompleks databehandlingsoppgave ønsker du å prøve på neste?
```mermaid
journey
title Din Data Behandlingsutvikling
section I dag
Array Forvirring: 3: Du
Grunnleggende Løkker: 4: Du
Forståelse av Indeks: 5: Du
section Denne Uken
Metode Beherskelse: 4: Du
Effektiv Behandling: 5: Du
Moderne Syntaks: 5: Du
section Neste Måned
Komplekse Algoritmer: 5: Du
Ytelsesoptimalisering: 5: Du
Lære Andre: 5: Du
```
> 📦 **Du har låst opp kraften i dataorganisering og -behandling!** Arrays og løkker er grunnlaget for nesten alle applikasjoner du noen gang kommer til å lage. Fra enkle lister til kompleks dataanalyse har du nå verktøyene for å håndtere informasjon effektivt og elegant. Hver dynamisk nettside, mobilapp og datadrevet applikasjon er avhengig av disse fundamentale konseptene. Velkommen til verden av skalerbar databehandling! 🎉
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på dets opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på originalspråket skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,47 +1,92 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "20c72cf2e5b0050d38ca3cb14a75a9df",
"translation_date": "2025-10-23T22:29:08+00:00",
"original_hash": "3fcfa99c4897e051b558b5eaf1e8cc74",
"translation_date": "2026-01-07T00:49:11+00:00",
"source_file": "3-terrarium/1-intro-to-html/README.md",
"language_code": "no"
}
-->
# Terrarium-prosjekt del 1: Introduksjon til HTML
![Introduksjon til HTML](../../../../translated_images/webdev101-html.4389c2067af68e98280c1bde52b6c6269f399eaae3659b7c846018d8a7b0bbd9.no.png)
```mermaid
journey
title Din HTML-læringsreise
section Grunnlag
Lag HTML-fil: 3: Student
Legg til DOCTYPE: 4: Student
Strukturér dokument: 5: Student
section Innhold
Legg til metadata: 4: Student
Inkluder bilder: 5: Student
Organiser oppsett: 5: Student
section Semantikk
Bruk riktige tagger: 4: Student
Forbedre tilgjengelighet: 5: Student
Bygg terrarium: 5: Student
```
![Introduksjon til HTML](../../../../translated_images/webdev101-html.4389c2067af68e98.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
HTML, eller HyperText Markup Language, er grunnlaget for alle nettsider du noen gang har besøkt. Tenk på HTML som skjelettet som gir struktur til nettsider det definerer hvor innholdet skal plasseres, hvordan det er organisert, og hva hver del representerer. Mens CSS senere vil "kle opp" HTML-en din med farger og oppsett, og JavaScript vil gi den liv med interaktivitet, gir HTML den essensielle strukturen som gjør alt annet mulig.
I denne leksjonen skal du lage HTML-strukturen for et virtuelt terrarium-grensesnitt. Dette praktiske prosjektet vil lære deg grunnleggende HTML-konsepter mens du bygger noe visuelt engasjerende. Du vil lære hvordan du organiserer innhold ved hjelp av semantiske elementer, jobber med bilder, og lager grunnlaget for en interaktiv webapplikasjon.
Ved slutten av denne leksjonen vil du ha en fungerende HTML-side som viser plantebilder i organiserte kolonner, klar for styling i neste leksjon. Ikke bekymre deg hvis det ser enkelt ut i starten det er akkurat slik HTML skal være før CSS legger til den visuelle finishen.
## Quiz før leksjonen
HTML, eller HyperText Markup Language, er grunnlaget for alle nettsider du noen gang har besøkt. Tenk på HTML som skjelettet som gir struktur til nettsider det definerer hvor innhold går, hvordan det organiseres, og hva hver del representerer. Mens CSS senere "kler opp" ditt HTML med farger og oppsett, og JavaScript bringer det til liv med interaktivitet, gir HTML den nødvendige strukturen som gjør alt annet mulig.
I denne leksjonen skal du lage HTML-strukturen for et virtuelt terrarium-grensesnitt. Dette praktiske prosjektet vil lære deg grunnleggende HTML-konsepter mens du bygger noe visuelt engasjerende. Du vil lære hvordan du organiserer innhold med semantiske elementer, jobber med bilder, og lager grunnlaget for en interaktiv webapplikasjon.
Ved slutten av denne leksjonen vil du ha en fungerende HTML-side som viser plantebilder i organiserte kolonner, klar for styling i neste leksjon. Ikke bekymre deg om det ser enkelt ut i starten det er akkurat slik HTML skal være før CSS legger til den visuelle poleringen.
```mermaid
mindmap
root((HTML Grunnleggende))
Structure
DOCTYPE-erklæring
HTML-element
Hode seksjon
Kropp innhold
Elements
Tagger & Attributter
Selv-lukkende tagger
Innlagte elementer
Blokk vs Inline
Content
Tekstelementer
Bilder
Beholdere (div)
Lister
Semantics
Meningsfulle tagger
Tilgjengelighet
Skjermlesere
SEO Fordeler
Best Practices
Korrekt innrykk
Gyldig markup
Beskrivende alt-tekst
Organisert struktur
```
## Quiz før forelesning
[Quiz før leksjonen](https://ff-quizzes.netlify.app/web/quiz/15)
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/15)
> 📺 **Se og lær**: Sjekk ut denne nyttige videooversikten
> 📺 **Se og lær**: Se denne nyttige videooversikten
>
> [![HTML Grunnleggende Video](https://img.youtube.com/vi/1TvxJKBzhyQ/0.jpg)](https://www.youtube.com/watch?v=1TvxJKBzhyQ)
> [![HTML Fundamentals Video](https://img.youtube.com/vi/1TvxJKBzhyQ/0.jpg)](https://www.youtube.com/watch?v=1TvxJKBzhyQ)
## Sette opp prosjektet ditt
Før vi dykker inn i HTML-koden, la oss sette opp et ordentlig arbeidsområde for terrarium-prosjektet ditt. Å lage en organisert filstruktur fra starten av er en viktig vane som vil være nyttig gjennom hele din webutviklingsreise.
Før vi dykker inn i HTML-koden, la oss sette opp et ordentlig arbeidsområde for terrarium-prosjektet ditt. Å lage en organisert mappestruktur fra begynnelsen er en viktig vane som vil tjene deg godt gjennom hele webutviklingsreisen.
### Oppgave: Lag prosjektstrukturen din
Du skal lage en dedikert mappe for terrarium-prosjektet ditt og legge til din første HTML-fil. Her er to tilnærminger du kan bruke:
Du skal lage en dedikert mappe for terrarium-prosjektet ditt og legge til din første HTML-fil. Her er to ulike metoder du kan bruke:
**Alternativ 1: Bruke Visual Studio Code**
1. Åpne Visual Studio Code
2. Klikk "File" → "Open Folder" eller bruk `Ctrl+K, Ctrl+O` (Windows/Linux) eller `Cmd+K, Cmd+O` (Mac)
3. Lag en ny mappe kalt `terrarium` og velg den
4. I Explorer-panelet, klikk på "New File"-ikonet
5. Navngi filen din `index.html`
3. Opprett en ny mappe kalt `terrarium` og velg den
4. I Explorer-panelet, klikk på ikonet for "New File"
5. Gi filen navnet `index.html`
![VS Code Explorer viser opprettelse av ny fil](../../../../translated_images/vs-code-index.e2986cf919471eb984a0afef231380c8b132b000635105f2397bd2754d1b689c.no.png)
![VS Code Explorer showing new file creation](../../../../translated_images/vs-code-index.e2986cf919471eb9.no.png)
**Alternativ 2: Bruke terminalkommandoer**
```bash
@ -53,21 +98,38 @@ code index.html
**Dette oppnår disse kommandoene:**
- **Oppretter** en ny katalog kalt `terrarium` for prosjektet ditt
- **Navigerer** inn i terrarium-katalogen
- **Oppretter** en tom `index.html`-fil
- **Går inn i** terrarium-mappen
- **Oppretter** en tom `index.html` fil
- **Åpner** filen i Visual Studio Code for redigering
> 💡 **Proff-tips**: Filnavnet `index.html` er spesielt i webutvikling. Når noen besøker et nettsted, ser nettlesere automatisk etter `index.html` som standard siden som skal vises. Dette betyr at en URL som `https://mysite.com/projects/` automatisk vil vise `index.html`-filen fra `projects`-mappen uten å måtte spesifisere filnavnet i URL-en.
> 💡 **Proftips**: Filnavnet `index.html` er spesielt i webutvikling. Når noen besøker en nettside, leter nettlesere automatisk etter `index.html` som standardside å vise. Det betyr at en URL som `https://mysite.com/projects/` automatisk vil vise `index.html`-filen i `projects`-mappen uten at du trenger å spesifisere filnavnet i URL-en.
## Forstå HTML-dokumentstruktur
Hvert HTML-dokument følger en spesifikk struktur som nettlesere trenger for å forstå og vise korrekt. Tenk på denne strukturen som et formelt brev det har nødvendige elementer i en bestemt rekkefølge som hjelper mottakeren (i dette tilfellet nettleseren) med å prosessere innholdet riktig.
La oss starte med å legge til det essensielle fundamentet som hvert HTML-dokument trenger.
Hvert HTML-dokument følger en spesifikk struktur som nettlesere må forstå og vise riktig. Tenk på denne strukturen som et formelt brev den har påkrevde elementer i en bestemt rekkefølge som hjelper mottakeren (nettleseren) med å prosessere innholdet på riktig måte.
```mermaid
flowchart TD
A["<!DOCTYPE html>"] --> B["<html>"]
B --> C["<head>"]
C --> D["<title>"]
C --> E["<meta charset>"]
C --> F["<meta viewport>"]
B --> G["<body>"]
G --> H["<h1> Overskrift"]
G --> I["<div> Beholdere"]
G --> J["<img> Bilder"]
style A fill:#e1f5fe
style B fill:#f3e5f5
style C fill:#fff3e0
style G fill:#e8f5e8
```
La oss starte med å legge til det essensielle grunnlaget som hvert HTML-dokument trenger.
### DOCTYPE-deklarasjon og rootelement
### DOCTYPE-deklarasjonen og rootelementet
De to første linjene i en HTML-fil fungerer som dokumentets "introduksjon" til nettleseren:
De to første linjene i en hvilken som helst HTML-fil fungerer som dokumentets "introduksjon" til nettleseren:
```html
<!DOCTYPE html>
@ -75,22 +137,30 @@ De to første linjene i en HTML-fil fungerer som dokumentets "introduksjon" til
```
**Forstå hva denne koden gjør:**
- **Deklarerer** dokumenttypen som HTML5 ved å bruke `<!DOCTYPE html>`
- **Oppretter** rootelementet `<html>` som vil inneholde alt sideinnhold
- **Etablerer** moderne webstandarder for korrekt nettleservisning
- **Sikrer** konsistent visning på tvers av forskjellige nettlesere og enheter
- **Deklarerer** dokumenttypen som HTML5 med `<!DOCTYPE html>`
- **Oppretter** rootelementet `<html>` som vil inneholde alt innhold på siden
- **Etablerer** moderne webstandarder for korrekt nettleserrendering
- **Sikrer** jevn visning på tvers av ulike nettlesere og enheter
> 💡 **VS Code tips**: Hold musepekeren over en hvilken som helst HTML-tag i VS Code for å se nyttig informasjon fra MDN Web Docs, inkludert bruker-eksempler og nettleserkompatibilitet.
> 📚 **Lær mer**: DOCTYPE-deklarasjonen hindrer nettlesere i å gå i "quirks mode," som ble brukt for å støtte svært gamle nettsider. Moderne webutvikling bruker den enkle `<!DOCTYPE html>` deklarasjonen for å sikre [standard-kompatibel rendering](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode).
> 💡 **VS Code-tips**: Hold musepekeren over en HTML-tag i VS Code for å se nyttig informasjon fra MDN Web Docs, inkludert eksempler på bruk og nettleserkompatibilitet.
### 🔄 **Pedagogisk sjekk**
**Pause og reflekter**: Før du fortsetter, sørg for at du forstår:
- ✅ Hvorfor hvert HTML-dokument trenger en DOCTYPE-deklarasjon
- ✅ Hva rootelementet `<html>` inneholder
- ✅ Hvordan denne strukturen hjelper nettlesere med å gjengi sidene riktig
> 📚 **Lær mer**: DOCTYPE-deklarasjonen forhindrer nettlesere fra å gå inn i "quirks mode", som ble brukt for å støtte veldig gamle nettsteder. Moderne webutvikling bruker den enkle `<!DOCTYPE html>`-deklarasjonen for å sikre [standardkompatibel visning](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode).
**Rask selvtest**: Kan du forklare med dine egne ord hva "standard-kompatibel rendering" betyr?
## Legge til essensiell dokumentmetadata
`<head>`-seksjonen i et HTML-dokument inneholder viktig informasjon som nettlesere og søkemotorer trenger, men som besøkende ikke ser direkte på siden. Tenk på det som "bak kulissene"-informasjon som hjelper nettsiden din med å fungere riktig og vises korrekt på tvers av forskjellige enheter og plattformer.
`<head>`-delen i et HTML-dokument inneholder viktig informasjon som nettlesere og søkemotorer trenger, men som besøkende ikke ser direkte på siden. Tenk på det som "bak kulissene"-informasjonen som hjelper nettsiden din å fungere riktig og vises korrekt på ulike enheter og plattformer.
Denne metadataen forteller nettlesere hvordan de skal vise siden din, hvilken tegnkoding som skal brukes, og hvordan de skal håndtere forskjellige skjermstørrelser alt essensielt for å lage profesjonelle, tilgjengelige nettsider.
Denne metadataen forteller nettlesere hvordan de skal vise siden, hvilken tegnkoding de skal bruke, og hvordan de skal håndtere ulike skjermstørrelser alt essensielt for å lage profesjonelle, tilgjengelige nettsider.
### Oppgave: Legg til dokumenthodet
### Oppgave: Legg til dokumenthode
Sett inn denne `<head>`-seksjonen mellom dine åpne og lukkede `<html>`-tagger:
@ -103,28 +173,28 @@ Sett inn denne `<head>`-seksjonen mellom dine åpne og lukkede `<html>`-tagger:
</head>
```
**Bryte ned hva hvert element oppnår:**
- **Setter** sidetittelen som vises i nettleserfaner og søkeresultater
- **Spesifiserer** UTF-8 tegnkoding for korrekt tekstvisning over hele verden
**Hva hvert element gjør:**
- **Setter** sidetittel som vises i nettleserfaner og søkeresultater
- **Spesifiserer** UTF-8 tegnkoding for riktig visning av tekst over hele verden
- **Sikrer** kompatibilitet med moderne versjoner av Internet Explorer
- **Konfigurerer** responsivt design ved å sette viewport til å matche enhetens bredde
- **Kontrollerer** startzoomnivå for å vise innhold i naturlig størrelse
- **Konfigurerer** responsivt design ved å sette viewporten til enhetsbredde
- **Kontrollerer** startzoomen for å vise innhold i naturlig størrelse
> 🤔 **Tenk på dette**: Hva ville skje hvis du satte en viewport meta-tag som dette: `<meta name="viewport" content="width=600">`? Dette ville tvinge siden til alltid å være 600 piksler bred, og bryte responsivt design! Lær mer om [korrekt viewport-konfigurasjon](https://developer.mozilla.org/docs/Web/HTML/Viewport_meta_tag).
> 🤔 **Tenk over dette**: Hva ville skjedd hvis du satt en viewport-meta tag som dette: `<meta name="viewport" content="width=600">`? Dette ville tvinge siden til alltid å være 600 piksler bred, og bryte responsivt design! Lær mer om [korrekt viewport-konfigurasjon](https://developer.mozilla.org/docs/Web/HTML/Viewport_meta_tag).
## Bygge dokumentets kropp
`<body>`-elementet inneholder alt synlig innhold på nettsiden din alt brukerne vil se og samhandle med. Mens `<head>`-seksjonen ga instruksjoner til nettleseren, inneholder `<body>`-seksjonen det faktiske innholdet: tekst, bilder, knapper og andre elementer som skaper brukergrensesnittet ditt.
`<body>`-elementet inneholder alt synlig innhold på nettsiden alt brukeren ser og kan interagere med. Mens `<head>`-delen ga instruksjoner til nettleseren, inneholder `<body>` den faktiske innholdet: tekst, bilder, knapper og andre elementer som lager brukergrensesnittet.
La oss legge til kroppstrukturen og forstå hvordan HTML-tagger fungerer sammen for å lage meningsfylt innhold.
La oss legge til kroppens struktur og forstå hvordan HTML-tagger samhandler for å lage meningsfylt innhold.
### Forstå HTML-tagstruktur
### Forstå HTML-taggstruktur
HTML bruker parvise tagger for å definere elementer. De fleste tagger har en åpningstag som `<p>` og en lukkingstag som `</p>`, med innhold imellom: `<p>Hei, verden!</p>`. Dette skaper et avsnittselement som inneholder teksten "Hei, verden!".
HTML bruker parvise tagger for å definere elementer. De fleste tagger har en åpningstagg som `<p>` og en avslutningstagg som `</p>`, med innhold mellom: `<p>Hei, verden!</p>`. Dette lager et paragraf-element som inneholder teksten "Hei, verden!".
### Oppgave: Legg til body-elementet
Oppdater HTML-filen din for å inkludere `<body>`-elementet:
Oppdater HTML-filen din til å inkludere `<body>`-elementet:
```html
<!DOCTYPE html>
@ -139,136 +209,179 @@ Oppdater HTML-filen din for å inkludere `<body>`-elementet:
</html>
```
**Her er hva denne komplette strukturen gir:**
- **Etablerer** det grunnleggende HTML5-dokumentrammeverket
- **Inkluderer** essensiell metadata for korrekt nettleservisning
- **Oppretter** en tom kropp klar for ditt synlige innhold
**Dette gir den komplette strukturen:**
- **Etablerer** det grunnleggende HTML5 dokumentrammeverket
- **Inkluderer** essensiell metadata for korrekt nettleserrendering
- **Lager** en tom kropp klar for synlig innhold
- **Følger** moderne webutviklings beste praksis
Nå er du klar til å legge til de synlige elementene i terrariet ditt. Vi vil bruke `<div>`-elementer som beholdere for å organisere forskjellige seksjoner av innholdet, og `<img>`-elementer for å vise plantebildene.
Nå er du klar til å legge til synlige elementer i terrariet ditt. Vi bruker `<div>`-elementer som beholdere for å organisere forskjellige innholdsseksjoner, og `<img>`-elementer for å vise plantebildene.
### Arbeide med bilder og layoutbeholdere
### Jobbe med bilder og layout-beholdere
Bilder er spesielle i HTML fordi de bruker "selvlukkende" tagger. I motsetning til elementer som `<p></p>` som omslutter innhold, inneholder `<img>`-taggen all informasjon den trenger innenfor selve taggen ved hjelp av attributter som `src` for bildefilstien og `alt` for tilgjengelighet.
Bilder er spesielle i HTML fordi de bruker "selvlukkende" tagger. I motsetning til elementer som `<p></p>` som omslutter innhold, inneholder `<img>`-taggen all nødvendig informasjon innenfor seg selv ved hjelp av attributter som `src` for bildefil-lokasjon og `alt` for tilgjengelighet.
Før du legger til bilder i HTML-en din, må du organisere prosjektfilene dine riktig ved å opprette en bildemappe og legge til plantegrafikken.
Før du legger til bilder i HTML-en din, må du organisere prosjektfilene dine riktig ved å lage en mappe for bilder og legge til plantegrafikkene.
**Først, sett opp bildene dine:**
1. Opprett en mappe kalt `images` inne i terrarium-prosjektmappen din
1. Lag en mappe kalt `images` inne i terrarium-prosjektmappen din
2. Last ned plantebildene fra [løsningsmappen](../../../../3-terrarium/solution/images) (14 plantebilder totalt)
3. Kopier alle plantebildene inn i den nye `images`-mappen din
3. Kopier alle plantebildene over i den nye `images`-mappen
### Oppgave: Lag plantevisningslayouten
### Oppgave: Lag layout for plantevisning
Legg nå til plantebildene organisert i to kolonner mellom `<body></body>`-taggene dine:
Legg nå til plantebildene organisert i to kolonner mellom dine `<body></body>`-tagger:
```html
<div id="page">
<div id="left-container" class="container">
<div class="plant-holder">
<img class="plant" alt="plant" id="plant1" src="../../../../translated_images/plant1.d87946a2ca70cc4316bda6e6c3af7210fbe9ada5539a7885141a9ce0efaf7be3.no.png" />
<img class="plant" alt="plant" id="plant1" src="../../../../translated_images/plant1.d87946a2ca70cc43.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant2" src="../../../../translated_images/plant2.8daa1606c9c1ad896bb171212c7d1d882e504b76b8ec3a2d1c337d775cf50dc3.no.png" />
<img class="plant" alt="plant" id="plant2" src="../../../../translated_images/plant2.8daa1606c9c1ad89.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant3" src="../../../../translated_images/plant3.8b0d484381a2a2a77c5c06ad97ab6ae5b7023da8c6c7678b0183bc0e46ea17a7.no.png" />
<img class="plant" alt="plant" id="plant3" src="../../../../translated_images/plant3.8b0d484381a2a2a7.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant4" src="../../../../translated_images/plant4.656e16ae1df37be2af5f4e7b5ab6c5decc432c3d3ec2eb98b904ddbecad49db0.no.png" />
<img class="plant" alt="plant" id="plant4" src="../../../../translated_images/plant4.656e16ae1df37be2.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant5" src="../../../../translated_images/plant5.2b41b9355f11ebccd62d327f5f14e56531ecda9c6f970bc89e386ee9f0273bb0.no.png" />
<img class="plant" alt="plant" id="plant5" src="../../../../translated_images/plant5.2b41b9355f11ebcc.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant6" src="../../../../translated_images/plant6.3d1827d03b6569946be13ae5da1f32947ae56732638a43757a7c616a6adccc5d.no.png" />
<img class="plant" alt="plant" id="plant6" src="../../../../translated_images/plant6.3d1827d03b656994.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant7" src="../../../../translated_images/plant7.8152c302ac97f621a6c595bdf3939103568f9efc7d3b06a0f02a1ea66f479de0.no.png" />
<img class="plant" alt="plant" id="plant7" src="../../../../translated_images/plant7.8152c302ac97f621.no.png" />
</div>
</div>
<div id="right-container" class="container">
<div class="plant-holder">
<img class="plant" alt="plant" id="plant8" src="../../../../translated_images/plant8.38d6428174ffa850a47cd1b81d528fa528adda7d23f3ae0bb42f4a27356ca5e6.no.png" />
<img class="plant" alt="plant" id="plant8" src="../../../../translated_images/plant8.38d6428174ffa850.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant9" src="../../../../translated_images/plant9.f0e38d3327c37fc29cd2734d48d20c2cf69300898ece6d46708829e02ce540e3.no.png" />
<img class="plant" alt="plant" id="plant9" src="../../../../translated_images/plant9.f0e38d3327c37fc2.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant10" src="../../../../translated_images/plant10.b159d6d6e985595f56d86b4b38061b8e7b4c9969c210c199fe967269cf935e7f.no.png" />
<img class="plant" alt="plant" id="plant10" src="../../../../translated_images/plant10.b159d6d6e985595f.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant11" src="../../../../translated_images/plant11.2a03a1c2ec8ea84ef3a80c06cc6883f3960fbb669f2c0b0bd824ba33d7eb7d32.no.png" />
<img class="plant" alt="plant" id="plant11" src="../../../../translated_images/plant11.2a03a1c2ec8ea84e.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant12" src="../../../../translated_images/plant12.60e9b53e538fbaf3e5797ebf800acb483baf5639e6cf378292ac2321ab8a5ea9.no.png" />
<img class="plant" alt="plant" id="plant12" src="../../../../translated_images/plant12.60e9b53e538fbaf3.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant13" src="../../../../translated_images/plant13.07a51543c820bcf57f67a9a6c0acbd6211ff795e2e67a42a9718224534e95fab.no.png" />
<img class="plant" alt="plant" id="plant13" src="../../../../translated_images/plant13.07a51543c820bcf5.no.png" />
</div>
<div class="plant-holder">
<img class="plant" alt="plant" id="plant14" src="../../../../translated_images/plant14.6e486371ba7d36ba3520d9828887993cb4c3edad8bdd8ff9b1b315717ff8cb63.no.png" />
<img class="plant" alt="plant" id="plant14" src="../../../../translated_images/plant14.6e486371ba7d36ba.no.png" />
</div>
</div>
</div>
```
**Steg for steg, her er hva som skjer i denne koden:**
**Steg for steg, dette skjer i koden:**
- **Oppretter** en hovedsidebeholder med `id="page"` for å holde alt innhold
- **Etablerer** to kolonnebeholdere: `left-container` og `right-container`
- **Organiserer** 7 planter i venstre kolonne og 7 planter i høyre kolonne
- **Omslutter** hvert plantebilde i en `plant-holder` div for individuell plassering
- **Bruker** konsistente klassenavn for CSS-styling i neste leksjon
- **Tildeler** unike ID-er til hvert plantebilde for senere interaksjon med JavaScript
- **Inkluderer** riktige filstier som peker til bildemappen
- **Pakker** hvert plantebilde i en `plant-holder` div for individuell posisjonering
- **Bruker** konsekvente klassenavn for CSS-styling i neste leksjon
- **Tildeler** unike ID-er til hvert plantebilde for JavaScript-interaksjon senere
- **Inkluderer** riktige filbaner som peker til bilder-mappen
> 🤔 **Tenk på dette**: Legg merke til at alle bilder for øyeblikket har samme alt-tekst "plant". Dette er ikke ideelt for tilgjengelighet. Brukere av skjermlesere vil høre "plant" gjentatt 14 ganger uten å vite hvilken spesifikk plante hvert bilde viser. Kan du komme på bedre, mer beskrivende alt-tekst for hvert bilde?
> 🤔 **Tenk over dette**: Legg merke til at alle bildene har samme alternative tekst "plant" akkurat nå. Dette er ikke ideelt for tilgjengelighet. Skjermlesere vil høre "plant" 14 ganger uten å vite hvilke spesifikke planter hvert bilde viser. Kan du tenke deg bedre, mer beskrivende alt-tekster for hvert bilde?
> 📝 **HTML-elementtyper**: `<div>`-elementer er "blokknivå" og tar opp full bredde, mens `<span>`-elementer er "inline" og tar bare opp nødvendig bredde. Hva tror du ville skje hvis du endret alle disse `<div>`-taggene til `<span>`-tagger?
> 📝 **HTML-elementtyper**: `<div>`-elementer er "blokknivå" og tar opp full bredde, mens `<span>`-elementer er "inline" og tar kun opp nødvendig bredde. Hva tror du ville skjedd hvis du endret alle disse `<div>`-taggene til `<span>`-tagger?
Med denne markeringen lagt til, vil plantene vises på skjermen, selv om de ikke ser polerte ut ennå det er det CSS er til for i neste leksjon! For nå har du et solid HTML-grunnlag som organiserer innholdet ditt riktig og følger beste praksis for tilgjengelighet.
### 🔄 **Pedagogisk sjekk**
**Forståelse av struktur**: Ta et øyeblikk til å gjennomgå HTML-strukturen din:
- ✅ Kan du identifisere hovedbeholderne i layouten din?
- ✅ Forstår du hvorfor hvert bilde har en unik ID?
- ✅ Hvordan vil du beskrive formålet til `plant-holder`-divene?
## Bruke semantisk HTML for tilgjengelighet
**Visuell inspeksjon**: Åpne HTML-filen i en nettleser. Du skal se:
- En enkel liste med plantebilder
- Bilder organisert i to kolonner
- Enkel, ustylet layout
Semantisk HTML betyr å velge HTML-elementer basert på deres betydning og formål, ikke bare deres utseende. Når du bruker semantisk markering, kommuniserer du strukturen og betydningen av innholdet ditt til nettlesere, søkemotorer og hjelpemidler som skjermlesere.
**Husk**: Dette enkle utseendet er akkurat hvordan HTML skal se ut før CSS-styling!
Denne tilnærmingen gjør nettstedene dine mer tilgjengelige for brukere med funksjonshemninger og hjelper søkemotorer med å forstå innholdet ditt bedre. Det er et grunnleggende prinsipp for moderne webutvikling som skaper bedre opplevelser for alle.
Med denne markupen lagt til vil plantene vises på skjermen, selv om det ikke ser polert ut ennå det er CSS sin jobb i neste leksjon! For nå har du et solid HTML-grunnlag som ordentlig organiserer innholdet ditt og følger beste praksis for tilgjengelighet.
## Bruke semantisk HTML for tilgjengelighet
Semantisk HTML betyr å velge HTML-elementer basert på deres mening og hensikt, ikke bare utseende. Når du bruker semantisk markup, kommuniserer du struktur og mening av innholdet ditt til nettlesere, søkemotorer og hjelpemidler som skjermlesere.
```mermaid
flowchart TD
A[Trenger å legge til innhold?] --> B{Hvilken type?}
B -->|Hovedoverskrift| C["<h1>"]
B -->|Underoverskrift| D["<h2>, <h3>, osv."]
B -->|Avsnitt| E["<p>"]
B -->|Liste| F["<ul>, <ol>"]
B -->|Navigasjon| G["<nav>"]
B -->|Artikkel| H["<article>"]
B -->|Seksjon| I["<section>"]
B -->|Generisk beholder| J["<div>"]
C --> K[Skjermlesere annonserer som hovedtittel]
D --> L[Oppretter riktig overskriftsrekkefølge]
E --> M[Gir riktig tekstavstand]
F --> N[Muliggjør snarveier for liste-navigasjon]
G --> O[Identifiserer navigasjonslandemerker]
H --> P[Markerer frittstående innhold]
I --> Q[Grupperer relatert innhold]
J --> R[Bruk kun når ingen semantisk tag passer]
style C fill:#4caf50
style D fill:#4caf50
style E fill:#4caf50
style F fill:#4caf50
style G fill:#2196f3
style H fill:#2196f3
style I fill:#2196f3
style J fill:#ff9800
```
Denne tilnærmingen gjør nettstedene dine mer tilgjengelige for brukere med funksjonsnedsettelser og hjelper søkemotorer å bedre forstå innholdet ditt. Det er et grunnleggende prinsipp i moderne webutvikling som skaper bedre opplevelser for alle.
### Legge til en semantisk sidetittel
La oss legge til en ordentlig overskrift på terrariumsiden din. Sett inn denne linjen rett etter den åpne `<body>`-taggen:
La oss legge til en passende overskrift på terrarium-siden din. Sett inn denne linjen rett etter åpningstaggen `<body>`:
```html
<h1>My Terrarium</h1>
```
**Hvorfor semantisk markering er viktig:**
**Hvorfor semantisk markup er viktig:**
- **Hjelper** skjermlesere med å navigere og forstå sidestrukturen
- **Forbedrer** søkemotoroptimalisering (SEO) ved å klargjøre innholdshierarkiet
- **Forbedrer** søkemotoroptimalisering (SEO) ved å klargjøre innholdshierarki
- **Øker** tilgjengeligheten for brukere med synshemninger eller kognitive forskjeller
- **Skaper** bedre brukeropplevelser på tvers av alle enheter og plattformer
- **Skaper** bedre brukeropplevelser på alle enheter og plattformer
- **Følger** webstandarder og beste praksis for profesjonell utvikling
**Eksempler på semantiske vs. ikke-semantiske valg:**
| Formål | ✅ Semantisk valg | ❌ Ikke-semantisk valg |
|--------|------------------|-----------------------|
| Hovedoverskrift | `<h1>Tittel</h1>` | `<div class="big-text">Tittel</div>` |
|---------|-------------------|------------------------|
| Hovedoverskrift | `<h1>Title</h1>` | `<div class="big-text">Title</div>` |
| Navigasjon | `<nav><ul><li></li></ul></nav>` | `<div class="menu"><div></div></div>` |
| Knapp | `<button>Klikk her</button>` | `<span onclick="...">Klikk her</span>` |
| Knapp | `<button>Click me</button>` | `<span onclick="...">Click me</span>` |
| Artikkelinnhold | `<article><p></p></article>` | `<div class="content"><div></div></div>` |
> 🎥 **Se det i aksjon**: Se [hvordan skjermlesere interagerer med nettsider](https://www.youtube.com/watch?v=OUDV1gqs9GA) for å forstå hvorfor semantisk markering er avgjørende for tilgjengelighet. Legg merke til hvordan korrekt HTML-struktur hjelper brukere med å navigere effektivt.
> 🎥 **Se det i praksis**: Se [hvordan skjermlesere interagerer med nettsider](https://www.youtube.com/watch?v=OUDV1gqs9GA) for å forstå hvorfor semantisk markup er avgjørende for tilgjengelighet. Legg merke til hvordan riktig HTML-struktur hjelper brukere å navigere effektivt.
## Lage terrarium-beholderen
La oss nå legge til HTML-strukturen for selve terrariet glassbeholderen der plantene til slutt vil bli plassert. Denne delen demonstrerer et viktig konsept: HTML gir struktur, men uten CSS-styling vil disse elementene ikke være synlige ennå.
Nå skal vi legge til HTML-strukturen for selve terrariet glassbeholderen hvor plantene til slutt vil plasseres. Denne seksjonen demonstrerer et viktig konsept: HTML gir struktur, men uten CSS-styling vil ikke disse elementene være synlige ennå.
Terrarium-markeringen bruker beskrivende klassenavn som vil gjøre CSS-styling intuitiv og vedlikeholdbar i neste leksjon.
Terrarium-markupen bruker beskrivende klassenavn som vil gjøre CSS-stylingen intuitiv og vedlikeholdbar i neste leksjon.
### Oppgave: Legg til terrarium-strukturen
Sett inn denne markeringen over den siste `</div>`-taggen (før den lukkende taggen til sidebeholderen):
Sett inn denne markupen over den siste `</div>`-taggen (før avslutningstaggen til sidebeholderen):
```html
<div id="terrarium">
@ -283,13 +396,41 @@ Sett inn denne markeringen over den siste `</div>`-taggen (før den lukkende tag
```
**Forstå denne terrarium-strukturen:**
- **Oppretter** en hovedterrarium-beholder med en unik ID for styling
- **Oppretter** en hovedterrarium-beholder med en unik ID for styling
- **Definerer** separate elementer for hver visuell komponent (topp, vegger, jord, bunn)
- **Inkluderer** nestede elementer for glasseffekter (glansfulle elementer)
- **Bruker** beskrivende klassenavn som tydelig indikerer hvert elements formål
- **Forbereder** strukturen for CSS-styling som vil skape glass-terrarium-utseendet
- **Inkluderer** nestede elementer for glassrefleksjonseffekter (glinsende elementer)
- **Bruker** beskrivende klassenavn som klart indikerer hvert elements formål
- **Forbereder** strukturen for CSS-styling som vil skape terrariets glassutseende
> 🤔 **Merker du noe?**: Selv om du la til denne markupen, ser du ingenting nytt på siden! Dette illustrerer perfekt hvordan HTML gir struktur mens CSS gir utseende. Disse `<div>`-elementene eksisterer, men har ingen visuell styling ennå det kommer i neste leksjon!
```mermaid
flowchart TD
A[HTML-dokument] --> B[Dokumenthode]
A --> C[Dokumentkropp]
B --> D[Titelelement]
B --> E[Meta-tegnsett]
B --> F[Meta-visningsvindu]
C --> G[Hovedoverskrift]
C --> H[Sidebeholder]
H --> I[Vennebeholder med 7 planter]
H --> J[Høyre beholder med 7 planter]
H --> K[Terrariumstruktur]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#e8f5e8
style H fill:#f3e5f5
```
### 🔄 **Pedagogisk innsjekking**
**Beherskelse av HTML-struktur**: Før du går videre, sørg for at du kan:
- ✅ Forklare forskjellen mellom HTML-struktur og visuelt utseende
- ✅ Identifisere semantiske vs. ikke-semantiske HTML-elementer
- ✅ Beskrive hvordan riktig markup gagner tilgjengelighet
- ✅ Gjenkjenne dokumenttreets fullstendige struktur
> 🤔 **Legg merke til noe?**: Selv om du la til denne markeringen, ser du ikke noe nytt på siden! Dette illustrerer perfekt hvordan HTML gir struktur mens CSS gir utseende. Disse `<div>`-elementene eksisterer, men har ingen visuell styling ennå det kommer i neste leksjon!
**Test din forståelse**: Prøv å åpne HTML-filen i en nettleser med JavaScript deaktivert og CSS fjernet. Dette viser den rene semantiske strukturen du har laget!
---
@ -297,69 +438,160 @@ Sett inn denne markeringen over den siste `</div>`-taggen (før den lukkende tag
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Lag en semantisk HTML-struktur for en plantepleieveiledning som kan legges til terrarium-prosjektet.
**Prompt:** Lag en semantisk HTML-seksjon som inkluderer en hovedoverskrift "Plant Care Guide", tre underseksjoner med overskriftene "Watering", "Light Requirements" og "Soil Care", hver med et avsnitt med informasjon om plantepleie. Bruk riktige semantiske HTML-tagger som `<section>`, `<h2>`, `<h3>` og `<p>` for å strukturere innholdet på en passende måte.
**Beskrivelse:** Lag en semantisk HTML-struktur for en seksjon om plantepleie som kan legges til terrarium-prosjektet.
**Oppgave:** Lag en semantisk HTML-seksjon som inkluderer en hovedoverskrift "Plant Care Guide", tre underseksjoner med overskrifter "Watering", "Light Requirements" og "Soil Care", hver med et avsnitt med informasjon om plantepleie. Bruk riktige semantiske HTML-tagger som `<section>`, `<h2>`, `<h3>`, og `<p>` for å strukturere innholdet passende.
Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## Utforsk HTML-historieutfordring
## Utforsk HTML-historie-utfordring
**Lær om webutviklingens evolusjon**
**Lær om webutviklingen**
HTML har utviklet seg betydelig siden Tim Berners-Lee skapte den første nettleseren ved CERN i 1990. Noen eldre tagger som `<marquee>` er nå avviklet fordi de ikke fungerer godt med moderne tilgjengelighetsstandarder og prinsipper for responsiv design.
HTML har utviklet seg betydelig siden Tim Berners-Lee laget den første nettleseren på CERN i 1990. Noen eldre tagger som `<marquee>` er nå foreldet fordi de ikke fungerer godt med moderne tilgjengelighetsstandarder og prinsipper for responsivt design.
**Prøv dette eksperimentet:**
1. Pakk midlertidig inn din `<h1>`-tittel i en `<marquee>`-tag: `<marquee><h1>My Terrarium</h1></marquee>`
2. Åpne siden din i en nettleser og observer rulleffekten
3. Reflekter over hvorfor denne taggen ble avviklet (hint: tenk på brukeropplevelse og tilgjengelighet)
4. Fjern `<marquee>`-taggen og gå tilbake til semantisk oppmerking
1. Pakk midlertidig inn `<h1>`-tittelen din i en `<marquee>`-tagg: `<marquee><h1>My Terrarium</h1></marquee>`
2. Åpne siden i en nettleser og observer rulleffekten
3. Tenk over hvorfor denne taggen ble avviklet (tips: tenk på brukeropplevelse og tilgjengelighet)
4. Fjern `<marquee>`-taggen og gå tilbake til semantisk markup
**Refleksjonsspørsmål:**
- Hvordan kan en rullende tittel påvirke brukere med synshemming eller følsomhet for bevegelse?
- Hvordan kan en rullende tittel påvirke brukere med synshemming eller bevegelsesfølsomhet?
- Hvilke moderne CSS-teknikker kan oppnå lignende visuelle effekter på en mer tilgjengelig måte?
- Hvorfor er det viktig å bruke gjeldende webstandarder i stedet for avviklede elementer?
- Hvorfor er det viktig å bruke dagens webstandarder i stedet for foreldede elementer?
Utforsk mer om [utgåtte og avviklede HTML-elementer](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements) for å forstå hvordan webstandarder utvikler seg for å forbedre brukeropplevelsen.
Utforsk mer om [utdaterte og foreldede HTML-elementer](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements) for å forstå hvordan webstandarder utvikler seg for å forbedre brukeropplevelsen.
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/16)
## Gjennomgang og selvstudium
## Gjennomgang og Selvstudium
**Fordyp deg i HTML-kunnskap**
HTML har vært grunnlaget for nettet i over 30 år, og har utviklet seg fra et enkelt dokumentmarkeringsspråk til en sofistikert plattform for å bygge interaktive applikasjoner. Å forstå denne utviklingen hjelper deg med å sette pris på moderne webstandarder og ta bedre utviklingsbeslutninger.
HTML har vært grunnlaget for nettet i over 30 år, og har utviklet seg fra et enkelt dokumentmarkeringsspråk til en sofistikert plattform for å bygge interaktive applikasjoner. Å forstå denne utviklingen hjelper deg å sette pris på moderne webstandarder og ta bedre utviklingsvalg.
**Anbefalte læringsveier:**
1. **HTML-historie og evolusjon**
1. **HTML-historie og utvikling**
- Undersøk tidslinjen fra HTML 1.0 til HTML5
- Utforsk hvorfor visse tagger ble avviklet (tilgjengelighet, mobilvennlighet, vedlikeholdbarhet)
- Utforsk hvorfor enkelte tagger ble avviklet (tilgjengelighet, mobilvennlighet, vedlikeholdbarhet)
- Undersøk nye HTML-funksjoner og forslag
2. **Dypdykk i semantisk HTML**
- Studer den komplette listen over [HTML5 semantiske elementer](https://developer.mozilla.org/docs/Web/HTML/Element)
- Øv på å identifisere når du skal bruke `<article>`, `<section>`, `<aside>` og `<main>`
- Studer den fullstendige listen over [HTML5 semantiske elementer](https://developer.mozilla.org/docs/Web/HTML/Element)
- Øv på å identifisere når du skal bruke `<article>`, `<section>`, `<aside>`, og `<main>`
- Lær om ARIA-attributter for forbedret tilgjengelighet
3. **Moderne webutvikling**
- Utforsk [bygging av responsive nettsteder](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon) på Microsoft Learn
- Utforsk [å bygge responsive nettsteder](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon) på Microsoft Learn
- Forstå hvordan HTML integreres med CSS og JavaScript
- Lær om webytelse og SEO beste praksis
**Refleksjonsspørsmål:**
- Hvilke avviklede HTML-tagger oppdaget du, og hvorfor ble de fjernet?
- Hvilke nye HTML-funksjoner blir foreslått for fremtidige versjoner?
- Hvilke foreldede HTML-tagger oppdaget du, og hvorfor ble de fjernet?
- Hvilke nye HTML-funksjoner foreslås for fremtidige versjoner?
- Hvordan bidrar semantisk HTML til webtilgjengelighet og SEO?
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Åpne DevTools (F12) og inspiser HTML-strukturen til ditt favorittnettsted
- [ ] Lag en enkel HTML-fil med grunnleggende tagger: `<h1>`, `<p>`, og `<img>`
- [ ] Valider HTML-en din med W3C HTML Validator online
- [ ] Prøv å legge til en kommentar i HTML-en din med `<!-- comment -->`
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør quizen etter leksjonen og gå gjennom semantiske HTML-konsepter
- [ ] Lag en enkel nettside om deg selv med korrekt HTML-struktur
- [ ] Eksperimenter med forskjellige overskriftsnivåer og tekstformateringstags
- [ ] Legg til bilder og lenker for å øve på multimedia-integrering
- [ ] Undersøk HTML5-funksjoner du ikke har prøvd ennå
### 📅 **Din ukelange HTML-reise**
- [ ] Fullfør terrarium-prosjektoppgaven med semantisk markup
- [ ] Lag en tilgjengelig nettside med ARIA-labels og roller
- [ ] Øv på å lage skjemaer med ulike input-typer
- [ ] Utforsk HTML5 API-er som localStorage eller geolokasjon
- [ ] Studer responsive HTML-mønstre og mobil-først design
- [ ] Gå gjennom andres HTML-kode for god praksis
### 🌟 **Din månedslange webplattform**
- [ ] Lag en porteføljenettside som viser din HTML-ekspertise
- [ ] Lær HTML-templating med et rammeverk som Handlebars
- [ ] Bidra til open source-prosjekter ved å forbedre HTML-dokumentasjon
- [ ] Mestre avanserte HTML-konsepter som egendefinerte elementer
- [ ] Integrer HTML med CSS-rammeverk og JavaScript-biblioteker
- [ ] Veilede andre som lærer HTML-grunnleggende
## 🎯 Din HTML-mester-tidslinje
```mermaid
timeline
title HTML Læringsprogresjon
section Grunnlag (5 minutter)
Dokumentstruktur: DOCTYPE-deklarasjon
: HTML-rot element
: Forståelse av Head vs Body
section Metadata (10 minutter)
Essensielle Meta-tagger: Tegnkoding
: Viewport-konfigurasjon
: Nettleserkompatibilitet
section Innholdsproduksjon (15 minutter)
Bildeintegrasjon: Korrekte filstier
: Viktigheten av alt-tekst
: Selv-lukkende tagger
section Layoutorganisering (20 minutter)
Container-strategi: Div-elementer for struktur
: Klasse- og ID-navngivning
: Nestede elementhierarki
section Semantisk Mestring (30 minutter)
Meningsfull markup: Overskriftshierarki
: Navigasjon for skjermlesere
: Beste praksis for tilgjengelighet
section Avanserte Konsepter (1 time)
HTML5-funksjoner: Moderne semantiske elementer
: ARIA-attributter
: Ytelsesvurderinger
section Profesjonelle Ferdigheter (1 uke)
Kodeorganisering: Filstrukturmønstre
: Vedlikeholdbar markup
: Team-samarbeid
section Ekspertnivå (1 måned)
Moderne Nettstandarder: Progressiv forbedring
: Kryss-nettleser kompatibilitet
: Oppdateringer i HTML-spesifikasjonen
```
### 🛠️ Ditt HTML-verktøysettoppsummering
Etter å ha fullført denne leksjonen har du nå:
- **Dokumentstruktur**: Fullstendig HTML5-grunnlag med korrekt DOCTYPE
- **Semantisk markup**: Meningsfulle tagger som forbedrer tilgjengelighet og SEO
- **Bildeintegrasjon**: Riktig filorganisering og alt-tekst praksis
- **Layout-containere**: Strategisk bruk av div-er med beskrivende klassenavn
- **Tilgjengelighetsbevissthet**: Forståelse for skjermlesernavigasjon
- **Moderne standarder**: Nåværende HTML5-praksis og kunnskap om foreldede tagger
- **Prosjektgrunnlag**: Solid basis for CSS-styling og JavaScript-interaktivitet
**Neste steg**: Din HTML-struktur er klar for CSS-styling! Det semantiske fundamentet du har bygget vil gjøre neste leksjon mye enklere å forstå.
## Oppgave
[Øv på HTML: Bygg en bloggmockup](assignment.md)
[Øv deg på HTML: Lag en blogg-mockup](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi tilstreber nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettingstjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på originalspråket skal betraktes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,87 +1,141 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "92c4431eac70670b0450b02c1d11279a",
"translation_date": "2025-10-23T22:28:19+00:00",
"original_hash": "e39f3a4e3bcccf94639e3af1248f8a4d",
"translation_date": "2026-01-07T00:52:30+00:00",
"source_file": "3-terrarium/2-intro-to-css/README.md",
"language_code": "no"
}
-->
# Terrarium Prosjekt Del 2: Introduksjon til CSS
![Introduksjon til CSS](../../../../translated_images/webdev101-css.3f7af5991bf53a200d79e7257e5e450408d8ea97f5b531d31b2e3976317338ee.no.png)
# Terrarium-prosjekt Del 2: Introduksjon til CSS
```mermaid
journey
title Din CSS-stilreise
section Grunnlag
Koble til CSS-fil: 3: Student
Forstå kaskade: 4: Student
Lær arv: 4: Student
section Selektorer
Målrett elementer: 4: Student
Klassemønstre: 5: Student
ID-spesifisitet: 5: Student
section Oppsett
Plasser elementer: 4: Student
Lag containere: 5: Student
Bygg terrarium: 5: Student
section Polering
Legg til visuelle effekter: 5: Student
Responsivt design: 5: Student
Glassrefleksjoner: 5: Student
```
![Introduksjon til CSS](../../../../translated_images/webdev101-css.3f7af5991bf53a20.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
Husker du hvordan HTML-terrariumet ditt så ganske enkelt ut? CSS er der vi forvandler den enkle strukturen til noe visuelt tiltalende.
Hvis HTML er som å bygge rammen til et hus, er CSS alt som får det til å føles som et hjem malingsfarger, møblering, belysning og hvordan rommene flyter sammen. Tenk på hvordan Versailles-palasset startet som en enkel jaktlodge, men nøye oppmerksomhet til dekorasjon og layout forvandlet det til en av verdens mest praktfulle bygninger.
I dag skal vi forvandle terrariumet ditt fra funksjonelt til polert. Du vil lære hvordan du posisjonerer elementer presist, lager layout som tilpasser seg ulike skjermstørrelser, og skaper den visuelle appellen som gjør nettsteder engasjerende.
Ved slutten av denne leksjonen vil du se hvordan strategisk CSS-styling kan forbedre prosjektet ditt dramatisk. La oss legge til litt stil i terrariumet ditt.
## Quiz før forelesning
Husker du hvordan HTML-terrariet ditt så ganske enkelt ut? CSS er der vi forvandler den enkle strukturen til noe visuelt tiltalende.
Hvis HTML er som å bygge rammen til et hus, så er CSS alt som får det til å føles som hjemme malingsfarger, møblering, belysning og hvordan rommene flyter sammen. Tenk på hvordan Versailles-palasset startet som en enkel jakthytte, men nøye oppmerksomhet på dekorasjon og layout forvandlet det til en av verdens mest praktfulle bygninger.
I dag skal vi forvandle terrariet ditt fra funksjonelt til polert. Du vil lære hvordan du plasserer elementer presist, får oppsett til å tilpasse seg forskjellige skjermstørrelser, og skaper det visuelle uttrykket som gjør nettsider engasjerende.
Ved slutten av denne leksjonen vil du se hvordan strategisk CSS-styling dramatisk kan forbedre prosjektet ditt. La oss tilføre litt stil til terrariet ditt.
```mermaid
mindmap
root((CSS Grunnleggende))
Cascade
Specificity Regler
Arv
Prioritetsrekkefølge
Konfliktløsning
Selectors
Elementetiketter
Klasser (.class)
IDer (#id)
Kombinatorer
Box Model
Margin
Border
Padding
Innhold
Layout
Posisjonering
Visningstyper
Flexbox
Grid
Visual Effects
Farger
Skygger
Overganger
Animasjoner
Responsive Design
Mediespørringer
Fleksible Enheter
Viewport Meta
Mobil Først
```
## Forhåndsquiz
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/17)
[Forhåndsquiz](https://ff-quizzes.netlify.app/web/quiz/17)
## Komme i gang med CSS
CSS blir ofte sett på som bare "å gjøre ting pene," men det har et mye bredere formål. CSS er som å være regissør for en film du kontrollerer ikke bare hvordan alt ser ut, men også hvordan det beveger seg, reagerer på interaksjon og tilpasser seg ulike situasjoner.
CSS blir ofte sett på som bare «å gjøre ting pene», men det har et mye bredere formål. CSS er som å være regissør for en film du kontrollerer ikke bare hvordan alt ser ut, men også hvordan det beveger seg, reagerer på interaksjon, og tilpasser seg ulike situasjoner.
Moderne CSS er utrolig kapabel. Du kan skrive kode som automatisk justerer layout for telefoner, nettbrett og stasjonære datamaskiner. Du kan lage jevne animasjoner som guider brukernes oppmerksomhet dit det trengs. Resultatene kan være ganske imponerende når alt fungerer sammen.
Moderne CSS er bemerkelsesverdig kapabel. Du kan skrive kode som automatisk justerer oppsett for telefoner, nettbrett og stasjonære datamaskiner. Du kan lage glatte animasjoner som leder brukerens oppmerksomhet dit det trengs. Resultatene kan være ganske imponerende når alt fungerer sammen.
> 💡 **Proff-tips**: CSS utvikler seg stadig med nye funksjoner og kapabiliteter. Sjekk alltid [CanIUse.com](https://caniuse.com) for å verifisere nettleserstøtte for nyere CSS-funksjoner før du bruker dem i produksjonsprosjekter.
> 💡 **Profftips**: CSS utvikler seg stadig med nye funksjoner og muligheter. Sjekk alltid [CanIUse.com](https://caniuse.com) for å verifisere nettleserstøtte for nyere CSS-funksjoner før du bruker dem i produksjonsprosjekter.
**Dette skal vi oppnå i denne leksjonen:**
- **Skaper** et komplett visuelt design for terrariumet ditt ved hjelp av moderne CSS-teknikker
- **Utforsker** grunnleggende konsepter som kaskade, arv og CSS-selektorer
- **Implementerer** responsive posisjonerings- og layoutstrategier
- **Bygger** terrariumbeholderen ved hjelp av CSS-former og styling
- **Skaper** et komplett visuelt design for terrariet ditt med moderne CSS-teknikker
- **Utforsker** grunnleggende konsepter som kaskade, arv og CSS-velgere
- **Implementerer** responsiv posisjonering og oppsettsstrategier
- **Bygger** terrariets beholder ved bruk av CSS-former og styling
### Forutsetning
Du bør ha fullført HTML-strukturen for terrariumet ditt fra forrige leksjon og ha det klart til å styles.
Du bør ha fullført HTML-strukturen for terrariet ditt fra forrige leksjon og ha det klart til styling.
> 📺 **Videoressurs**: Sjekk ut denne nyttige videoen
>
> [![CSS Grunnleggende Tutorial](https://img.youtube.com/vi/6yIdOIV9p1I/0.jpg)](https://www.youtube.com/watch?v=6yIdOIV9p1I)
> [![CSS Basics Tutorial](https://img.youtube.com/vi/6yIdOIV9p1I/0.jpg)](https://www.youtube.com/watch?v=6yIdOIV9p1I)
### Sette opp CSS-filen din
Før vi kan begynne å style, må vi koble CSS til HTML-en vår. Denne koblingen forteller nettleseren hvor den finner stylinginstruksjonene for terrariumet vårt.
Før vi kan starte med styling, må vi koble CSS til HTML-en vår. Denne forbindelsen forteller nettleseren hvor stylinginstruksjonene for terrariet vårt finnes.
I terrarium-mappen din, opprett en ny fil kalt `style.css`, og koble den deretter til HTML-dokumentets `<head>`-seksjon:
I terrarimappen din lager du en ny fil kalt `style.css`, så lenker du til den i `<head>`-delen av HTML-dokumentet ditt:
```html
<link rel="stylesheet" href="./style.css" />
```
**Dette gjør koden:**
- **Oppretter** en kobling mellom HTML- og CSS-filene dine
- **Oppretter** en forbindelse mellom HTML- og CSS-filene dine
- **Forteller** nettleseren å laste og bruke stilene fra `style.css`
- **Bruker** attributtet `rel="stylesheet"` for å spesifisere at dette er en CSS-fil
- **Refererer** til filbanen med `href="./style.css"`
- **Refererer** filbanen med `href="./style.css"`
## Forstå CSS-kaskaden
## Forståelse av CSS-kaskaden
Har du noen gang lurt på hvorfor CSS kalles "Cascading" Style Sheets? Stiler kaskader ned som et fossefall, og noen ganger kommer de i konflikt med hverandre.
Har du noen gang lurt på hvorfor CSS heter "Cascading Style Sheets"? Stiler faller som et fossestryk, og noen ganger kommer de i konflikt med hverandre.
Tenk på hvordan militære kommandostrukturer fungerer en generell ordre kan si "alle tropper skal ha på seg grønt," men en spesifikk ordre til enheten din kan si "ha på deg blå uniform til seremonien." Den mer spesifikke instruksjonen har forrang. CSS følger lignende logikk, og å forstå denne hierarkien gjør feilsøking mye enklere.
Tenk på hvordan militære kommandostrukturer fungerer en generalordre kan si "alle tropper skal bære grønt," men en spesifikk ordre til din enhet kan si "bruk dressblått til seremonien." Den mer spesifikke instruksen går foran. CSS følger lignende logikk, og å forstå denne hierarkien gjør feilsøking mye enklere.
### Eksperimentere med kaskadeprioritet
La oss se kaskaden i aksjon ved å lage en stilkonflikt. Først, legg til en inline-stil i `<h1>`-taggen din:
La oss se kaskaden i aksjon ved å skape en stilkonflikt. Først, legg til en inline-stil på `<h1>`-taggen din:
```html
<h1 style="color: red">My Terrarium</h1>
```
**Hva denne koden gjør:**
- **Bruker** en rød farge direkte på `<h1>`-elementet ved hjelp av inline-styling
- **Bruker** attributtet `style` for å legge inn CSS direkte i HTML
- **Oppretter** den høyeste prioriteten for stilregelen for dette spesifikke elementet
**Dette gjør koden:**
- **Setter** fargen rød direkte på `<h1>`-elementet ved bruk av inline-style
- **Bruker** `style`-attributtet for å legge CSS direkte inn i HTML-en
- **Skaper** stilen med høyest prioritet for dette spesifikke elementet
Legg deretter til denne regelen i `style.css`-filen din:
Neste, legg denne regelen til `style.css`-filen din:
```css
h1 {
@ -89,29 +143,50 @@ h1 {
}
```
**I det ovennevnte har vi:**
- **Definert** en CSS-regel som retter seg mot alle `<h1>`-elementer
- **Satt** tekstfargen til blå ved hjelp av et eksternt stilark
- **Opprettet** en lavere prioritet regel sammenlignet med inline-stiler
**Kunnskapssjekk**: Hvilken farge vises i webappen din? Hvorfor vinner den fargen? Kan du tenke på scenarier der du kanskje vil overstyre stiler?
> 💡 **CSS-prioritetsrekkefølge (høyest til lavest):**
> 1. **Inline-stiler** (style-attributt)
**Her har vi:**
- **Definert** en CSS-regel som målretter alle `<h1>`-elementene
- **Satt** tekstfargen til blå via et eksternt stylesheet
- **Laget** en regel med lavere prioritet sammenlignet med inline-stiler
**Kunnskapssjekk**: Hvilken farge vises i webappen din? Hvorfor vinner den fargen? Kan du tenke deg situasjoner hvor det kan være ønskelig å overstyre stiler?
```mermaid
flowchart TD
A["Nettleser møter h1-element"] --> B{"Sjekk for inline-stiler"}
B -->|Funnet| C["style='color: red'"]
B -->|Ingen| D{"Sjekk for ID-regler"}
C --> E["Bruk rød farge (1000 poeng)"]
D -->|Funnet| F["#heading { color: green }"]
D -->|Ingen| G{"Sjekk for klasse-regler"}
F --> H["Bruk grønn farge (100 poeng)"]
G -->|Funnet| I[".title { color: blue }"]
G -->|Ingen| J{"Sjekk element-regler"}
I --> K["Bruk blå farge (10 poeng)"]
J -->|Funnet| L["h1 { color: purple }"]
J -->|Ingen| M["Bruk nettleserstandard"]
L --> N["Bruk lilla farge (1 poeng)"]
style C fill:#ff6b6b
style F fill:#51cf66
style I fill:#339af0
style L fill:#9775fa
```
> 💡 **CSS prioriteringsrekkefølge (høyest til lavest):**
> 1. **Inline-stiler** (style-attributtet)
> 2. **ID-er** (#myId)
> 3. **Klasser** (.myClass) og attributter
> 4. **Element-selektorer** (h1, div, p)
> 5. **Nettleserens standardinnstillinger**
> 4. **Elementvelgere** (h1, div, p)
> 5. **Nettleserstandarder**
## CSS-arv i praksis
CSS-arv fungerer som genetikk elementer arver visse egenskaper fra sine overordnede elementer. Hvis du setter fontfamilien på body-elementet, bruker all tekst inni automatisk den samme fonten. Det er som hvordan Habsburg-familiens karakteristiske kjeve dukket opp gjennom generasjoner uten å bli spesifisert for hver enkelt.
CSS-arv fungerer som genetikk elementer arver visse egenskaper fra sine overordnede elementer. Hvis du setter fontfamilien på `<body>`-elementet, bruker all tekst innenfor automatisk den samme fonten. Det er likt hvordan Habsburg-familiens karakteristiske kjeveform dukket opp over flere generasjoner uten at det var spesifisert for hver enkelt.
Men ikke alt blir arvet. Tekststiler som fonter og farger blir arvet, men layoutegenskaper som marginer og grenser blir ikke. Akkurat som barn kan arve fysiske trekk, men ikke foreldrenes klesvalg.
Men ikke alt blir arvet. Tekststiler som fonter og farger arves, men oppsetts-egenskaper som marger og rammer gjør ikke det. Akkurat som barn kan arve fysiske trekk, men ikke foreldrenes motepreferanser.
### Observere fontarv
### Se på font-arv
La oss se arv i aksjon ved å sette en fontfamilie på `<body>`-elementet:
La oss se arv i praksis ved å sette en fontfamilie på `<body>`-elementet:
```css
body {
@ -119,31 +194,46 @@ body {
}
```
**Bryte ned hva som skjer her:**
- **Setter** fontfamilien for hele siden ved å rette seg mot `<body>`-elementet
- **Bruker** en fontstabel med reservealternativer for bedre nettleserkompatibilitet
- **Bruker** moderne systemfonter som ser flotte ut på tvers av ulike operativsystemer
- **Sikrer** at alle barnelementer arver denne fonten med mindre det spesifikt overstyres
**Hva som skjer her:**
- **Setter** fontfamilien for hele siden ved å målrette `<body>`
- **Bruker** en font-stack med fallback-alternativer for bedre kompatibilitet i nettlesere
- **Benytter** moderne systemfonter som ser bra ut på ulike operativsystemer
- **Sikrer** at alle underordnede elementer arver denne fonten med mindre det overstyres eksplisitt
Åpne nettleserens utviklerverktøy (F12), naviger til Elements-fanen, og inspiser `<h1>`-elementet ditt. Du vil se at det arver fontfamilien fra body:
Åpne nettleserens utviklerverktøy (F12), gå til Elementer-fanen, og inspiser `<h1>`-elementet ditt. Du vil se at det arver fontfamilien fra body:
![arvet font](../../../../translated_images/1.cc07a5cbe114ad1d4728c35134584ac1b87db688eff83cf75985cf31fe0ed95c.no.png)
![arvet font](../../../../translated_images/1.cc07a5cbe114ad1d.no.png)
**Eksperimenttid**: Prøv å sette andre arvelige egenskaper på `<body>` som `color`, `line-height` eller `text-align`. Hva skjer med overskriften din og andre elementer?
**Eksperimenter**: Prøv å sette andre arvelige egenskaper på `<body>` som `color`, `line-height` eller `text-align`. Hva skjer med overskriften og andre elementer?
> 📝 **Arvelige egenskaper inkluderer**: `color`, `font-family`, `font-size`, `line-height`, `text-align`, `visibility`
>
> **Ikke-arvelige egenskaper inkluderer**: `margin`, `padding`, `border`, `width`, `height`, `position`
## Mestre CSS-selektorer
### 🔄 **Pedagogisk sjekk**
**Forståelse av CSS-grunnlag**: Før du går videre til velgere, bør du kunne:
- ✅ Forklare forskjellen mellom kaskade og arv
- ✅ Forutsi hvilken stil som vil vinne i en spesifisitetskonflikt
- ✅ Identifisere hvilke egenskaper som arves fra foreldreelementer
- ✅ Koble CSS-filer korrekt til HTML
CSS-selektorer er din måte å rette seg mot spesifikke elementer for styling. De fungerer som å gi presise retninger i stedet for å si "huset," kan du si "det blå huset med den røde døren på Maple Street."
**Rask test**: Hvis du har disse stilene, hvilken farge får et `<h1>` inne i en `<div class="special">`?
```css
div { color: blue; }
.special { color: green; }
h1 { color: red; }
```
*Svar: Rød (elementvelgeren retter seg direkte mot h1)*
CSS gir ulike måter å være spesifikk på, og å velge riktig selektor er som å velge det passende verktøyet for oppgaven. Noen ganger trenger du å style hver dør i nabolaget, og noen ganger bare én spesifikk dør.
## Mestre CSS-velgere
### Element-selektorer (Tagger)
CSS-velgere er måten du målretter bestemte elementer for styling. De fungerer som å gi presise anvisninger i stedet for å si "huset", kan du si "det blå huset med den røde døren i Maple Street."
Element-selektorer retter seg mot HTML-elementer etter taggnavn. De er perfekte for å sette grunnleggende stiler som gjelder bredt over siden din:
CSS tilbyr ulike måter å være spesifikk på, og det å velge riktig velger er som å velge det riktige verktøyet for en oppgave. Noen ganger må du style hver dør i nabolaget, andre ganger bare én bestemt dør.
### Elementvelgere (Tagger)
Elementvelgere målretter HTML-elementer etter taggnavn. De er perfekte for å sette grunnleggende stiler som gjelder over hele siden:
```css
body {
@ -161,18 +251,18 @@ h1 {
```
**Forstå disse stilene:**
- **Setter** konsistent typografi over hele siden med `body`-selektoren
- **Fjerner** standard nettlesermarginer og padding for bedre kontroll
- **Styler** alle overskriftselementer med farge, justering og avstand
- **Bruker** `rem`-enheter for skalerbar, tilgjengelig fontstørrelse
- **Setter** konsekvent typografi på hele siden med `body`-velgeren
- **Fjerner** nettleserens standard marger og padding for bedre kontroll
- **Styler** alle overskriftselementene med farge, justering og avstand
- **Bruker** `rem`-enheter for skalerbar og tilgjengelig fontstørrelse
Mens element-selektorer fungerer godt for generell styling, trenger du mer spesifikke selektorer for å style individuelle komponenter som plantene i terrariumet ditt.
Selv om elementvelgere fungerer godt for generell styling, trenger du mer spesifikke velgere for å style individuelle komponenter som plantene i terrariet ditt.
### ID-selektorer for unike elementer
### ID-velgere for unike elementer
ID-selektorer bruker symbolet `#` og retter seg mot elementer med spesifikke `id`-attributter. Siden ID-er må være unike på en side, er de perfekte for å style individuelle, spesielle elementer som våre venstre og høyre plantebeholdere.
ID-velgere bruker `#`-symbolet og målretter elementer med spesifikke `id`-attributter. Siden ID-er må være unike på en side, er de perfekte for å style individuelle, spesielle elementer som beholderne for venstre og høyre plante.
La oss lage stylingen for terrariumets sidebeholdere der plantene skal bo:
La oss lage styling for terrariets sidebeholdere hvor plantene skal bo:
```css
#left-container {
@ -199,13 +289,13 @@ La oss lage stylingen for terrariumets sidebeholdere der plantene skal bo:
```
**Dette oppnår koden:**
- **Posisjonerer** beholdere ved de ytterste venstre og høyre kantene ved hjelp av `absolute` posisjonering
- **Bruker** `vh` (viewport height) enheter for responsiv høyde som tilpasser seg skjermstørrelse
- **Bruker** `box-sizing: border-box` slik at padding inkluderes i totalbredden
- **Plasserer** beholdere helt til venstre og høyre ved bruk av `absolute` posisjonering
- **Bruker** `vh` (viewport height)-enheter for responsiv høyde som tilpasser seg skjermstørrelsen
- **Setter** `box-sizing: border-box` slik at padding inkluderes i total bredde
- **Fjerner** unødvendige `px`-enheter fra nullverdier for renere kode
- **Setter** en subtil bakgrunnsfarge som er mer behagelig for øynene enn skarp grå
- **Setter** en subtil bakgrunnsfarge som er mer behagelig for øynene enn en skarp grå
**Kodekvalitetsutfordring**: Legg merke til hvordan denne CSS-en bryter DRY (Don't Repeat Yourself)-prinsippet. Kan du refaktorere den ved å bruke både en ID og en klasse?
**Kodekvalitetsutfordring**: Legg merke til at denne CSS-en bryter med DRY-prinsippet (Don't Repeat Yourself). Kan du refaktorere den ved å bruke både ID og klasse?
**Forbedret tilnærming:**
```html
@ -233,22 +323,22 @@ La oss lage stylingen for terrariumets sidebeholdere der plantene skal bo:
}
```
### Klasse-selektorer for gjenbrukbare stiler
### Klassevelgere for gjenbrukbare stiler
Klasse-selektorer bruker symbolet `.` og er perfekte når du vil bruke de samme stilene på flere elementer. I motsetning til ID-er kan klasser gjenbrukes gjennom hele HTML-en din, noe som gjør dem ideelle for konsistente stylingsmønstre.
Klassevelgere bruker `.`-symbolet og er perfekte når du vil bruke de samme stilene på flere elementer. I motsetning til ID-er kan klasser gjenbrukes over hele HTML-en, noe som gjør dem ideelle for konsistente stilmønstre.
I terrariumet vårt trenger hver plante lignende styling, men også individuell posisjonering. Vi vil bruke en kombinasjon av klasser for delte stiler og ID-er for unik posisjonering.
I terrariet vårt trenger hver plante lignende styling, men også individuell posisjonering. Vi vil bruke en kombinasjon av klasser for felles stiler og ID-er for unik posisjonering.
**Her er HTML-strukturen for hver plante:**
```html
<div class="plant-holder">
<img class="plant" alt="Decorative plant for terrarium" id="plant1" src="../../../../translated_images/plant1.d18b18ffe73da18f8b1ac7aba73b4050af52f4a0c9174aeac464b85123fc2850.no.png" />
<img class="plant" alt="Decorative plant for terrarium" id="plant1" src="../../../../translated_images/plant1.d18b18ffe73da18f.no.png" />
</div>
```
**Viktige elementer forklart:**
- **Bruker** `class="plant-holder"` for konsistent beholderstyling på tvers av alle planter
- **Bruker** `class="plant"` for delte bildestiler og oppførsel
**Nøkkelelementer forklart:**
- **Bruker** `class="plant-holder"` for konsistent container-styling på tvers av alle planter
- **Setter** `class="plant"` for felles bildefunksjon og oppførsel
- **Inkluderer** unik `id="plant1"` for individuell posisjonering og JavaScript-interaksjon
- **Gir** beskrivende alt-tekst for skjermlesertilgjengelighet
@ -274,37 +364,53 @@ Legg nå til disse stilene i `style.css`-filen din:
}
```
**Bryte ned disse stilene:**
- **Oppretter** relativ posisjonering for planteholderen for å etablere en posisjoneringskontekst
- **Setter** hver planteholder til 13% høyde, slik at alle planter passer vertikalt uten scrolling
- **Flytter** beholdere litt til venstre for bedre sentrering av planter innenfor beholderne
- **Lar** planter skalere responsivt med `max-width` og `max-height` egenskaper
- **Bruker** `z-index` for å lagre planter over andre elementer i terrariumet
**Hva disse stilene gjør:**
- **Oppretter** relativ posisjonering for planteholderen for å etablere kontekst for posisjonering
- **Setter** hver planteholder til 13 % høyde, slik at alle planter får plass vertikalt uten rulling
- **Flytter** holderne litt mot venstre for bedre sentrering av plantene i beholderne
- **Tillater** plantene å skalere responsivt med `max-width` og `max-height`
- **Bruker** `z-index` for å legge plantene over andre elementer i terrariet
- **Legger til** en subtil hover-effekt med CSS-overganger for bedre brukerinteraksjon
**Kritisk tenkning**: Hvorfor trenger vi både `.plant-holder` og `.plant` selektorer? Hva ville skjedd hvis vi prøvde å bruke bare én?
**Kritisk tenkning**: Hvorfor trenger vi både `.plant-holder` og `.plant` velgere? Hva ville skjedd hvis vi bare brukte én?
> 💡 **Designmønster**: Beholderen (`.plant-holder`) kontrollerer layout og posisjonering, mens innholdet (`.plant`) kontrollerer utseende og skalering. Denne separasjonen gjør koden mer vedlikeholdbar og fleksibel.
> 💡 **Designmønster**: Containeren (`.plant-holder`) styrer layout og posisjonering, mens innholdet (`.plant`) styrer utseende og skalering. Denne separasjonen gjør koden mer vedlikeholdbar og fleksibel.
## Forstå CSS-posisjonering
CSS-posisjonering er som å være sceneregissør for et teaterstykke du dirigerer hvor hver skuespiller står og hvordan de beveger seg rundt på scenen. Noen skuespillere følger standardformasjonen, mens andre trenger spesifikk posisjonering for dramatisk effekt.
CSS-posisjonering er som å være regi for et teaterstykke du bestemmer hvor hver skuespiller står og hvordan de beveger seg på scenen. Noen følger standard formasjon, mens andre trenger spesiell plassering for dramatisk effekt.
Når du forstår posisjonering, blir mange layoututfordringer håndterbare. Trenger du en navigasjonslinje som holder seg øverst mens brukerne ruller? Posisjonering fikser det. Vil du ha en verktøytips som vises på et spesifikt sted? Det er også posisjonering.
Når du forstår posisjonering, blir mange layoututfordringer håndterbare. Trenger du en navigasjonslinje som blir værende øverst mens brukeren blar? Posisjonering løser det. Vil du ha et verktøytips som dukker opp på et bestemt sted? Det er også posisjonering.
### De fem posisjonsverdiene
```mermaid
quadrantChart
title CSS-posisjoneringsstrategi
x-axis Dokumentflyt --> Fjernet fra flyt
y-axis Statisk posisjon --> Presis kontroll
quadrant-1 Absolutt
quadrant-2 Fast
quadrant-3 Statisk
quadrant-4 Sticky
Static: [0.2, 0.2]
Relative: [0.3, 0.6]
Absolute: [0.8, 0.8]
Fixed: [0.9, 0.7]
Sticky: [0.5, 0.9]
```
| Posisjonsverdi | Oppførsel | Bruksområde |
|----------------|----------|-------------|
|----------------|-----------|-------------|
| `static` | Standardflyt, ignorerer top/left/right/bottom | Normal dokumentlayout |
| `relative` | Posisjonert relativt til sin normale posisjon | Små justeringer, opprette posisjoneringskontekst |
| `absolute` | Posisjonert relativt til nærmeste posisjonerte forfader | Presis plassering, overlegg |
| `fixed` | Posisjonert relativt til visningsvinduet | Navigasjonslinjer, flytende elementer |
| `sticky` | Veksler mellom relativ og fast basert på scrolling | Overskrifter som fester seg ved scrolling |
| `relative` | Posisjonert relativt til sin normale plassering | Små justeringer, etablere posisjoneringskontekst |
| `absolute` | Posisjonert relativt til nærmeste posisjonerte forelder | Presis plassering, overlapp |
| `fixed` | Posisjonert relativt til viewporten | Navigasjonslinjer, flytende elementer |
| `sticky` | Bytter mellom relativ og fast basert på scroll | Overskrifter som fester seg ved scroll |
### Posisjonering i vårt terrarium
### Posisjonering i terrariet vårt
Terrariumet vårt bruker en strategisk kombinasjon av posisjonstyper for å skape ønsket layout:
Terrariet benytter en strategisk kombinasjon av posisjonstyper for det ønskede oppsettet:
```css
/* Container positioning */
@ -328,25 +434,60 @@ Terrariumet vårt bruker en strategisk kombinasjon av posisjonstyper for å skap
**Forstå posisjoneringsstrategien:**
- **Absolutte beholdere** fjernes fra normal dokumentflyt og festes til skjermkanter
- **Relativ planteholder** skaper en posisjoneringskontekst mens den forblir i dokumentflyt
- **Absolutte planter** kan posisjoneres presist innenfor sine relative beholdere
- **Denne kombinasjonen** lar planter stables vertikalt mens de er individuelt posisjonerbare
- **Relative planteholdere** oppretter en posisjoneringskontekst samtidig som de forblir i dokumentflyten
- **Absolutte planter** kan plasseres presist innenfor sine relative beholdere
- **Kombinasjonen** lar plantene stables vertikalt samtidig som de kan posisjoneres individuelt
> 🎯 **Hvorfor dette er viktig**: `plant`-elementene trenger absolutt posisjonering for å bli flyttbare i neste leksjon. Absolutt posisjonering fjerner dem fra den normale layoutflyten, noe som gjør dra-og-slipp-interaksjoner mulig.
> 🎯 **Hvorfor dette er viktig**: `plant`-elementene trenger absolutt posisjonering for å bli dra-og-slippbare i neste leksjon. Absolutt posisjonering fjerner dem fra normal layoutflyt, noe som gjør dra-og-slipp-interaksjoner mulig.
**Eksperimenttid**: Prøv å endre posisjonsverdiene og observer resultatene:
- Hva skjer hvis du endrer `.container` fra `absolute` til `relative`?
- Hvordan endrer layouten seg hvis `.plant-holder` bruker `absolute` i stedet for `relative`?
**Eksperimenter**: Prøv å endre posisjonsverdiene og observer resultatene:
- Hva skjer om du endrer `.container` fra `absolute` til `relative`?
- Hvordan endres layouten hvis `.plant-holder` bruker `absolute` i stedet for `relative`?
- Hva skjer når du bytter `.plant` til `relative` posisjonering?
## Bygge terrariumet med CSS
Nå skal vi bygge en glasskrukke ved hjelp av kun CSS ingen bilder eller grafikkprogramvare nødvendig.
### 🔄 **Pedagogisk innsjekking**
**CSS Posisjonering Mesterlig**: Ta en pause for å verifisere forståelsen din:
- ✅ Kan du forklare hvorfor planter trenger absolutt posisjonering for drag-and-drop?
- ✅ Forstår du hvordan relative beholdere skaper posisjoneringskontekst?
- ✅ Hvorfor bruker sidebeholderne absolutt posisjonering?
- ✅ Hva ville skjedd hvis du fjernet alle posisjoneringsdeklarasjoner helt?
**Reell Verden Kobling**: Tenk på hvordan CSS-posisjonering speiler reell verden layout:
- **Static**: Bøker på en hylle (naturlig rekkefølge)
- **Relative**: Flytte en bok litt men beholde plassen
- **Absolute**: Plassere et bokmerke på en eksakt sidenummer
- **Fixed**: En klistrelapp som forblir synlig mens du blar sider
## Bygge Terrariet med CSS
Nå skal vi bygge en glasskrukke kun med CSS ingen bilder eller grafikkprogrammer nødvendig.
Å skape realistisk glass, skygger og dybdeeffekter ved å bruke posisjonering og transparens viser CSS sine visuelle muligheter. Denne teknikken speiler hvordan arkitekter innen Bauhaus-bevegelsen brukte enkle geometriske former for å lage komplekse, vakre strukturer. Når du forstår disse prinsippene, vil du kjenne igjen CSS-teknikkene bak mange nettdesign.
```mermaid
flowchart LR
A[Krukkens Topp] --> E[Fullstendig Terrarium]
B[Krukkens Vegger] --> E
C[Jordlag] --> E
D[Krukkens Bunn] --> E
F[Glass Effekter] --> E
A1["50% bredde<br/>5% høyde<br/>Topp posisjon"] --> A
B1["60% bredde<br/>80% høyde<br/>Avrundede kanter<br/>0.5 opasitet"] --> B
C1["60% bredde<br/>5% høyde<br/>Mørk brun<br/>Bunnlag"] --> C
D1["50% bredde<br/>1% høyde<br/>Bunn posisjon"] --> D
F1["Subtile skygger<br/>Transparens<br/>Z-indeks lagdeling"] --> F
style E fill:#d1e1df,stroke:#3a241d
style A fill:#e8f5e8
style B fill:#e8f5e8
style C fill:#8B4513
style D fill:#e8f5e8
```
Å lage realistisk utseende glass, skygger og dybdeeffekter ved hjelp av posisjonering og gjennomsiktighet demonstrerer CSS sine visuelle kapabiliteter. Denne teknikken speiler hvordan arkitekter i Bauhaus-bevegelsen brukte enkle geometriske former for å skape komplekse, vakre strukturer. Når du forstår disse prinsippene, vil du gjenkjenne CSS-teknikkene bak mange webdesign.
### Lage Komponentene til Glasskrukken
### Lage komponentene til glasskrukken
La oss bygge terrarium-glasset bit for bit. Hver del bruker absolutt posisjonering og prosentbasert størrelse for responsiv design:
La oss bygge terrarium-krukken bit for bit. Hver del bruker absolutt posisjonering og prosentbaserte størrelser for responsivt design:
```css
.jar-walls {
@ -398,89 +539,200 @@ La oss bygge terrarium-glasset bit for bit. Hver del bruker absolutt posisjoneri
}
```
**Forstå terrarium-konstruksjonen:**
- **Bruker** prosentbaserte dimensjoner for responsiv skalering på alle skjermstørrelser
- **Plasserer** elementer absolutt for å stable og justere dem presist
- **Bruker** ulike opasitetsverdier for å skape en glassgjennomsiktighetseffekt
- **Implementerer** `z-index` lagdeling slik at plantene vises inne i glasset
- **Legger til** subtile skygger og raffinert avrunding av kantene for et mer realistisk utseende
- **Bruker** ulike opasitetsverdier for å skape glasseffekten
- **Implementerer** `z-index` lagring slik at planter vises inni krukken
- **Legger til** subtile boksskygger og raffinert border-radius for mer realistisk utseende
### Responsiv design med prosenter
### Responsivt Design med Prosenter
Legg merke til hvordan alle dimensjoner bruker prosenter i stedet for faste pikselverdier:
Legg merke til at alle dimensjonene bruker prosenter i stedet for faste piksler:
**Hvorfor dette er viktig:**
- **Sikrer** at terrariet skalerer proporsjonalt på alle skjermstørrelser
- **Opprettholder** de visuelle relasjonene mellom glasskomponentene
- **Gir** en konsistent opplevelse fra mobiltelefoner til store skrivebordsskjermer
- **Lar** designet tilpasse seg uten å bryte det visuelle oppsettet
- **Sikrer** at terrariet skaleres proporsjonalt på hvilken som helst skjermstørrelse
- **Opprettholder** de visuelle forholdene mellom krukkens komponenter
- **Gir** en konsekvent opplevelse fra mobiltelefoner til store stasjonære skjermer
- **Lar** designen tilpasse seg uten å bryte layouten visuelt
### CSS-enheter i praksis
### CSS-enheter i bruk
Vi bruker `rem`-enheter for avrunding av kantene, som skalerer relativt til rotfontstørrelsen. Dette skaper mer tilgjengelige design som respekterer brukerens fontpreferanser. Lær mer om [CSS relative enheter](https://www.w3.org/TR/css-values-3/#font-relative-lengths) i den offisielle spesifikasjonen.
Vi bruker `rem`-enheter for border-radius, som skalerer relativt til rot-fontstørrelsen. Dette skaper mer tilgjengelige design som respekterer brukerens fontpreferanser. Les mer om [CSS relative units](https://www.w3.org/TR/css-values-3/#font-relative-lengths) i den offisielle spesifikasjonen.
**Visuell eksperimentering**: Prøv å endre disse verdiene og observer effektene:
- Endre glassets opasitet fra 0.5 til 0.8 hvordan påvirker dette glassets utseende?
- Juster jordfargen fra `#3a241d` til `#8B4513` hvilken visuell effekt har dette?
- Endre `z-index` for jorden til 2 hva skjer med lagdelingen?
**Visuell eksperimentering**: Prøv å endre disse verdiene og se effektene:
- Endre jar-opasiteten fra 0.5 til 0.8 hvordan påvirker det glassutseendet?
- Juster jordfargen fra `#3a241d` til `#8B4513` hvilken visuell effekt får det?
- Endre `z-index` for jorden til 2 hva skjer med lagringen?
### 🔄 **Pedagogisk innsjekking**
**Forståelse av visuell CSS-design**: Bekreft forståelsen din av visuell CSS:
- ✅ Hvordan skaper prosentbaserte dimensjoner responsiv design?
- ✅ Hvorfor skaper opasitet glasseffekten?
- ✅ Hvilken rolle spiller z-index i lagdelingen?
- ✅ Hvordan skaper border-radius verdiene krukkeformen?
**Designprinsipp**: Legg merke til hvordan vi bygger komplekse visuelle elementer fra enkle former:
1. **Rektangler****Avrundede rektangler** → **Krukkekomponenter**
2. **Flate farger****Opasitet** → **Glasseffekt**
3. **Individuelle elementer****Lagvis sammensetning** → **3D-utseende**
---
## GitHub Copilot Agent-utfordring 🚀
## GitHub Copilot Agent Challenge 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
Bruk Agent-modus for å fullføre denne utfordringen:
**Beskrivelse:** Lag en CSS-animasjon som får terrarium-plantene til å svaie forsiktig frem og tilbake, og simulerer en naturlig briseeffekt. Dette vil hjelpe deg med å øve på CSS-animasjoner, transformasjoner og nøkkelrammer, samtidig som det forbedrer terrariets visuelle appell.
**Beskrivelse:** Lag en CSS-animasjon som får terrariumplantene til å svaie forsiktig fram og tilbake, som en naturlig bris. Dette hjelper deg å praktisere CSS-animasjoner, transformasjoner og keyframes samtidig som terrariet ditt får liv.
**Oppgave:** Legg til CSS-nøkkelrammeanimasjoner for å få plantene i terrariet til å svaie forsiktig fra side til side. Lag en svaieanimasjon som roterer hver plante litt (2-3 grader) til venstre og høyre med en varighet på 3-4 sekunder, og bruk den på `.plant`-klassen. Sørg for at animasjonen går i en uendelig loop og har en easing-funksjon for naturlig bevegelse.
**Oppgave:** Legg til CSS keyframe-animasjoner for å få plantene i terrariet til å svaie forsiktig fra side til side. Lag en svingende animasjon som roterer hver plante svakt (2-3 grader) til venstre og høyre med en varighet på 3-4 sekunder, og anvend den på `.plant`-klassen. Sørg for at animasjonen går i loop og har en easing-funksjon for naturlig bevegelse.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Les mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring: Legge til glassrefleksjoner
## 🚀 Utfordring: Legge til Glassrefleksjoner
Klar til å forbedre terrariet med realistiske glassrefleksjoner? Denne teknikken vil gi dybde og realisme til designet.
Klar for å forbedre terrariet med realistiske glassrefleksjoner? Denne teknikken tilfører dybde og realisme til designen.
Du skal lage subtile høydepunkter som simulerer hvordan lys reflekteres fra glassoverflater. Denne tilnærmingen ligner på hvordan renessansemalere som Jan van Eyck brukte lys og refleksjon for å få malt glass til å se tredimensjonalt ut. Her er målet ditt:
Du skal lage subtile høylys som simulerer hvordan lys reflekteres på glassoverflater. Denne tilnærmingen ligner på hvordan renessanse-malere som Jan van Eyck brukte lys og refleksjon for å få malt glass til å virke tredimensjonalt. Slik skal det bli:
![ferdig terrarium](../../../../translated_images/terrarium-final.2f07047ffc597d0a06b06cab28a77801a10dd12fdb6c7fc630e9c40665491c53.no.png)
![finished terrarium](../../../../translated_images/terrarium-final.2f07047ffc597d0a.no.png)
**Din utfordring:**
- **Lag** subtile hvite eller lyse ovale former for glassrefleksjonene
- **Plasser** dem strategisk på venstre side av glasset
- **Plasser** dem strategisk på venstre side av krukken
- **Bruk** passende opasitet og uskarphetseffekter for realistisk lysrefleksjon
- **Bruk** `border-radius` for å lage organiske, bobleaktige former
- **Eksperimenter** med gradienter eller skygger for forbedret realisme
- **Bruk** `border-radius` for å lage organiske, boblelignende former
- **Eksperimenter** med graderinger eller boksskygger for forbedret realisme
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/18)
## Utvid CSS-kunnskapene dine
## Utvid Dine CSS-Kunnskaper
CSS kan virke komplekst i starten, men å forstå disse kjernekonseptene gir et solid grunnlag for mer avanserte teknikker.
CSS kan virke komplekst i starten, men når du forstår disse kjerneprinsippene får du et solid grunnlag for mer avanserte teknikker.
**Dine neste CSS-læringsområder:**
- **Flexbox** - forenkler justering og distribusjon av elementer
- **CSS Grid** - gir kraftige verktøy for å lage komplekse oppsett
- **CSS-variabler** - reduserer repetisjon og forbedrer vedlikeholdbarhet
- **Responsiv design** - sikrer at nettsteder fungerer godt på ulike skjermstørrelser
- **CSS Grid** - kraftige verktøy for å lage komplekse layouter
- **CSS Variabler** - reduserer gjentakelse og forbedrer vedlikehold
- **Responsivt design** - sikrer at nettsider fungerer godt på ulike skjermstørrelser
### Interaktive læringsressurser
Øv på disse konseptene med disse engasjerende, praktiske spillene:
Prøv disse konsepter med engasjerende, praktiske spill:
- 🐸 [Flexbox Froggy](https://flexboxfroggy.com/) - Mestre Flexbox gjennom morsomme utfordringer
- 🌱 [Grid Garden](https://codepip.com/games/grid-garden/) - Lær CSS Grid ved å dyrke virtuelle gulrøtter
- 🎯 [CSS Battle](https://cssbattle.dev/) - Test CSS-ferdighetene dine med kodeutfordringer
- 🎯 [CSS Battle](https://cssbattle.dev/) - Test dine CSS-ferdigheter med kodingsutfordringer
### Ytterligere læring
For omfattende CSS-grunnleggende, fullfør dette Microsoft Learn-modulet: [Style your HTML app with CSS](https://docs.microsoft.com/learn/modules/build-simple-website/4-css-basics/?WT.mc_id=academic-77807-sagibbon)
For en omfattende innføring i CSS-fundamenter, fullfør denne Microsoft Learn-modulen: [Style your HTML app with CSS](https://docs.microsoft.com/learn/modules/build-simple-website/4-css-basics/?WT.mc_id=academic-77807-sagibbon)
### ⚡ **Hva du kan gjøre på de neste 5 minuttene**
- [ ] Åpne DevTools og inspiser CSS-stiler på en nettside via Elements-panelet
- [ ] Lag en enkel CSS-fil og koble den til en HTML-side
- [ ] Prøv å endre farger med forskjellige metoder: hex, RGB og navngitte farger
- [ ] Øv på boksen-modellen ved å legge til padding og margin på en div
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør quiz etter leksjonen og gå gjennom CSS-fundamenter
- [ ] Style HTML-siden din med fonter, farger og marger
- [ ] Lag en enkel layout med flexbox eller grid
- [ ] Eksperimenter med CSS-overganger for myke effekter
- [ ] Øv på responsivt design med medieforespørsler
### 📅 **Din uke-lange CSS-reise**
- [ ] Fullfør terrarium-styling-oppgaven med kreativitet
- [ ] Mestre CSS Grid ved å bygge en fotogalleri-layout
- [ ] Lær CSS-animasjoner for å bringe designene til liv
- [ ] Utforsk CSS preprocessors som Sass eller Less
- [ ] Studer designprinsipper og bruk dem i CSS
- [ ] Analyser og gjenskap interessante design du finner på nettet
### 🌟 **Din månedslange designmestring**
- [ ] Bygg et komplett responsivt nettside-designsystem
- [ ] Lær CSS-in-JS eller utility-first rammeverk som Tailwind
- [ ] Bidra til open source-prosjekter med CSS-forbedringer
- [ ] Mestre avanserte CSS-konsepter som CSS egendefinerte egenskaper og containment
- [ ] Lag gjenbrukbare komponentbiblioteker med modulær CSS
- [ ] Veilede andre som lærer CSS og del designkunnskap
## 🎯 Din CSS-mestringstidslinje
```mermaid
timeline
title CSS Læringsprogresjon
section Grunnlag (10 minutter)
Filtilkobling: Koble CSS til HTML
: Forstå kaskaderegler
: Lær arv grunnleggende
section Velgere (15 minutter)
Målretting av elementer: Elementvelgere
: Klasse mønstre
: ID-spesifisitet
: Kombinatorer
section Boksmodell (20 minutter)
Grunnleggende oppsett: Margin og polstring
: Kant-egenskaper
: Innholds-størrelse
: Boks-størrelse oppførsel
section Posisjonering (25 minutter)
Plassering av elementer: Statisk vs relativ
: Absolutt posisjonering
: Z-indeks lagdeling
: Responsiv enheter
section Visuell design (30 minutter)
Stylingmestring: Farger og opasitet
: Skygger og effekter
: Overganger
: Transform egenskaper
section Responsivt design (45 minutter)
Multi-enhetsstøtte: Mediespørringer
: Fleksible oppsett
: Mobil-først tilnærming
: Visningsport-optimalisering
section Avanserte teknikker (1 uke)
Moderne CSS: Flexbox oppsett
: CSS Grid systemer
: Egne egenskaper
: Animajons nøkkelbilder
section Profesjonelle ferdigheter (1 måned)
CSS Arkitektur: Komponent mønstre
: Vedlikeholdbar kode
: Ytelsesoptimalisering
: Tverr-nettleser kompatibilitet
```
### 🛠️ Din CSS-verktøykasse Oppsummering
Etter å ha fullført denne leksjonen har du nå:
- **Cascade-forståelse**: Hvordan stiler arves og overstyres
- **Selector-mesterlig**: Presis målretting med elementer, klasser og IDer
- **Posisjoneringsferdigheter**: Strategisk plassering og lagdeling av elementer
- **Visuell design**: Lage glasseffekter, skygger og transparens
- **Responsive teknikker**: Prosentbaserte layouter som tilpasser seg alle skjermer
- **Kodeorganisering**: Ren, vedlikeholdbar CSS-struktur
- **Moderne praksis**: Bruk av relative enheter og tilgjengelige designmønstre
**Neste steg**: Terrariet ditt har nå både struktur (HTML) og stil (CSS). Den siste leksjonen legger til interaktivitet med JavaScript!
## Oppgave
[CSS Refactoring](assignment.md)
[CSS Refaktorering](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved bruk av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, må du være klar over at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på originalspråket skal betraktes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,78 +1,178 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "bc93f6285423033ebf5b8abeb5282888",
"translation_date": "2025-10-23T22:27:25+00:00",
"original_hash": "973e48ad87d67bf5bb819746c9f8e302",
"translation_date": "2026-01-07T00:50:36+00:00",
"source_file": "3-terrarium/3-intro-to-DOM-and-closures/README.md",
"language_code": "no"
}
-->
# Terrariumprosjekt del 3: DOM-manipulering og JavaScript-closures
# Terrarium-prosjekt del 3: DOM-manipulasjon og JavaScript-closures
![DOM og en closure](../../../../translated_images/webdev101-js.10280393044d7eaaec7e847574946add7ddae6be2b2194567d848b61d849334a.no.png)
```mermaid
journey
title Din JavaScript DOM-reise
section Grunnlag
Forstå DOM: 3: Student
Lær closures: 4: Student
Koble elementer: 4: Student
section Interaksjon
Sett opp drahendelser: 4: Student
Følg koordinater: 5: Student
Håndter bevegelse: 5: Student
section Puss
Legg til opprydding: 4: Student
Test funksjonalitet: 5: Student
Fullfør terrarium: 5: Student
```
![DOM and a closure](../../../../translated_images/webdev101-js.10280393044d7eaa.no.png)
> Sketchnote av [Tomomi Imura](https://twitter.com/girlie_mac)
Velkommen til en av de mest engasjerende aspektene ved webutvikling - å gjøre ting interaktive! Document Object Model (DOM) fungerer som en bro mellom HTML og JavaScript, og i dag skal vi bruke det til å gi liv til terrariet ditt. Da Tim Berners-Lee skapte den første nettleseren, forestilte han seg en web hvor dokumenter kunne være dynamiske og interaktive - DOM gjør denne visjonen mulig.
Velkommen til en av de mest engasjerende aspektene ved webutvikling å gjøre ting interaktive! Document Object Model (DOM) er som en bro mellom din HTML og JavaScript, og i dag skal vi bruke den til å bringe terrariet ditt til liv. Da Tim Berners-Lee laget den første nettleseren, forestilte han seg et nett der dokumenter kunne være dynamiske og interaktive DOM gjør denne visjonen mulig.
Vi skal også utforske JavaScript-closures, som kanskje høres skremmende ut i starten. Tenk på closures som "hukommelseslommer" der funksjonene dine kan huske viktig informasjon. Det er som om hver plante i terrariet har sin egen dataregistrering for å spore posisjonen sin. Innen slutten av denne leksjonen vil du forstå hvor naturlige og nyttige de er.
Vi skal også utforske JavaScript-closures, som kanskje høres skremmende ut i begynnelsen. Tenk på closures som å lage «minnelommer» hvor funksjonene dine kan huske viktig informasjon. Det er som om hver plante i terrariet har sin egen dataregistrering for å spore sin posisjon. Når du er ferdig med denne leksjonen, vil du forstå hvor naturlige og nyttige de er.
Her er hva vi skal lage: et terrarium hvor brukere kan dra og slippe planter hvor de vil. Du vil lære DOM-manipuleringsteknikker som driver alt fra dra-og-slipp filopplastinger til interaktive spill. La oss gi liv til terrariet ditt.
Her er hva vi bygger: et terrarium hvor brukere kan dra og slippe planter hvor som helst de vil. Du lærer DOM-manipulasjonsteknikker som driver alt fra drag-og-slipp filopplasting til interaktive spill. La oss få terrariet ditt til å leve.
## Quiz før leksjonen
```mermaid
mindmap
root((DOM & JavaScript))
DOM-tre
Elementvalg
Egenskapstilgang
Hendelseshåndtering
Dynamiske oppdateringer
Hendelser
Pekehendelser
Mussehendelser
Berøringshendelser
Hendelseslyttere
Lukninger
Private variabler
Funksjonsscope
Minnevedvarende
Tilstandsbehandling
Dra og slipp
Posisjonssporing
Koordinatmatematikk
Hendelseslivssyklus
Brukerinteraksjon
Moderne mønstre
Hendelsedelegering
Ytelse
Kryss-enhet
Tilgjengelighet
```
## Quiz før forelesning
[Quiz før leksjonen](https://ff-quizzes.netlify.app/web/quiz/19)
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/19)
## Forstå DOM: Din inngangsport til interaktive nettsider
Document Object Model (DOM) er hvordan JavaScript kommuniserer med HTML-elementene dine. Når nettleseren din laster inn en HTML-side, oppretter den en strukturert representasjon av siden i minnet - det er DOM. Tenk på det som et slektstre der hvert HTML-element er et familiemedlem som JavaScript kan få tilgang til, endre eller omorganisere.
Document Object Model (DOM) er hvordan JavaScript kommuniserer med HTML-elementene dine. Når nettleseren din laster en HTML-side, lager den en strukturert representasjon av siden i minnet det er DOM. Tenk på det som et familietre der hvert HTML-element er et familiemedlem som JavaScript kan få tilgang til, endre eller omarrangere.
DOM-manipulering forvandler statiske sider til interaktive nettsteder. Hver gang du ser en knapp endre farge ved hover, innhold som oppdateres uten å laste siden på nytt, eller elementer du kan dra rundt, er det DOM-manipulering i aksjon.
DOM-manipulasjon forvandler statiske sider til interaktive nettsteder. Hver gang du ser en knapp som endrer farge ved hover, innhold som oppdateres uten sideoppdatering, eller elementer du kan dra rundt, er det DOM-manipulasjon i arbeid.
![DOM-tre representasjon](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.no.png)
```mermaid
flowchart TD
A["Dokument"] --> B["HTML"]
B --> C["Hode"]
B --> D["Kropp"]
C --> E["Tittel"]
C --> F["Meta-tagger"]
D --> G["H1: Mitt Terrarium"]
D --> H["Div: Sidebeholder"]
H --> I["Div: Venstre beholder"]
H --> J["Div: Høyre beholder"]
H --> K["Div: Terrarium"]
I --> L["Planteelementer 1-7"]
J --> M["Planteelementer 8-14"]
L --> N["img#plante1"]
L --> O["img#plante2"]
M --> P["img#plante8"]
M --> Q["img#plante9"]
style A fill:#e1f5fe
style B fill:#f3e5f5
style D fill:#e8f5e8
style H fill:#fff3e0
style N fill:#ffebee
style O fill:#ffebee
style P fill:#ffebee
style Q fill:#ffebee
```
![DOM tree representation](../../../../translated_images/dom-tree.7daf0e763cbbba92.no.png)
> En representasjon av DOM og HTML-markeringen som refererer til det. Fra [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
> En representasjon av DOM og HTML-markup som refererer til den. Fra [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
**Dette gjør DOM kraftig:**
- **Gir** en strukturert måte å få tilgang til ethvert element på siden din
- **Muliggjør** dynamiske innholdsoppdateringer uten å laste siden på nytt
**Dette gjør DOM kraftfullt:**
- **Gir** en strukturert måte å få tilgang til alle elementer på siden din
- **Muliggjør** dynamiske innholdsoppdateringer uten sideoppdateringer
- **Tillater** sanntidsrespons på brukerinteraksjoner som klikk og dra
- **Skaper** grunnlaget for moderne interaktive webapplikasjoner
## JavaScript-closures: Skap organisert, kraftig kode
## JavaScript-closures: Lage organisert og kraftfull kode
En [JavaScript-closure](https://developer.mozilla.org/docs/Web/JavaScript/Closures) er som å gi en funksjon sitt eget private arbeidsområde med vedvarende hukommelse. Tenk på hvordan Darwins finker på Galápagosøyene utviklet spesialiserte nebb basert på sitt spesifikke miljø - closures fungerer på lignende måte, og skaper spesialiserte funksjoner som "husker" sin spesifikke kontekst selv etter at foreldrefunksjonen er ferdig.
En [JavaScript-closure](https://developer.mozilla.org/docs/Web/JavaScript/Closures) er som å gi en funksjon sitt eget private arbeidsområde med vedvarende minne. Tenk på hvordan Darwins finker på Galápagosøyene utviklet spesialiserte nebb basert på sitt spesifikke miljø closures fungerer på samme måte, og lager spesialiserte funksjoner som «husker» sin spesifikke kontekst selv etter at foreldrefunksjonen har fullført.
I vårt terrarium hjelper closures hver plante med å huske sin egen posisjon uavhengig. Dette mønsteret dukker opp overalt i profesjonell JavaScript-utvikling, og gjør det til et verdifullt konsept å forstå.
I terrariet vårt hjelper closures hver plante med å huske sin egen posisjon uavhengig. Dette mønsteret dukker opp overalt i profesjonell JavaScript-utvikling, og gjør det til et verdifullt konsept å forstå.
> 💡 **Forstå closures**: Closures er et viktig tema i JavaScript, og mange utviklere bruker dem i årevis før de fullt ut forstår alle de teoretiske aspektene. I dag fokuserer vi på praktisk anvendelse - du vil se closures naturlig dukke opp mens vi bygger våre interaktive funksjoner. Forståelsen vil utvikle seg etter hvert som du ser hvordan de løser reelle problemer.
```mermaid
flowchart LR
A["dragElement(plant1)"] --> B["Oppretter lukking"]
A2["dragElement(plant2)"] --> B2["Oppretter lukking"]
B --> C["Private variabler"]
B2 --> C2["Private variabler"]
C --> D["pos1, pos2, pos3, pos4"]
C --> E["pointerDrag-funksjon"]
C --> F["elementDrag-funksjon"]
C --> G["stopElementDrag-funksjon"]
C2 --> D2["pos1, pos2, pos3, pos4"]
C2 --> E2["pointerDrag-funksjon"]
C2 --> F2["elementDrag-funksjon"]
C2 --> G2["stopElementDrag-funksjon"]
H["Plante 1 husker sin posisjon"] --> B
H2["Plante 2 husker sin posisjon"] --> B2
style B fill:#e8f5e8
style B2 fill:#e8f5e8
style C fill:#fff3e0
style C2 fill:#fff3e0
```
> 💡 **Forstå closures**: Closures er et viktig tema i JavaScript, og mange utviklere bruker dem i mange år før de fullt ut forstår alle teoretiske aspekter. I dag fokuserer vi på praktisk anvendelse du vil se closures naturlig dukke opp når vi bygger våre interaktive funksjoner. Forståelsen utvikler seg mens du ser hvordan de løser virkelige problemer.
![DOM-tre representasjon](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.no.png)
![DOM tree representation](../../../../translated_images/dom-tree.7daf0e763cbbba92.no.png)
> En representasjon av DOM og HTML-markeringen som refererer til det. Fra [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
> En representasjon av DOM og HTML-markup som refererer til den. Fra [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
I denne leksjonen skal vi fullføre vårt interaktive terrarieprosjekt ved å lage JavaScript som lar en bruker manipulere plantene på siden.
I denne leksjonen skal vi fullføre vårt interaktive terrariumprosjekt ved å lage JavaScript som lar en bruker manipulere plantene på siden.
## Før vi begynner: Forberedelse for suksess
Du trenger HTML- og CSS-filene dine fra de tidligere terrarie-leksjonene - vi er i ferd med å gjøre det statiske designet interaktivt. Hvis du er med for første gang, vil det å fullføre de tidligere leksjonene gi viktig kontekst.
Du trenger HTML- og CSS-filene dine fra forrige terrariumleksjoner vi skal gjøre det statiske designet interaktivt. Hvis du er ny, bør du fullføre disse leksjonene først for å få viktig kontekst.
Her er hva vi skal lage:
- **Smidig dra-og-slipp** for alle terrarieplanter
- **Koordinatsporing** slik at plantene husker posisjonene sine
- **Et komplett interaktivt grensesnitt** ved bruk av ren JavaScript
- **Ren, organisert kode** ved bruk av closure-mønstre
Dette skal vi bygge:
- **Jevn drag-og-slipp** for alle terrariumplanter
- **Koordinatsporing** slik at planter husker posisjonene sine
- **Et komplett interaktivt grensesnitt** med ren JavaScript
- **Ren, organisert kode** med closure-mønstre
## Oppsett av JavaScript-filen din
## Sette opp din JavaScript-fil
La oss lage JavaScript-filen som vil gjøre terrariet ditt interaktivt.
La oss lage JavaScript-filen som skal gjøre terrariet ditt interaktivt.
**Steg 1: Opprett script-filen din**
**Steg 1: Lag din scriptfil**
I terrarie-mappen din, opprett en ny fil kalt `script.js`.
I terrarium-mappen din, lag en ny fil kalt `script.js`.
**Steg 2: Koble JavaScript til HTML-filen din**
**Steg 2: Knytt JavaScript til HTML**
Legg til denne script-taggen i `<head>`-seksjonen av `index.html`-filen din:
Legg til denne script-taggen i `<head>`-seksjonen i `index.html`-filen din:
```html
<script src="./script.js" defer></script>
@ -80,26 +180,26 @@ Legg til denne script-taggen i `<head>`-seksjonen av `index.html`-filen din:
**Hvorfor `defer`-attributtet er viktig:**
- **Sikrer** at JavaScript venter til all HTML er lastet
- **Forhindrer** feil der JavaScript leter etter elementer som ikke er klare ennå
- **Forhindrer** feil der JavaScript søker etter elementer som ikke er klare ennå
- **Garanterer** at alle planteelementene dine er tilgjengelige for interaksjon
- **Gir** bedre ytelse enn å plassere script nederst på siden
- **Gir** bedre ytelse enn å plassere skripter nederst på siden
> ⚠️ **Viktig merknad**: `defer`-attributtet forhindrer vanlige timingproblemer. Uten det kan JavaScript prøve å få tilgang til HTML-elementer før de er lastet, noe som fører til feil.
> ⚠️ **Viktig notat**: `defer`-attributtet forhindrer vanlige tidsproblemer. Uten det kan JavaScript prøve å aksessere HTML-elementer før de er lastet, noe som fører til feil.
---
## Koble JavaScript til HTML-elementene dine
Før vi kan gjøre elementer flyttbare, må JavaScript finne dem i DOM. Tenk på dette som et bibliotekskatalogsystem - når du har katalognummeret, kan du finne akkurat den boken du trenger og få tilgang til alt innholdet.
Før vi kan gjøre elementene draggbare, må JavaScript finne dem i DOM. Tenk på dette som et bibliotekkatalogiseringssystem når du har katalognummret, kan du finne akkurat boken du trenger og få tilgang til hele innholdet.
Vi bruker metoden `document.getElementById()` for å lage disse koblingene. Det er som å ha et presist arkivsystem - du gir en ID, og det finner akkurat det elementet du trenger i HTML.
Vi skal bruke `document.getElementById()`-metoden for å lage disse koblingene. Det er som å ha et presist arkivsystem du oppgir en ID, og det finner akkurat elementet du trenger i HTML-en din.
### Aktivere dra-funksjonalitet for alle planter
### Aktivere drafunksjon for alle planter
Legg til denne koden i `script.js`-filen din:
```javascript
// Enable drag functionality for all 14 plants
// Aktiver dra-funksjonalitet for alle 14 planter
dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
@ -116,24 +216,34 @@ dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));
```
**Dette oppnår koden:**
**Dette oppnår denne koden:**
- **Finner** hvert planteelement i DOM ved hjelp av dets unike ID
- **Henter** en JavaScript-referanse til hvert HTML-element
- **Sender** hvert element til en `dragElement`-funksjon (som vi skal lage neste)
- **Forbereder** hver plante for dra-og-slipp interaksjon
- **Kobler** HTML-strukturen din til JavaScript-funksjonalitet
- **Sender** hvert element til en `dragElement`-funksjon (som vi lager neste)
- **Forbereder** hver plante for drag-og-slipp interaksjon
- **Kobler** HTML-strukturen til JavaScript-funksjonalitet
> 🎯 **Hvorfor bruke ID-er i stedet for klasser?** ID-er gir unike identifikatorer for spesifikke elementer, mens CSS-klasser er designet for å style grupper av elementer. Når JavaScript trenger å manipulere individuelle elementer, gir ID-er den presisjonen og ytelsen vi trenger.
> 🎯 **Hvorfor bruke ID-er i stedet for klasser?** ID-er gir unike identifikatorer for spesifikke elementer, mens CSS-klasser er laget for å style grupper av elementer. Når JavaScript skal manipulere individuelle elementer, gir ID-er den presisjonen og ytelsen vi trenger.
> 💡 **Proff-tips**: Legg merke til hvordan vi kaller `dragElement()` for hver plante individuelt. Denne tilnærmingen sikrer at hver plante får sin egen uavhengige dra-adferd, noe som er essensielt for smidig brukerinteraksjon.
> 💡 **Tips:** Legg merke til at vi kaller `dragElement()` for hver plante individuelt. Denne tilnærmingen sikrer at hver plante får sin egen uavhengige dra-oppførsel, noe som er essensielt for en jevn brukeropplevelse.
### 🔄 **Pedagogisk sjekk**
**Forståelse av DOM-kobling**: Før vi går videre med drafunksjonalitet, sjekk at du kan:
- ✅ Forklare hvordan `document.getElementById()` finner HTML-elementer
- ✅ Forstå hvorfor vi bruker unike ID-er for hver plante
- ✅ Beskrive hensikten med `defer`-attributtet i script-tagger
- ✅ Gjenkjenne hvordan JavaScript og HTML kobles sammen gjennom DOM
**Rask selvevaluering**: Hva skjer hvis to elementer har samme ID? Hvorfor returnerer `getElementById()` bare ett element?
*Svar: ID-er skal være unike; hvis de er duplisert, returneres bare det første elementet*
---
## Bygge dragElement-closure
## Lage dragElement-closure
Nå skal vi lage kjernen i dra-funksjonaliteten vår: en closure som styrer dra-adferden for hver plante. Denne closuren vil inneholde flere indre funksjoner som samarbeider for å spore musebevegelser og oppdatere elementposisjoner.
lager vi kjernen i vår drafunksjonalitet: en closure som styrer dra-oppførselen for hver plante. Denne closuren vil inneholde flere indre funksjoner som jobber sammen for å spore musebevegelser og oppdatere elementposisjoner.
Closures er perfekte for denne oppgaven fordi de lar oss opprette "private" variabler som vedvarer mellom funksjonskall, og gir hver plante sitt eget uavhengige koordinatsporingssystem.
Closures er perfekte for denne oppgaven fordi de lar oss lage "private" variabler som vedvarer mellom funksjonskall, og gir hver plante sin egen uavhengige koordinatsporing.
### Forstå closures med et enkelt eksempel
@ -141,14 +251,14 @@ La meg demonstrere closures med et enkelt eksempel som illustrerer konseptet:
```javascript
function createCounter() {
let count = 0; // This is like a private variable
let count = 0; // Dette er som en privat variabel
function increment() {
count++; // The inner function remembers the outer variable
count++; // Den indre funksjonen husker den ytre variabelen
return count;
}
return increment; // We're giving back the inner function
return increment; // Vi gir tilbake den indre funksjonen
}
const myCounter = createCounter();
@ -156,181 +266,243 @@ console.log(myCounter()); // 1
console.log(myCounter()); // 2
```
**Dette skjer i closure-mønsteret:**
- **Oppretter** en privat `count`-variabel som kun eksisterer innenfor denne closuren
- **Den indre funksjonen** kan få tilgang til og endre den ytre variabelen (closure-mekanismen)
- **Når vi returnerer** den indre funksjonen, opprettholder den forbindelsen til den private dataen
- **Selv etter** at `createCounter()` er ferdig med å kjøre, vedvarer `count` og husker verdien sin
**Dette skjer i dette closure-mønsteret:**
- **Oppretter** en privat `count`-variabel som bare eksisterer i denne closuren
- **Innerfunksjonen** kan få tilgang til og endre den ytre variabelen (closure-mekanismen)
- **Når vi returnerer** innerfunksjonen, beholder den forbindelsen til denne private dataen
- **Selv etter** at `createCounter()` er ferdig med kjøringen, vedvarer `count` og husker sin verdi
### Hvorfor closures er perfekte for dra-funksjonalitet
### Hvorfor closures er perfekte for drafunksjonalitet
For vårt terrarium trenger hver plante å huske sine nåværende posisjonskoordinater. Closures gir den perfekte løsningen:
For terrariet vårt må hver plante huske sine nåværende posisjonskoordinater. Closures gir den perfekte løsningen:
**Nøkkelfordeler for prosjektet vårt:**
**Nøkkelfordeler i prosjektet:**
- **Opprettholder** private posisjonsvariabler for hver plante uavhengig
- **Bevarer** koordinatdata mellom dra-hendelser
- **Forhindrer** variabelkonflikter mellom ulike flyttbare elementer
- **Skaper** en ren, organisert kodestruktur
- **Bevarer** koordinatdata mellom drahendelser
- **Forhindrer** variabelkonflikter mellom ulike draggbare elementer
- **Skaper** ren og organisert kode
> 🎯 **Læringsmål**: Du trenger ikke å mestre alle aspekter ved closures akkurat nå. Fokuser på å se hvordan de hjelper oss med å organisere kode og opprettholde tilstand for dra-funksjonaliteten.
> 🎯 **Læringsmål**: Du trenger ikke mestre alle aspekter av closures akkurat nå. Fokuser på hvordan de hjelper oss med å organisere kode og opprettholde tilstand for drafunksjonaliteten vår.
```mermaid
stateDiagram-v2
[*] --> Ready: Side laster
Ready --> DragStart: Bruker trykker ned (pointerdown)
DragStart --> Dragging: Mus/finger beveger seg (pointermove)
Dragging --> Dragging: Fortsett å bevege
Dragging --> DragEnd: Bruker slipper (pointerup)
DragEnd --> Ready: Tilbakestill for neste dra
state DragStart {
[*] --> CapturePosition
CapturePosition --> SetupListeners
SetupListeners --> [*]
}
state Dragging {
[*] --> CalculateMovement
CalculateMovement --> UpdatePosition
UpdatePosition --> [*]
}
state DragEnd {
[*] --> RemoveListeners
RemoveListeners --> CleanupState
CleanupState --> [*]
}
```
### Lage dragElement-funksjonen
Nå skal vi bygge hovedfunksjonen som vil håndtere all dra-logikken. Legg til denne funksjonen under deklarasjonene for planteelementene:
bygger vi hovedfunksjonen som skal håndtere all dra-logikken. Legg til denne funksjonen under deklarasjonen av planteelementene dine:
```javascript
function dragElement(terrariumElement) {
// Initialize position tracking variables
let pos1 = 0, // Previous mouse X position
pos2 = 0, // Previous mouse Y position
pos3 = 0, // Current mouse X position
pos4 = 0; // Current mouse Y position
// Initialiser posisjonssporingsvariabler
let pos1 = 0, // Forrige muse X-posisjon
pos2 = 0, // Forrige muse Y-posisjon
pos3 = 0, // Nåværende muse X-posisjon
pos4 = 0; // Nåværende muse Y-posisjon
// Set up the initial drag event listener
// Sett opp den første dra-hendelseslytter
terrariumElement.onpointerdown = pointerDrag;
}
```
**Forstå posisjonssporingssystemet:**
**Forstå posisjonsporingssystemet:**
- **`pos1` og `pos2`**: Lagrer forskjellen mellom gamle og nye museposisjoner
- **`pos3` og `pos4`**: Sporer de nåværende musekoordinatene
- **`terrariumElement`**: Det spesifikke planteelementet vi gjør flyttbart
- **`onpointerdown`**: Hendelsen som utløses når brukeren begynner å dra
- **`terrariumElement`**: Det spesifikke planteelementet vi lager draggbart
- **`onpointerdown`**: Hendelsen som trigges når brukeren begynner å dra
**Slik fungerer closure-mønsteret:**
**Slik fungerer closure-mønsteret her:**
- **Oppretter** private posisjonsvariabler for hvert planteelement
- **Opprettholder** disse variablene gjennom dra-livssyklusen
- **Opprettholder** disse variablene gjennom hele drag-livssyklusen
- **Sikrer** at hver plante sporer sine egne koordinater uavhengig
- **Gir** et rent grensesnitt gjennom `dragElement`-funksjonen
### Hvorfor bruke pointer-hendelser?
### Hvorfor bruke pointer-events?
Du lurer kanskje på hvorfor vi bruker `onpointerdown` i stedet for den mer kjente `onclick`. Her er forklaringen:
| Hendelsestype | Best for | Ulempen |
| Hendelsestype | Best for | Fangsten |
|---------------|----------|---------|
| `onclick` | Enkle knappetrykk | Kan ikke håndtere dra (bare klikk og slipp) |
| `onclick` | Enkle knappklikk | Kan ikke håndtere dra (bare klikk og slipp) |
| `onpointerdown` | Både mus og berøring | Nyere, men godt støttet i dag |
| `onmousedown` | Kun mus på desktop | Utelukker mobilbrukere |
| `onmousedown` | Kun desktop-mus | Utelukker mobilbrukere |
**Hvorfor pointer-hendelser er perfekte for det vi bygger:**
- **Fungerer utmerket** enten noen bruker mus, finger eller til og med stylus
**Hvorfor pointer-events er perfekte for dette:**
- **Fungerer utmerket** enten noen bruker mus, finger eller penn
- **Føles likt** på laptop, nettbrett eller telefon
- **Håndterer** den faktiske dra-bevegelsen (ikke bare klikk-og-ferdig)
- **Skaper** en smidig opplevelse som brukere forventer fra moderne webapper
- **Håndterer** selve dra-bevegelsen (ikke bare klikk)
- **Gir** en jevn opplevelse som brukere forventer fra moderne webapper
> 💡 **Fremtidssikring**: Pointer-events er den moderne måten å håndtere brukerinteraksjoner på. I stedet for å skrive separat kode for mus og touch, får du begge deler gratis. Ganske praktisk, ikke sant?
> 💡 **Fremtidssikring**: Pointer-hendelser er den moderne måten å håndtere brukerinteraksjoner på. I stedet for å skrive separat kode for mus og berøring, får du begge gratis. Ganske kult, ikke sant?
### 🔄 **Pedagogisk sjekk**
**Forståelse av hendelseshåndtering**: Stopp opp og sjekk at du forstår:
- ✅ Hvorfor bruker vi pointer-events i stedet for mus-events?
- ✅ Hvordan persisterer closure-variabler mellom funksjonskall?
- ✅ Hvilken rolle spiller `preventDefault()` for jevn dragging?
- ✅ Hvorfor legger vi lyttere på dokumentet i stedet for enkelt-elementer?
**Virkelighetsforbindelse**: Tenk på drag-og-slipp-grensesnitt du bruker daglig:
- **Filopplastinger**: Dra filer inn i nettleservinduet
- **Kanban-tavler**: Flytte oppgaver mellom kolonner
- **Bildegallerier**: Omorganisere bilderangering
- **Mobilgrensesnitt**: Sveiping og drag på berøringsskjermer
---
## Funksjonen pointerDrag: Fange starten på en dra-bevegelse
## pointerDrag-funksjonen: Fange starten på en dra
Når en bruker trykker ned på en plante (enten med museklikk eller fingerberøring), aktiveres `pointerDrag`-funksjonen. Denne funksjonen fanger opp de innledende koordinatene og setter opp dra-systemet.
Når en bruker trykker ned på en plante (enten med mus eller finger), trår `pointerDrag`-funksjonen i kraft. Denne funksjonen fanger de innledende koordinatene og setter opp dra-systemet.
Legg til denne funksjonen inne i `dragElement`-closure, rett etter linjen `terrariumElement.onpointerdown = pointerDrag;`:
Legg denne funksjonen inn i `dragElement`-closure, rett etter linjen `terrariumElement.onpointerdown = pointerDrag;`:
```javascript
function pointerDrag(e) {
// Prevent default browser behavior (like text selection)
// Forhindre standard nettleseradferd (som tekstvalg)
e.preventDefault();
// Capture the initial mouse/touch position
pos3 = e.clientX; // X coordinate where drag started
pos4 = e.clientY; // Y coordinate where drag started
// Fang den opprinnelige mus-/berøringsposisjonen
pos3 = e.clientX; // X-koordinat der draingen startet
pos4 = e.clientY; // Y-koordinat der draingen startet
// Set up event listeners for the dragging process
// Sett opp hendelseslyttere for draingsprosessen
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
}
```
**Steg for steg, dette skjer:**
- **Forhindrer** standard nettleseratferd som kan forstyrre dra-bevegelsen
- **Registrerer** de nøyaktige koordinatene der brukeren startet dra-bevegelsen
- **Etablerer** hendelseslyttere for den pågående dra-bevegelsen
- **Forbereder** systemet til å spore muse-/fingerbevegelse over hele dokumentet
- **Forhindrer** standard nettleseradferd som kan forstyrre dragging
- **Registrerer** de nøyaktige koordinatene der brukeren startet dra-gesten
- **Etablerer** eventlyttinger for pågående dragbevegelser
- **Forbereder** systemet på å spore muse-/fingerbevegelser over hele dokumentet
### Forstå hendelsesforebygging
### Forstå event-preventDefault
Linjen `e.preventDefault()` er avgjørende for smidig dra-bevegelse:
Linjen `e.preventDefault()` er avgjørende for jevn dragging:
**Uten forebygging kan nettlesere:**
- **Velge** tekst når du drar over siden
- **Utløse** kontekstmenyer ved høyreklikk-dra
**Uten dette kan nettlesere:**
- **Velge** tekst ved dragging over siden
- **Åpne** kontekstmenyer ved høyreklikk-drag
- **Forstyrre** vår tilpassede dra-adferd
- **Skape** visuelle artefakter under dra-operasjonen
- **Skape** visuelle forstyrrelser under drag-operasjonen
> 🔍 **Eksperiment**: Etter å ha fullført denne leksjonen, prøv å fjerne `e.preventDefault()` og se hvordan det påvirker dra-opplevelsen. Du vil raskt forstå hvorfor denne linjen er essensiell!
> 🔍 **Eksperiment:** Etter denne leksjonen, prøv å fjerne `e.preventDefault()` og se hvordan det påvirker drag-opplevelsen. Du vil raskt forstå hvorfor denne linjen er essensiell!
### Koordinatsporingssystem
Egenskapene `e.clientX` og `e.clientY` gir oss presise muse-/berøringskoordinater:
| Egenskap | Hva den måler | Bruksområde |
|----------|---------------|-------------|
| `clientX` | Horisontal posisjon relativt til visningsområdet | Spore venstre-høyre bevegelse |
| `clientY` | Vertikal posisjon relativt til visningsområdet | Spore opp-ned bevegelse |
`e.clientX` og `e.clientY`-egenskapene gir oss presise muse-/berøringskoordinater:
| Egenskap | Hva måles | Bruksområde |
|----------|-----------|-------------|
| `clientX` | Horisontal posisjon relativ til viewport | Sporing av bevegelse fra venstre til høyre |
| `clientY` | Vertikal posisjon relativ til viewport | Sporing av bevegelse opp og ned |
**Forstå disse koordinatene:**
- **Gir** pikselperfekt posisjonsinformasjon
- **Oppdateres** i sanntid mens brukeren beveger pekeren
- **Forblir** konsistent på tvers av ulike skjermstørrelser og zoomnivåer
- **Muliggjør** smidige, responsive dra-interaksjoner
- **Gir** pikselpresis posisjoneringsinformasjon
- **Oppdateres** i sanntid mens brukeren flytter pekeren
- **Forblir** konsekvent på tvers av forskjellige skjermstørrelser og zoomnivåer
- **Muliggjør** jevne, responsive dra-handlinger
### Oppsett av dokumentnivå hendelseslyttere
### Sette opp hendelseslyttere på dokumentnivå
Legg merke til hvordan vi knytter flytte- og stopp-hendelsene til hele `document`, ikke bare planteelementet:
Legg merke til hvordan vi fester flytte- og stopp-hendelsene til hele `document`, ikke bare planteelementet:
```javascript
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
```
**Hvorfor knytte til dokumentet:**
- **Fortsetter** sporing selv når musen forlater planteelementet
- **Forhindrer** avbrudd i dra-bevegelsen hvis brukeren beveger seg raskt
- **Gir** smidig dra-bevegelse over hele skjermen
- **Håndterer** kanttilfeller der pekeren beveger seg utenfor nettleservinduet
**Hvorfor feste til dokumentet:**
- **Fortsetter** å spore selv når musa forlater planteelementet
- **Forhindrer** avbrudd i dra-handlingen hvis brukeren beveger seg raskt
- **Gir** jevn dragging over hele skjermen
- **Håndterer** spesialtilfeller der pekeren beveger seg utenfor nettleservinduet
> ⚡ **Ytelsesnotat**: Vi rydder opp i disse dokumentnivå-lytterne når dra-bevegelsen stopper for å unngå minnelekkasjer og ytelsesproblemer.
> ⚡ **Ytelsesnotat**: Vi vil rydde opp i disse dokumentnivå-lytterene når dragging stopper for å unngå minnelekkasjer og ytelsesproblemer.
## Fullføre dra-systemet: Bevegelse og opprydding
skal vi legge til de to gjenværende funksjonene som håndterer den faktiske dra-bevegelsen og oppryddingen når dra-bevegelsen stopper. Disse funksjonene samarbeider for å skape smidig, responsiv plantebevegelse over terrariet ditt.
legger vi til de to siste funksjonene som håndterer den faktiske dra-bevegelsen og oppryddingen når dragging stopper. Disse funksjonene jobber sammen for å skape jevn, responsiv plantebevegelse i terrariet ditt.
### Funksjonen elementDrag: Spore bevegelse
### elementDrag-funksjonen: Spore bevegelse
Legg til `elementDrag`-funksjonen rett etter den avsluttende krøllparentesen til `pointerDrag`:
Legg til `elementDrag`-funksjonen rett etter avsluttende krøllete parentes for `pointerDrag`:
```javascript
function elementDrag(e) {
// Calculate the distance moved since the last event
pos1 = pos3 - e.clientX; // Horizontal distance moved
pos2 = pos4 - e.clientY; // Vertical distance moved
// Beregn avstanden som er flyttet siden forrige hendelse
pos1 = pos3 - e.clientX; // Horisontal flyttet avstand
pos2 = pos4 - e.clientY; // Vertikal flyttet avstand
// Update the current position tracking
pos3 = e.clientX; // New current X position
pos4 = e.clientY; // New current Y position
// Oppdater sporing av gjeldende posisjon
pos3 = e.clientX; // Ny gjeldende X-posisjon
pos4 = e.clientY; // Ny gjeldende Y-posisjon
// Apply the movement to the element's position
// Bruk bevegelsen på elementets posisjon
terrariumElement.style.top = (terrariumElement.offsetTop - pos2) + 'px';
terrariumElement.style.left = (terrariumElement.offsetLeft - pos1) + 'px';
}
```
**Forstå koordinatmatematikken:**
- **`pos1` og `pos2`**: Beregner hvor langt musen har beveget seg siden siste oppdatering
- **`pos3` og `pos4`**: Lagre musens nåværende posisjon for neste beregning
- **`offsetTop` og `offsetLeft`**: Hente elementets nåværende posisjon på siden
- **Subtraksjonslogikk**: Flytter elementet med samme avstand som musen har beveget seg
**Forstå matematikken bak koordinatene:**
- **`pos1` og `pos2`**: Beregner hvor langt musa har beveget seg siden forrige oppdatering
- **`pos3` og `pos4`**: Lagrer den nåværende museposisjonen for neste beregning
- **`offsetTop` og `offsetLeft`**: Henter elementets nåværende posisjon på siden
- **Subtraksjonslogikk**: Flytter elementet med samme avstand som musa har beveget seg
**Her er en oversikt over bevegelsesberegningen:**
```mermaid
sequenceDiagram
participant User
participant Mouse
participant JavaScript
participant Plant
User->>Mouse: Start dra ved (100, 50)
Mouse->>JavaScript: pointerdown hendelse
JavaScript->>JavaScript: Lagre startposisjon (pos3=100, pos4=50)
JavaScript->>JavaScript: Sett opp move/up lyttere
User->>Mouse: Flytt til (110, 60)
Mouse->>JavaScript: pointermove hendelse
JavaScript->>JavaScript: Beregn: pos1=10, pos2=10
JavaScript->>Plant: Oppdater: venstre += 10px, topp += 10px
Plant->>Plant: Render på ny posisjon
User->>Mouse: Slipp ved (120, 65)
Mouse->>JavaScript: pointerup hendelse
JavaScript->>JavaScript: Fjern lyttere
JavaScript->>JavaScript: Tilbakestill for neste dra
```
**Her er bevegelsesberegningen forklart:**
1. **Måler** forskjellen mellom gammel og ny museposisjon
2. **Beregner** hvor mye elementet skal flyttes basert på musens bevegelse
3. **Oppdaterer** elementets CSS-posisjonsverdier i sanntid
4. **Lagrer** den nye posisjonen som utgangspunkt for neste bevegelsesberegning
2. **Beregner** hvor mye elementet skal flyttes basert på musebevegelsen
3. **Oppdaterer** elementets CSS-posisjons-egenskaper i sanntid
4. **Lagrer** den nye posisjonen som grunnlag for neste bevegelsesberegning
### Visuell fremstilling av matematikken
### Visuell fremstilling av matematikk
```mermaid
sequenceDiagram
@ -338,76 +510,88 @@ sequenceDiagram
participant JavaScript
participant Plant
Mouse->>JavaScript: Move from (100,50) to (110,60)
JavaScript->>JavaScript: Calculate: moved 10px right, 10px down
JavaScript->>Plant: Update position by +10px right, +10px down
Plant->>Plant: Render at new position
Mouse->>JavaScript: Flytt fra (100,50) til (110,60)
JavaScript->>JavaScript: Beregn: flyttet 10px til høyre, 10px ned
JavaScript->>Plant: Oppdater posisjon med +10px til høyre, +10px ned
Plant->>Plant: Tegn på ny posisjon
```
### stopElementDrag-funksjonen: Opprydding
### Funksjonen stopElementDrag: Rydding
Legg til oppryddingsfunksjonen etter den avsluttende krøllparentesen til `elementDrag`:
Legg til oppryddingsfunksjonen etter avsluttende krøllete parentes for `elementDrag`:
```javascript
function stopElementDrag() {
// Remove the document-level event listeners
// Fjern hendelseslyttere på dokumentnivå
document.onpointerup = null;
document.onpointermove = null;
}
```
**Hvorfor opprydding er viktig:**
- **Forhindrer** minnelekkasjer fra hengende event listeners
- **Stopper** dra-funksjonen når brukeren slipper planten
- **Tillater** at andre elementer kan dras uavhengig
- **Tilbakestiller** systemet for neste dra-operasjon
**Hvorfor opprydding er essensielt:**
- **Forhindrer** minnelekkasjer fra hengende event-lyttere
- **Stopper** dragging når brukeren slipper planten
- **Tillater** andre elementer å kunne dras uavhengig
- **Nullstiller** systemet for neste dra-operasjon
**Hva som skjer uten opprydding:**
- Event listeners fortsetter å kjøre selv etter at draingen er stoppet
- Ytelsen forverres ettersom ubrukte lyttere hoper seg opp
- Uventet oppførsel ved interaksjon med andre elementer
- Nettleserressurser sløses bort på unødvendig eventhåndtering
- Event-lyttere fortsetter å kjøre selv etter dragging stopper
- Ytelsen forringes etter hvert som ubrukte lyttere akkumuleres
- Uforventet atferd ved interaksjon med andre elementer
- Nettleserressurser sløses bort på unødvendig hendelseshåndtering
### Forstå CSS-posisjonsverdier
### Forstå CSS-posisjonsegenskaper
Vårt dra-system manipulerer to viktige CSS-egenskaper:
| Egenskap | Hva den kontrollerer | Hvordan vi bruker den |
|----------|-----------------------|-----------------------|
| `top` | Avstand fra toppkanten | Vertikal posisjonering under draing |
| `left` | Avstand fra venstre kant | Horisontal posisjonering under draing |
| Egenskap | Hva den Kontrollerer | Hvordan vi bruker den |
|----------|---------------------|-----------------------|
| `top` | Avstand fra øverste kant | Vertikal posisjonering under dragging |
| `left` | Avstand fra venstre kant | Horisontal posisjonering under dragging |
**Viktige innsikter om offset-egenskaper:**
- **`offsetTop`**: Nåværende avstand fra toppen av den posisjonerte overordnede elementet
- **`offsetLeft`**: Nåværende avstand fra venstre av den posisjonerte overordnede elementet
- **Posisjoneringskontekst**: Disse verdiene er relative til nærmeste posisjonerte forfader
- **`offsetTop`**: Nåværende avstand fra toppen av det posisjonerte foreldre-elementet
- **`offsetLeft`**: Nåværende avstand fra venstre av det posisjonerte foreldre-elementet
- **Posisjoneringskontekst**: Disse verdiene er relative til nærmeste posisjonerte overordnede
- **Sanntidsoppdateringer**: Endres umiddelbart når vi modifiserer CSS-egenskapene
> 🎯 **Designfilosofi**: Dette dra-systemet er bevisst fleksibelt det finnes ingen "slipp-soner" eller restriksjoner. Brukere kan plassere planter hvor som helst, og får full kreativ kontroll over terrariumdesignen.
> 🎯 **Designfilosofi**: Dette dra-systemet er bevisst fleksibelt det finnes ingen "slippe-soner" eller restriksjoner. Brukere kan plassere planter hvor som helst, noe som gir dem full kreativ kontroll over terrarie-designet sitt.
## Sette alt sammen: Ditt komplette dra-system
## Sette det hele sammen: Ditt komplette dra-system
Gratulerer! Du har nettopp bygget et sofistikert dra-og-slipp-system ved hjelp av ren JavaScript. Din komplette `dragElement`-funksjon inneholder nå en kraftig closure som administrerer:
Gratulerer! Du har nettopp bygget et sofistikert dra-og-slipp-system med ren JavaScript. Din komplette `dragElement`-funksjon inneholder nå en kraftig closure som håndterer:
**Hva din closure oppnår:**
**Hva closure-en din oppnår:**
- **Opprettholder** private posisjonsvariabler for hver plante uavhengig
- **Håndterer** hele dra-livssyklusen fra start til slutt
- **Håndterer** hele drag-livssyklusen fra start til slutt
- **Gir** jevn, responsiv bevegelse over hele skjermen
- **Rydder** opp ressurser riktig for å forhindre minnelekkasjer
- **Skaper** et intuitivt, kreativt grensesnitt for terrariumdesign
- **Rydder** opp ressursene korrekt for å forhindre minnelekkasjer
- **Skaper** et intuitivt, kreativt grensesnitt for terrarie-design
### Teste ditt interaktive terrarium
### Test ditt interaktive terrarium
Nå kan du teste ditt interaktive terrarium! Åpne `index.html`-filen i en nettleser og prøv funksjonaliteten:
1. **Klikk og hold** på en plante for å starte draingen
2. **Flytt musen eller fingeren** og se planten følge jevnt med
3. **Slipp** for å plassere planten i sin nye posisjon
4. **Eksperimenter** med ulike oppsett for å utforske grensesnittet
1. **Klikk og hold** på en plante for å begynne å dra
2. **Beveg musa eller finger** og se planten følge jevnt etter
3. **Slipp** for å slippe planten på den nye posisjonen
4. **Eksperimenter** med ulike arrangementer for å utforske grensesnittet
🥇 **Prestasjon**: Du har laget en fullt interaktiv webapplikasjon ved hjelp av kjerneprinsipper som profesjonelle utviklere bruker daglig. Dra-og-slipp-funksjonaliteten bruker de samme prinsippene som ligger bak filopplastinger, kanban-tavler og mange andre interaktive grensesnitt.
🥇 **Prestasjon**: Du har laget en fullt interaktiv webapplikasjon som bruker kjernekonsepter profesjonelle utviklere jobber med hver dag. Den drag-og-slipp-funksjonaliteten bruker de samme prinsippene bak filopplastinger, kanban-tavler og mange andre interaktive grensesnitt.
![ferdig terrarium](../../../../translated_images/terrarium-final.0920f16e87c13a84cd2b553a5af9a3ad1cffbd41fbf8ce715d9e9c43809a5e2c.no.png)
### 🔄 **Pedagogisk sjekk**
**Full systemforståelse**: Bekreft din mestring av hele drag-systemet:
- ✅ Hvordan opprettholder closures uavhengig tilstand for hver plante?
- ✅ Hvorfor er kokken for koordinatberegninger nødvendig for jevn bevegelse?
- ✅ Hva ville skje om vi glemte å rydde opp i event-lyttere?
- ✅ Hvordan skalerer dette mønsteret til mer komplekse interaksjoner?
**Kodekvalitetsrefleksjon**: Gå gjennom din komplette løsning:
- **Modulært design**: Hver plante får sin egen closure-instans
- **Effektiv hendelseshåndtering**: Riktig oppsett og opprydding av lyttere
- **Tverrplattformstøtte**: Fungerer på desktop og mobil
- **Ytelsesbevisst**: Ingen minnelekkasjer eller unødvendige beregninger
![finished terrarium](../../../../translated_images/terrarium-final.0920f16e87c13a84.no.png)
---
@ -415,70 +599,165 @@ Nå kan du teste ditt interaktive terrarium! Åpne `index.html`-filen i en nettl
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Forbedre terrarium-prosjektet ved å legge til en tilbakestillingsfunksjon som returnerer alle planter til sine opprinnelige posisjoner med jevne animasjoner.
**Beskrivelse:** Forbedre terrarie-prosjektet ved å legge til funksjonalitet for tilbakestilling som returnerer alle planter til sine opprinnelige posisjoner med glatte animasjoner.
**Prompt:** Lag en tilbakestillingsknapp som, når den klikkes, animerer alle planter tilbake til sine opprinnelige posisjoner i sidepanelet ved hjelp av CSS-overganger. Funksjonen skal lagre de opprinnelige posisjonene når siden lastes, og jevnt flytte plantene tilbake til disse posisjonene over 1 sekund når tilbakestillingsknappen trykkes.
**Oppgave:** Lag en tilbakestillingsknapp som, når den klikkes, animerer alle planter tilbake til deres originale sidebjellsposisjoner ved hjelp av CSS-overganger. Funksjonen skal lagre de opprinnelige posisjonene når siden lastes, og glatt overføre plantene tilbake til disse posisjonene over 1 sekund når tilbakestillingsknappen trykkes.
Les mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Ekstra utfordring: Utvid dine ferdigheter
## 🚀 Ekstrautfordring: Utvid ferdighetene dine
Klar for å ta terrariet ditt til neste nivå? Prøv å implementere disse forbedringene:
Klar for å løfte terrariet ditt til neste nivå? Prøv å implementere disse forbedringene:
**Kreative utvidelser:**
- **Dobbeltklikk** en plante for å bringe den til fronten (z-indeks-manipulasjon)
- **Legg til visuell tilbakemelding** som en subtil glød når du holder musen over planter
- **Dobbeltklikk** en plante for å bringe den til fronten (z-indeks-manipulasjon)
- **Legg til visuell tilbakemelding** som en subtil glød ved hover over planter
- **Implementer grenser** for å forhindre at planter dras utenfor terrariet
- **Lag en lagringsfunksjon** som husker planteposisjoner ved hjelp av localStorage
- **Legg til lydeffekter** for å plukke opp og plassere planter
- **Lag en lagrefunksjon** som husker planteposisjoner ved bruk av localStorage
- **Legg til lydeffekter** for plukking opp og sette ned planter
> 💡 **Læringsmulighet**: Hver av disse utfordringene vil lære deg nye aspekter ved DOM-manipulasjon, hendelseshåndtering og brukeropplevelsesdesign.
> 💡 **Læringsmulighet**: Hver av disse utfordringene vil lære deg nye aspekter av DOM-manipulering, hendelseshåndtering og brukeropplevelsesdesign.
## Quiz etter forelesning
## Quiz etter forelesningen
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/20)
[Quiz etter forelesningen](https://ff-quizzes.netlify.app/web/quiz/20)
## Gjennomgang og selvstudie: Fordyp deg i forståelsen
## Gjennomgang og selvstudie: Fordypning av forståelsen
Du har mestret det grunnleggende om DOM-manipulasjon og closures, men det er alltid mer å utforske! Her er noen veier for å utvide din kunnskap og ferdigheter.
Du har mestret grunnprinsippene for DOM-manipulering og closures, men det er alltid mer å utforske! Her er noen veier til å utvide kunnskap og ferdigheter.
### Alternative tilnærminger til dra-og-slipp
### Alternative tilnærminger til drag og drop
Vi brukte pekebegivenheter for maksimal fleksibilitet, men webutvikling tilbyr flere tilnærminger:
Vi brukte pointer events for maksimal fleksibilitet, men webutvikling tilbyr flere metoder:
| Tilnærming | Best for | Læringsverdi |
|------------|----------|--------------|
| [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) | Filopplastinger, formelle dra-soner | Forståelse av nettleserens innebygde funksjoner |
| [Touch Events](https://developer.mozilla.org/docs/Web/API/Touch_events) | Mobilspesifikke interaksjoner | Mobil-først utviklingsmønstre |
| CSS `transform`-egenskaper | Jevne animasjoner | Ytelsesoptimaliseringsteknikker |
| [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) | Filopplastinger, formelle dra-soner | Forstå native nettleserfunksjoner |
| [Touch Events](https://developer.mozilla.org/docs/Web/API/Touch_events) | Mobilspesifikke interaksjoner | Mobile-first utviklingsmønstre |
| CSS `transform`-egenskaper | Jevne animasjoner | Ytelsesoptimalisering |
### Avanserte emner innen DOM-manipulasjon
### Avanserte DOM-manipulasjonstemaer
**Neste steg i din læringsreise:**
- **Event-delegasjon**: Håndtere hendelser effektivt for flere elementer
- **Intersection Observer**: Oppdage når elementer kommer inn/ut av visningsområdet
- **Mutation Observer**: Overvåke endringer i DOM-strukturen
- **Web Components**: Lage gjenbrukbare, innkapslede UI-elementer
- **Virtuelle DOM-konsepter**: Forstå hvordan rammeverk optimaliserer DOM-oppdateringer
**Neste steg i læringen:**
- **Event delegation**: Effektiv hendelseshåndtering for flere elementer
- **Intersection Observer**: Oppdage når elementer kommer inn/forlater viewport
- **Mutation Observer**: Observere endringer i DOM-strukturen
- **Web Components**: Lage gjenbrukbare, kapslede UI-elementer
- **Virtual DOM-konsepter**: Forstå hvordan rammeverk optimaliserer DOM-oppdateringer
### Essensielle ressurser for videre læring
**Teknisk dokumentasjon:**
- [MDN Pointer Events Guide](https://developer.mozilla.org/docs/Web/API/Pointer_events) - Omfattende pekebegivenhetsreferanse
- [MDN Pointer Events Guide](https://developer.mozilla.org/docs/Web/API/Pointer_events) - Utførlig referanse for pointer events
- [W3C Pointer Events Specification](https://www.w3.org/TR/pointerevents1/) - Offisiell standarddokumentasjon
- [JavaScript Closures Deep Dive](https://developer.mozilla.org/docs/Web/JavaScript/Closures) - Avanserte closure-mønstre
**Nettleserkompatibilitet:**
- [CanIUse.com](https://caniuse.com/) - Sjekk funksjonsstøtte på tvers av nettlesere
- [CanIUse.com](https://caniuse.com/) - Sjekk støtte for funksjoner i ulike nettlesere
- [MDN Browser Compatibility Data](https://github.com/mdn/browser-compat-data) - Detaljert kompatibilitetsinformasjon
**Praksismuligheter:**
- **Bygg** et puslespill ved hjelp av lignende dra-mekanismer
- **Lag** en kanban-tavle med dra-og-slipp oppgavehåndtering
- **Design** et bildegalleri med flyttbare fotoarrangementer
- **Eksperimenter** med berøringsgester for mobilgrensesnitt
- **Lag** et puslespill med lignende drag-mekanismer
- **Bygg** en kanban-tavle med dra-og-slipp oppgavestyring
- **Design** et bildegalleri med draggable fotoarrangementer
- **Eksperimenter** med touch-gester for mobile grensesnitt
> 🎯 **Læringsstrategi**: Den beste måten å befeste disse konseptene på er gjennom praksis. Prøv å lage varianter av draggable grensesnitt hvert prosjekt vil lære deg noe nytt om brukerinteraksjon og DOM-manipulasjon.
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Åpne nettleserens DevTools og skriv `document.querySelector('body')` i konsollen
- [ ] Prøv å endre tekst på en nettside ved hjelp av `innerHTML` eller `textContent`
- [ ] Legg til en klikkhendelse til en knapp eller lenke på en nettside
- [ ] Undersøk DOM-trestrukturen i Elements-panelet
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør quizen og gjennomgå DOM-manipulasjonskonsepter
- [ ] Lag en interaktiv nettside som reagerer på brukerklikk
- [ ] Øv på hendelseshåndtering med ulike hendelsestyper (klikk, mouseover, tastetrykk)
- [ ] Bygg en enkel oppgaveliste eller teller med DOM-manipulasjon
- [ ] Utforsk forholdet mellom HTML-elementer og JavaScript-objekter
### 📅 **Din ukelange JavaScript-reise**
- [ ] Fullfør det interaktive terrarie-prosjektet med dra-og-slipp-funksjonalitet
- [ ] Mestre event delegation for effektiv hendelseshåndtering
- [ ] Lær om event loop og asynkron JavaScript
- [ ] Øv på closures ved å bygge moduler med privat tilstand
- [ ] Utforsk moderne DOM API-er som Intersection Observer
- [ ] Lag interaktive komponenter uten å bruke rammeverk
### 🌟 **Din månedslange JavaScript-mestring**
- [ ] Lag en kompleks single-page-applikasjon med ren JavaScript
- [ ] Lær et moderne rammeverk (React, Vue eller Angular) og sammenlign med ren DOM
- [ ] Bidra til open source JavaScript-prosjekter
- [ ] Mestre avanserte konsepter som web components og custom elements
- [ ] Bygg ytelsesoptimaliserte webapplikasjoner med gode DOM-mønstre
- [ ] Lær bort om DOM-manipulering og JavaScript-grunnprinsipper
## 🎯 Din JavaScript DOM-mestring tidslinje
```mermaid
timeline
title DOM & JavaScript Læringsprogresjon
section Grunnlag (15 minutter)
DOM Forståelse: Elementvalgmetoder
: Navigasjon i trestruktur
: Egenskapsakseseringsmønstre
section Hendelseshåndtering (20 minutter)
Brukerinteraksjon: Grunnleggende pekerenheter
: Oppsett av hendelseslytter
: Kompatibilitet på tvers av enheter
: Teknikker for hendelsesforebygging
section Closures (25 minutter)
Omfangshåndtering: Opprettelse av private variabler
: Funksjoners persistens
: Tilstandshåndteringsmønstre
: Minneeffektivitet
section Dra-system (30 minutter)
Interaktive funksjoner: Koordinatsporing
: Posisjonsberegning
: Bevegelsesmatematikk
: Ryddingsrutiner
section Avanserte mønstre (45 minutter)
Profesjonelle ferdigheter: Hendelsesdelegasjon
: Ytelsesoptimalisering
: Feilhåndtering
: Tilgjengelighetshensyn
section Rammeverkforståelse (1 uke)
Moderne utvikling: Virtuelle DOM-konsepter
: Tilstandshåndteringsbiblioteker
: Komponentarkitekturer
: Integrasjon av byggverktøy
section Ekspertnivå (1 måned)
Avanserte DOM-APIer: Intersection Observer
: Mutation Observer
: Egne elementer
: Webkomponenter
```
### 🛠️ Din oppsummering av JavaScript-verktøykasse
Etter å ha fullført denne leksjonen har du nå:
- **DOM-mestring**: Elementutvalg, egenskapsmanipulering og tre-navigering
- **Hendelsesekspertise**: Tverrplattform interaksjonshåndtering med pointer events
- **Forståelse av closures**: Privat tilstandsadministrasjon og funksjonens persistens
- **Interaktive systemer**: Full implementasjon av dra-og-slipp fra bunnen av
- **Ytelsesbevissthet**: Korrekt opprydding av hendelser og minnehåndtering
- **Moderne mønstre**: Kodeorganisering brukt i profesjonell utvikling
- **Brukeropplevelse**: Lage intuitive, responsive grensesnitt
**Profesjonelle ferdigheter tilegnet**: Du har bygget funksjoner med de samme teknikkene som:
- **Trello/Kanban-tavler**: Dra-kort mellom kolonner
- **Filopplasting**: Dra-og-slipp av filer
- **Bildegallerier**: Foto-arrangementgrensesnitt
- **Mobilapper**: Touch-baserte interaksjonsmønstre
> 🎯 **Læringsstrategi**: Den beste måten å styrke disse konseptene på er gjennom praksis. Prøv å bygge variasjoner av dra-grensesnitt hvert prosjekt vil lære deg noe nytt om brukerinteraksjon og DOM-manipulasjon.
**Neste nivå**: Du er klar til å utforske moderne rammeverk som React, Vue eller Angular som bygger på disse grunnleggende DOM-manipulasjonskonseptene!
## Oppgave
@ -486,5 +765,7 @@ Vi brukte pekebegivenheter for maksimal fleksibilitet, men webutvikling tilbyr f
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på originalsproget bør regnes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi påtar oss ikke ansvar for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,45 +1,30 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "7965cd2bc5dc92ad888dc4c6ab2ab70a",
"translation_date": "2025-08-26T21:28:30+00:00",
"original_hash": "bc5c5550f79d10add90ce419ee34abb3",
"translation_date": "2026-01-07T00:13:15+00:00",
"source_file": "3-terrarium/README.md",
"language_code": "no"
}
-->
# Mitt Terrarium: Et prosjekt for å lære om HTML, CSS og DOM-manipulering med JavaScript 🌵🌱
## Distribuer ditt Terrarium
En liten dra-og-slipp kode-meditasjon. Med litt HTML, JS og CSS vil du kunne bygge et webgrensesnitt, style det, og til og med legge til flere interaksjoner etter eget ønske.
![mitt terrarium](../../../translated_images/screenshot_gray.0c796099a1f9f25e40aa55ead81f268434c00af30d7092490759945eda63067d.no.png)
# Leksjoner
1. [Introduksjon til HTML](./1-intro-to-html/README.md)
2. [Introduksjon til CSS](./2-intro-to-css/README.md)
3. [Introduksjon til DOM og JS Closures](./3-intro-to-DOM-and-closures/README.md)
## Krediteringer
Skrevet med ♥️ av [Jen Looper](https://www.twitter.com/jenlooper)
Terrariet laget via CSS er inspirert av Jakub Mandras glasskrukke [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY).
Kunstverket er håndtegnet av [Jen Looper](http://jenlooper.com) med hjelp av Procreate.
## Publiser ditt Terrarium
Du kan publisere terrariet ditt på nettet ved hjelp av Azure Static Web Apps.
Du kan distribuere, eller publisere ditt Terrarium på nettet ved å bruke **Azure Static Web Apps**.
1. Fork dette repoet
2. Trykk på denne knappen
2. Trykk på denne knappen 👇
[![Deploy til Azure-knapp](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.StaticApp)
3. Følg veiviseren for å opprette appen din. Sørg for at du setter app-roten til enten `/solution` eller roten av kodebasen din. Det er ingen API i denne appen, så du trenger ikke bekymre deg for å legge til det. En GitHub-mappe vil bli opprettet i ditt forkede repository som vil hjelpe Azure Static Web Apps' byggeservice med å bygge og publisere appen din til en ny URL.
3. Følg oppsettveiviseren for å lage appen din.
- Sett **App root** til enten `/solution` eller roten av kodebasen din.
- Det er ingen API i denne appen, så du kan hoppe over API-konfigurasjonen.
- En `.github`-mappe vil bli laget automatisk for å hjelpe Azure Static Web Apps med å bygge og publisere appen din.
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi tilstreber nøyaktighet, vennligst vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på originalspråket bør betraktes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
En liten dra-og-slipp kode-meditasjon. Med litt HTML, JS og CSS kan du lage et webgrensesnitt, style det og legge til interaksjon.
![mitt terrarium](../../../../translated_images/screenshot_gray.0c796099a1f9f25e40aa55ead81f268434c00af30d7092490759945eda63067d.no.png)
![mitt terrarium](../../../../translated_images/screenshot_gray.0c796099a1f9f25e.no.png)
## Krediteringer

@ -1,48 +1,290 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "5adea7059676fcdb1b546ccd54c956c2",
"translation_date": "2025-10-23T22:34:14+00:00",
"original_hash": "efa2ab875b8bb5a7883816506da6b6d2",
"translation_date": "2026-01-07T00:12:22+00:00",
"source_file": "4-typing-game/README.md",
"language_code": "no"
}
-->
# Hendelsesdrevet programmering - Lag et skrive-spill
# Eventdrevet programmering - Lag et skrive-spill
```mermaid
journey
title Din utviklingsreise for skrive-spillet
section Grunnlag
Planlegg spillstruktur: 3: Student
Design brukergrensesnitt: 4: Student
Sett opp HTML-elementer: 4: Student
section Funksjonalitet
Håndter brukerinput: 4: Student
Spor tidtaking: 5: Student
Kalkuler nøyaktighet: 5: Student
section Funksjoner
Legg til visuell tilbakemelding: 5: Student
Implementer spilllogikk: 5: Student
Finpuss opplevelsen: 5: Student
```
## Introduksjon
Her er noe alle utviklere vet, men sjelden snakker om: å skrive raskt er en superkraft! 🚀 Tenk på det - jo raskere du kan få ideene dine fra hjernen til kodeeditoren, desto mer kan kreativiteten din flyte. Det er som å ha en direkte linje mellom tankene dine og skjermen.
Her er noe alle utviklere vet, men sjelden snakker om: å skrive raskt er en superkraft! 🚀 Tenk på det - jo raskere du kan få idéene dine fra hjernen til kodeditoren, desto mer kan kreativiteten flyte. Det er som å ha en direkte pipeline mellom tankene dine og skjermen.
Vil du vite en av de beste måtene å forbedre denne ferdigheten på? Du gjettet det - vi skal lage et spill!
```mermaid
pie title Spillfunksjoner
"Tilbakemelding i sanntid" : 25
"Ytelsessporing" : 20
"Interaktivt brukergrensesnitt" : 20
"Tidtakersystem" : 15
"Sitatbehandling" : 10
"Resultatvisning" : 10
```
Vil du vite en av de beste måtene å forbedre denne ferdigheten på? Du gjettet riktig - vi skal lage et spill!
```mermaid
flowchart LR
A[Spiller starter spillet] --> B[Tilfeldig sitat vises]
B --> C[Spiller skriver tegn]
C --> D{Tegnet korrekt?}
D -->|Ja| E[Grønn utheving]
D -->|Nei| F[Rød utheving]
E --> G[Oppdater nøyaktighet]
F --> G
G --> H{Sitat fullført?}
H -->|Nei| C
H -->|Ja| I[Beregn ord per minutt]
I --> J[Vis resultater]
J --> K[Spill igjen?]
K -->|Ja| B
K -->|Nei| L[Spillet er over]
style A fill:#e1f5fe
style D fill:#fff3e0
style E fill:#e8f5e8
style F fill:#ffebee
style I fill:#f3e5f5
```
> La oss lage et fantastisk skrive-spill sammen!
Klar til å bruke alle de JavaScript-, HTML- og CSS-ferdighetene du har lært? Vi skal lage et skrive-spill som utfordrer deg med tilfeldige sitater fra den legendariske detektiven [Sherlock Holmes](https://en.wikipedia.org/wiki/Sherlock_Holmes). Spillet vil måle hvor raskt og nøyaktig du kan skrive - og tro meg, det er mer avhengighetsskapende enn du kanskje tror!
Klar til å jobbe med alle de JavaScript-, HTML- og CSS-ferdighetene du har lært? Vi skal lage et skrive-spill som vil utfordre deg med tilfeldige sitater fra den legendariske detektiven [Sherlock Holmes](https://en.wikipedia.org/wiki/Sherlock_Holmes). Spillet vil spore hvor raskt og nøyaktig du kan skrive - og tro meg, det er mer vanedannende enn du kanskje tror!
```mermaid
mindmap
root((Utvikling av skrivespill))
User Interface
Inndataelementer
Visuell tilbakemelding
Responsivt design
Tilgjengelighet
Game Logic
Sitatvalg
Tidsstyring
Nøyaktighetssporing
Poengberegning
Event Handling
Tastaturinndata
Knappetrykk
Sanntidsoppdateringer
Spilltilstandsendringer
Performance Metrics
Ord per minutt
Tegnnøyaktighet
Feilsporing
Fremdriftsvisning
User Experience
Umiddelbar tilbakemelding
Klare instruksjoner
Engasjerende innhold
Prestasjonssystem
```
![demo](../../../4-typing-game/images/demo.gif)
## Hva du bør kunne
## Hva du trenger å kunne
Før vi setter i gang, sørg for at du er komfortabel med disse konseptene (ikke bekymre deg hvis du trenger en rask oppfriskning - vi har alle vært der!):
```mermaid
flowchart TD
A[Brukerhandling] --> B{Hendelsestype?}
B -->|Taste trykket| C[Tastaturhendelse]
B -->|Knappeklikk| D[Mus hendelse]
B -->|Tidsur| E[Tids hendelse]
C --> F[Sjekk tegn]
D --> G[Start/Nullstill spill]
E --> H[Oppdater tidsur]
F --> I{Riktig?}
I -->|Ja| J[Marker grønn]
I -->|Nei| K[Marker rød]
J --> L[Oppdater poengsum]
K --> L
L --> M[Sjekk spillstatus]
G --> N[Generer nytt sitat]
H --> O[Vis tid]
M --> P{Spillet fullført?}
P -->|Ja| Q[Vis resultater]
P -->|Nei| R[Fortsett spill]
style A fill:#e1f5fe
style F fill:#e8f5e8
style I fill:#fff3e0
style Q fill:#f3e5f5
```
Før vi begynner, sørg for at du er komfortabel med disse konseptene (ikke bekymre deg hvis du trenger en rask oppfriskning - vi har alle vært der!):
- Lage tekstinnskriving og knappkontroller
- Lage tekstinntak- og knappkontroller
- CSS og sette stiler ved hjelp av klasser
- Grunnleggende JavaScript
- Lage en array
- Lage et tilfeldig tall
- Hente gjeldende tid
- Hente nåværende tid
Hvis noe av dette føles litt rustent, er det helt greit! Noen ganger er den beste måten å styrke kunnskapen din på å hoppe inn i et prosjekt og finne ut av ting underveis.
Hvis noen av disse føles litt rustne, er det helt fint! Noen ganger er den beste måten å styrke kunnskapen på å hoppe inn i et prosjekt og finne ut av ting underveis.
## La oss bygge dette!
### 🔄 **Pedagogisk sjekk**
**Grunnvurdering**: Før du begynner utviklingen, sørg for at du forstår:
- ✅ Hvordan HTML-skjemaer og inntakselementer fungerer
- ✅ CSS-klasser og dynamisk styling
- ✅ JavaScript-hendelseslyttere og -håndterere
- ✅ Array-manipulering og tilfeldig utvalg
- ✅ Tidsmåling og beregninger
[Opprett et skrive-spill ved hjelp av hendelsesdrevet programmering](./typing-game/README.md)
**Rask selvtest**: Kan du forklare hvordan disse konseptene fungerer sammen i et interaktivt spill?
- **Hendelser** utløses når brukere interagerer med elementer
- **Håndterere** prosesserer hendelsene og oppdaterer spilltilstand
- **CSS** gir visuell tilbakemelding på brukerhandlinger
- **Timing** gjør det mulig å måle ytelse og spillutvikling
## Kreditering
```mermaid
quadrantChart
title Ferdighetsutvikling i skrivespill
x-axis Nybegynner --> Ekspert
y-axis Statisk --> Interaktiv
quadrant-1 Avanserte spill
quadrant-2 Sanntidsapper
quadrant-3 Grunnleggende sider
quadrant-4 Interaktive nettsteder
HTML Forms: [0.3, 0.2]
CSS Styling: [0.4, 0.3]
Event Handling: [0.7, 0.8]
Game Logic: [0.8, 0.9]
Performance Tracking: [0.9, 0.7]
```
## La oss lage dette!
[Opprette et skrive-spill ved å bruke eventdrevet programmering](./typing-game/README.md)
### ⚡ **Hva du kan gjøre på de neste 5 minuttene**
- [ ] Åpne nettleserkonsollen din og prøv å lytte etter tastaturhendelser med `addEventListener`
- [ ] Lag en enkel HTML-side med et inntaksfelt og test skrivegjenkjenning
- [ ] Øv på strengmanipulering ved å sammenligne skrevet tekst med måltekst
- [ ] Eksperimenter med `setTimeout` for å forstå tidsfunksjoner
### 🎯 **Hva du kan få til denne timen**
- [ ] Fullfør quiz etter leksjonen og forstå eventdrevet programmering
- [ ] Lag en grunnleggende versjon av skrive-spillet med ordvalidering
- [ ] Legg til visuell tilbakemelding for riktig og feil skriving
- [ ] Implementer et enkelt poengsystem basert på hastighet og nøyaktighet
- [ ] Style spillet ditt med CSS for å gjøre det visuelt tiltalende
### 📅 **Din ukelange spillutvikling**
- [ ] Fullfør det fullstendige skrive-spillet med alle funksjoner og finpuss
- [ ] Legg til vanskelighetsgrader med varierende ordkompleksitet
- [ ] Implementer statistikksporing for brukere (WPM, nøyaktighet over tid)
- [ ] Lag lydeffekter og animasjoner for bedre brukeropplevelse
- [ ] Gjør spillet ditt mobilvennlig for touch-enheter
- [ ] Del spillet ditt på nett og samle tilbakemeldinger fra brukere
### 🌟 **Din månedslange interaktive utvikling**
- [ ] Lag flere spill som utforsker ulike interaksjonsmønstre
- [ ] Lær om spill-løkker, tilstandshåndtering og ytelsesoptimalisering
- [ ] Bidra til open source prosjekter for spillutvikling
- [ ] Mestre avanserte tidskonsepter og jevne animasjoner
- [ ] Lag en portefølje som viser diverse interaktive applikasjoner
- [ ] Veiled andre som er interessert i spillutvikling og brukerinteraksjon
## 🎯 Din tidslinje for å mestre skrive-spillet
```mermaid
timeline
title Spillutvikling Læringsprogresjon
section Oppsett (10 minutter)
Prosjektstruktur: HTML grunnlag
: CSS styling oppsett
: JavaScript filopprettelse
section Brukergrensesnitt (20 minutter)
Interaktive Elementer: Inndatafelt
: Knappekontroller
: Visningsområder
: Responsivt oppsett
section Hendelseshåndtering (25 minutter)
Brukerinteraksjon: Tastaturhendelser
: Mus hendelser
: Tilbakemelding i sanntid
: Tilstandsbehandling
section Spilllogikk (30 minutter)
Kjernefunksjonalitet: Sitatgenerering
: Tegnsammenligning
: Nøyaktighetsberegning
: Timerimplementering
section Ytelsessporing (35 minutter)
Metrikker & Analyse: WPM-beregning
: Feilsporing
: Visualisering av fremgang
: Resultatvisning
section Polering & Forbedring (45 minutter)
Brukeropplevelse: Visuell tilbakemelding
: Lyd effekter
: Animasjoner
: Tilgangsfunksjoner
section Avanserte Funksjoner (1 uke)
Utvidet Funksjonalitet: Vanskelighetsnivåer
: Topplister
: Tilpassede sitater
: Flerspilleralternativer
section Profesjonelle Ferdigheter (1 måned)
Spillutvikling: Ytelsesoptimalisering
: Kodearkitektur
: Testing strategier
: Distribusjonsmønstre
```
### 🛠️ Oppsummering av ditt spillutviklingsverktøy
Etter å ha fullført dette prosjektet, vil du ha mestret:
- **Eventdrevet programmering**: Responsive brukergrensesnitt som reagerer på input
- **Sanntidstilbakemelding**: Øyeblikkelige visuelle og ytelsesoppdateringer
- **Ytelsesmåling**: Nøyaktige tids- og poengsystemer
- **Spilltilstandshåndtering**: Kontroll på applikasjonsflyt og brukeropplevelse
- **Interaktiv design**: Å skape engasjerende og vanedannende brukeropplevelser
- **Moderne Web-APIer**: Utnytte nettleserfunksjoner for rike interaksjoner
- **Tilgjengelighetsmønstre**: Inkluderende design for alle brukere
**Virkelige bruksområder**: Disse ferdighetene gjelder direkte til:
- **Webapplikasjoner**: Alle interaktive grensesnitt eller dashbord
- **Utdanningsprogramvare**: Læringsplattformer og ferdighetstestverktøy
- **Produktivitetsverktøy**: Tekstredigerere, IDEer og samarbeidsprogramvare
- **Spillindustrien**: Nettleserspill og interaktiv underholdning
- **Mobilutvikling**: Touchbaserte grensesnitt og gesthåndtering
**Neste nivå**: Du er klar til å utforske avanserte spillrammeverk, sanntid flerspillersystemer eller komplekse interaktive applikasjoner!
## Credits
Skrevet med ♥️ av [Christopher Harrison](http://www.twitter.com/geektrainer)
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved bruk av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst merk at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Originaldokumentet på dets opprinnelige språk skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi fraskriver oss ansvar for eventuelle misforståelser eller feiltolkninger som følge av bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,115 +1,114 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e6b75e5b8caae906473a8a09d77b7121",
"translation_date": "2025-10-23T22:34:20+00:00",
"original_hash": "da8bc72041a2bb3826a54654ee1a8844",
"translation_date": "2026-01-07T00:47:41+00:00",
"source_file": "4-typing-game/typing-game/README.md",
"language_code": "no"
}
-->
# Lage et spill ved hjelp av hendelser
Har du noen gang lurt på hvordan nettsteder vet når du klikker på en knapp eller skriver i en tekstboks? Det er magien med hendelsesdrevet programmering! Hva er vel bedre måte å lære denne essensielle ferdigheten på enn å bygge noe nyttig et skrivehastighetsspill som reagerer på hver tast du trykker.
Har du noen gang lurt på hvordan nettsteder vet når du klikker på en knapp eller skriver i en tekstboks? Det er magien ved hendelsesdrevet programmering! Hva er vel en bedre måte å lære denne viktige ferdigheten på enn å bygge noe nyttig et skrivhastighetsspill som reagerer på hvert tastetrykk du gjør.
Du kommer til å se med egne øyne hvordan nettlesere "snakker" med JavaScript-koden din. Hver gang du klikker, skriver eller beveger musen, sender nettleseren små meldinger (vi kaller dem hendelser) til koden din, og du får bestemme hvordan du skal reagere!
Du skal få se på nært hold hvordan nettlesere "snakker" med JavaScript-koden din. Hver gang du klikker, skriver eller flytter musen, sender nettleseren små meldinger (vi kaller dem hendelser) til koden din, og du bestemmer hvordan du vil svare!
Når vi er ferdige her, vil du ha bygget et ekte skrivehastighetsspill som sporer hastigheten og nøyaktigheten din. Enda viktigere, du vil forstå de grunnleggende konseptene som driver hver interaktive nettside du noen gang har brukt. La oss sette i gang!
Når vi er ferdige her, har du laget et ekte skrivspill som følger med på hastigheten og nøyaktigheten din. Enda viktigere er at du vil forstå de grunnleggende konseptene som driver hvert interaktivt nettsted du noen gang har brukt. La oss sette i gang!
## Quiz før forelesning
## Før-forelesnings-quiz
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/21)
[Før-forelesnings-quiz](https://ff-quizzes.netlify.app/web/quiz/21)
## Hendelsesdrevet programmering
Tenk på din favorittapp eller nettside hva gjør at den føles levende og responsiv? Det handler om hvordan den reagerer på det du gjør! Hver berøring, klikk, sveip eller tastetrykk skaper det vi kaller en "hendelse", og det er der den virkelige magien i webutvikling skjer.
Tenk på din favorittapp eller favorittnettsted hva gjør at det føles levende og responsivt? Det handler om hvordan det reagerer på det du gjør! Hvert trykk, klikk, sveip eller tastetrykk lager det vi kaller en "hendelse", og det er der den virkelige magien i webutvikling skjer.
Her er det som gjør programmering for nettet så interessant: vi vet aldri når noen vil klikke på den knappen eller begynne å skrive i en tekstboks. De kan klikke umiddelbart, vente fem minutter, eller kanskje aldri klikke i det hele tatt! Denne uforutsigbarheten betyr at vi må tenke annerledes om hvordan vi skriver koden vår.
Her er det som gjør programmering for nettet så interessant: vi vet aldri når noen vil klikke på knappen eller begynne å skrive i en tekstboks. De kan klikke med en gang, vente fem minutter, eller kanskje aldri klikke i det hele tatt! Denne uforutsigbarheten betyr at vi må tenke annerledes om hvordan vi skriver koden vår.
I stedet for å skrive kode som kjører fra topp til bunn som en oppskrift, skriver vi kode som sitter tålmodig og venter på at noe skal skje. Det er litt som hvordan telegrafoperatører på 1800-tallet satt ved maskinene sine, klare til å svare i det øyeblikket en melding kom gjennom ledningen.
I stedet for å skrive kode som kjører ovenfra og ned som en oppskrift, skriver vi kode som tålmodig venter på at noe skal skje. Det er likt hvordan telegrafoperatører på 1800-tallet satt ved maskinene sine, klare til å svare i det øyeblikket en melding kom gjennom ledningen.
hva er egentlig en "hendelse"? Enkelt sagt, det er noe som skjer! Når du klikker på en knapp det er en hendelse. Når du skriver en bokstav det er en hendelse. Når du beveger musen det er en annen hendelse.
Men hva er egentlig en "hendelse"? Enkelt sagt, det er noe som skjer! Når du klikker på en knapp det er en hendelse. Når du skriver en bokstav det er en hendelse. Når du flytter på musa det er en annen hendelse.
Hendelsesdrevet programmering lar oss sette opp koden vår til å lytte og reagere. Vi lager spesielle funksjoner kalt **hendelseslyttere** som venter tålmodig på spesifikke ting som skal skje, og som deretter reagerer når de gjør det.
Hendelsesdrevet programmering lar oss sette opp koden vår til å lytte og svare. Vi lager spesielle funksjoner kalt **event listeners** som tålmodig venter på at bestemte ting skal skje, og så setter i gang når de gjør det.
Tenk på hendelseslyttere som å ha en dørklokke for koden din. Du setter opp dørklokken (`addEventListener()`), forteller den hvilken lyd den skal lytte etter (som et 'klikk' eller 'tastetrykk'), og deretter spesifiserer hva som skal skje når noen ringer på (din tilpassede funksjon).
Tenk på event listeners som en dørklokke for koden din. Du setter opp dørklokken (`addEventListener()`), forteller den hva slags lyd den skal lytte etter (som et 'click' eller 'keypress'), og spesifiserer hva som skal skje når noen ringer på (din egendefinerte funksjon).
**Slik fungerer hendelseslyttere:**
**Slik fungerer event listeners:**
- **Lytter** etter spesifikke brukerhandlinger som klikk, tastetrykk eller musebevegelser
- **Utfører** din tilpassede kode når den spesifiserte hendelsen oppstår
- **Reagerer** umiddelbart på brukerinteraksjoner, og skaper en sømløs opplevelse
- **Håndterer** flere hendelser på samme element ved hjelp av forskjellige lyttere
- **Utfører** din egendefinerte kode når den angitte hendelsen skjer
- **Reagerer** umiddelbart på brukerinteraksjoner, skaper en sømløs opplevelse
- **Håndterer** flere hendelser på samme element ved hjelp av ulike lyttere
> **NOTE:** Det er verdt å fremheve at det finnes mange måter å lage hendelseslyttere på. Du kan bruke anonyme funksjoner eller lage navngitte. Du kan bruke ulike snarveier, som å sette `click`-egenskapen, eller bruke `addEventListener()`. I vår øvelse skal vi fokusere på `addEventListener()` og anonyme funksjoner, da det sannsynligvis er den mest vanlige teknikken webutviklere bruker. Det er også den mest fleksible, ettersom `addEventListener()` fungerer for alle hendelser, og hendelsesnavnet kan gis som en parameter.
> **MERK:** Det er verdt å nevne at det finnes mange måter å lage event listeners på. Du kan bruke anonyme funksjoner, eller lage navngitte funksjoner. Du kan bruke forskjellige snarveier, som å sette `click`-egenskapen, eller bruke `addEventListener()`. I øvelsen vår skal vi fokusere på `addEventListener()` og anonyme funksjoner, siden det sannsynligvis er den vanligste teknikken webutviklere bruker. Det er også den mest fleksible, da `addEventListener()` fungerer for alle hendelser, og hendelsesnavnet kan gis som en parameter.
### Vanlige hendelser
Selv om nettlesere tilbyr dusinvis av forskjellige hendelser du kan lytte etter, er det de mest grunnleggende hendelsene som de fleste interaktive applikasjoner er avhengige av. Å forstå disse kjernehendelsene vil gi deg grunnlaget for å bygge sofistikerte brukerinteraksjoner.
Selv om nettlesere tilbyr dusinvis av forskjellige hendelser du kan lytte etter, baserer de fleste interaktive apper seg på bare noen få essensielle hendelser. Å forstå disse kjernehendelsene gir deg fundamentet for å bygge sofistikerte brukerinteraksjoner.
Det finnes [mange hendelser](https://developer.mozilla.org/docs/Web/Events) du kan lytte etter når du lager en applikasjon. I utgangspunktet vil alt en bruker gjør på en side utløse en hendelse, noe som gir deg mye makt til å sikre at de får den opplevelsen du ønsker. Heldigvis trenger du vanligvis bare et lite utvalg av hendelser. Her er noen vanlige (inkludert de to vi skal bruke når vi lager spillet vårt):
Det finnes [dusiner av hendelser](https://developer.mozilla.org/docs/Web/Events) tilgjengelig som du kan lytte etter når du lager en applikasjon. I utgangspunktet løfter alt brukeren gjør på en side en hendelse, noe som gir deg stor kraft til å sikre at de får den opplevelsen du ønsker. Heldigvis trenger du vanligvis bare noen få hendelser. Her er noen vanlige (inkludert de to vi skal bruke i spillet vårt):
| Hendelse | Beskrivelse | Vanlige bruksområder |
|----------|-------------|-----------------------|
| `click` | Brukeren klikket på noe | Knapp, lenker, interaktive elementer |
| `contextmenu` | Brukeren høyreklikket | Tilpassede høyreklikkmenyer |
| `select` | Brukeren markerte tekst | Tekstredigering, kopieringsoperasjoner |
| Hendelse | Beskrivelse | Vanlige Bruksområder |
|----------|-------------|----------------------|
| `click` | Brukeren klikket på noe | Knapper, lenker, interaktive elementer |
| `contextmenu` | Brukeren klikket med høyre museknapp | Egne høyreklikk-menyvalg |
| `select` | Brukeren markerte noe tekst | Tekstredigering, kopiering |
| `input` | Brukeren skrev inn tekst | Skjemavalidering, sanntidssøk |
**Forstå disse hendelsestypene:**
- **Utløses** når brukere interagerer med spesifikke elementer på siden din
- **Gir** detaljert informasjon om brukerens handling gjennom hendelsesobjekter
- **Muliggjør** at du kan lage responsive, interaktive webapplikasjoner
- **Utløses** når brukere interagerer med bestemte elementer på siden din
- **Gir** detaljert informasjon om brukerens handling via hendelsesobjekter
- **Lar deg** lage responsive, interaktive nettapplikasjoner
- **Fungerer** konsekvent på tvers av forskjellige nettlesere og enheter
## Lage spillet
Nå som du forstår hvordan hendelser fungerer, la oss sette den kunnskapen ut i praksis ved å lage noe nyttig. Vi skal lage et skrivehastighetsspill som demonstrerer hendelseshåndtering samtidig som det hjelper deg med å utvikle en viktig ferdighet som utvikler.
Nå som du forstår hvordan hendelser fungerer, la oss bruke kunnskapen i praksis ved å lage noe nyttig. Vi skal lage et skrivhastighetsspill som demonstrerer håndtering av hendelser samtidig som du utvikler en viktig utviklerferdighet.
Vi skal lage et spill for å utforske hvordan hendelser fungerer i JavaScript. Spillet vårt vil teste en spillers skriveferdigheter, som er en av de mest undervurderte ferdighetene alle utviklere bør ha. Fun fact: QWERTY-tastaturoppsettet vi bruker i dag ble faktisk designet på 1870-tallet for skrivemaskiner og gode skriveferdigheter er fortsatt like verdifulle for programmerere i dag! Den generelle flyten i spillet vil se slik ut:
Vi skal lage et spill for å utforske hvordan hendelser fungerer i JavaScript. Spillet vårt skal teste spillerens skrivingsevner, noe som er en av de mest undervurderte ferdighetene alle utviklere bør ha. Moro fakta: QWERTY-tastaturoppsettet vi bruker i dag, ble faktisk designet på 1870-tallet for skrivemaskiner og gode skriveferdigheter er fortsatt like verdifulle for programmerere i dag! Spillflyten vår vil se slik ut:
```mermaid
flowchart TD
A[Player clicks Start] --> B[Random quote displays]
B --> C[Player types in textbox]
C --> D{Word complete?}
D -->|Yes| E[Highlight next word]
D -->|No| F{Correct so far?}
F -->|Yes| G[Keep normal styling]
F -->|No| H[Show error styling]
E --> I{Quote complete?}
I -->|No| C
I -->|Yes| J[Show success message with time]
A[Spiller klikker Start] --> B[Tilfeldig sitat vises]
B --> C[Spiller skriver i tekstboksen]
C --> D{Ord fullført?}
D -->|Ja| E[Fremhev neste ord]
D -->|Nei| F{Riktig så langt?}
F -->|Ja| G[Behold normal stil]
F -->|Nei| H[Vis feilstil]
E --> I{Sitat fullført?}
I -->|Nei| C
I -->|Ja| J[Vis suksessmelding med tid]
G --> C
H --> C
```
**Slik fungerer spillet vårt:**
- **Starter** når spilleren klikker på startknappen og viser et tilfeldig sitat
- **Sporer** spillerens skriveprogresjon ord for ord i sanntid
- **Fremhever** det aktuelle ordet for å veilede spillerens fokus
- **Gir** umiddelbar visuell tilbakemelding for skrivefeil
- **Fremhever** det nåværende ordet for å lede spillerens fokus
- **Gir** umiddelbar visuell tilbakemelding ved skrivefeil
- **Beregner** og viser total tid når sitatet er fullført
La oss bygge spillet vårt og lære om hendelser!
### Filstruktur
Før vi begynner å kode, la oss organisere oss! Å ha en ryddig filstruktur fra begynnelsen vil spare deg for hodebry senere og gjøre prosjektet ditt mer profesjonelt. 😊
Før vi begynner å kode, la oss få orden på ting! Å ha en ryddig filstruktur helt fra starten vil spare deg for mye trøbbel senere og gjøre prosjektet ditt mer profesjonelt. 😊
Vi skal holde det enkelt med bare tre filer: `index.html` for strukturen på siden vår, `script.js` for all spilllogikken, og `style.css` for å få alt til å se bra ut. Dette er den klassiske trioen som driver mesteparten av nettet!
Vi skal holde det enkelt med bare tre filer: `index.html` for sidestrukturen, `script.js` for all spilllogikken, og `style.css` for å få alt til å se bra ut. Dette er den klassiske trioen som driver mesteparten av nettet!
**Opprett en ny mappe for arbeidet ditt ved å åpne en konsoll eller terminalvindu og skrive følgende kommando:**
**Lag en ny mappe til arbeidet ditt ved å åpne en konsoll- eller terminalvindu og skrive følgende kommando:**
```bash
# Linux or macOS
# Linux eller macOS
mkdir typing-game && cd typing-game
# Windows
md typing-game && cd typing-game
```
**Dette gjør kommandoene:**
- **Oppretter** en ny katalog kalt `typing-game` for prosjektfilene dine
- **Navigerer** automatisk inn i den nyopprettede katalogen
**Dette gjør disse kommandoene:**
- **Oppretter** en ny mappe kalt `typing-game` for prosjektfilene dine
- **Går inn i** den nylig opprettede mappen automatisk
- **Setter opp** et rent arbeidsområde for spillutviklingen din
**Åpne Visual Studio Code:**
@ -119,37 +118,37 @@ code .
```
**Denne kommandoen:**
- **Starter** Visual Studio Code i den gjeldende katalogen
- **Åpner** prosjektmappen din i editoren
- **Starter** Visual Studio Code i gjeldende mappe
- **Åpner** prosjektmappen i editoren
- **Gir** tilgang til alle utviklingsverktøyene du trenger
**Legg til tre filer i mappen i Visual Studio Code med følgende navn:**
- `index.html` - Inneholder strukturen og innholdet til spillet ditt
- `script.js` - Håndterer all spilllogikk og hendelseslyttere
- `style.css` - Definerer det visuelle utseendet og stilen
- `index.html` - Inneholder strukturen og innholdet i spillet ditt
- `script.js` - Håndterer all spilllogikk og event listeners
- `style.css` - Definerer det visuelle uttrykket og stilen
## Lag brukergrensesnittet
Nå skal vi bygge scenen der all spillaktiviteten vil skje! Tenk på dette som å designe kontrollpanelet for et romskip vi må sørge for at alt spillerne våre trenger er akkurat der de forventer det.
Nå skal vi bygge scenen hvor all spillaktiviteten skjer! Tenk på det som å designe kontrollpanelet for et romskip vi må sørge for at alt spillerne trenger er akkurat der de forventer det.
La oss finne ut hva spillet vårt faktisk trenger. Hvis du spilte et skrivehastighetsspill, hva ville du ønsket å se på skjermen? Her er hva vi trenger:
La oss finne ut hva spillet vårt faktisk trenger. Om du skulle spilt et skrivspill, hva ville du ønsket å se på skjermen? Her er hva vi trenger:
| UI-element | Formål | HTML-element |
|------------|--------|--------------|
| Sitatvisning | Viser teksten som skal skrives | `<p>` med `id="quote"` |
| Meldingsområde | Viser status- og suksessmeldinger | `<p>` med `id="message"` |
| Tekstfelt | Der spillerne skriver inn sitatet | `<input>` med `id="typed-value"` |
| Meldingområde | Viser status- og suksessmeldinger | `<p>` med `id="message"` |
| Tekstinnskriving | Hvor spilleren skriver sitatet | `<input>` med `id="typed-value"` |
| Startknapp | Starter spillet | `<button>` med `id="start"` |
**Forstå UI-strukturen:**
**Forstå brukergrensesnittets struktur:**
- **Organiserer** innhold logisk fra topp til bunn
- **Tildeler** unike ID-er til elementer for JavaScript-målretting
- **Gir** en klar visuell hierarki for bedre brukeropplevelse
- **Tilordner** unike ID-er til elementer for JavaScript
- **Gir** klar visuell hierarki for bedre brukeropplevelse
- **Inkluderer** semantiske HTML-elementer for tilgjengelighet
Hvert av disse elementene trenger ID-er slik at vi kan jobbe med dem i JavaScript. Vi vil også legge til referanser til CSS- og JavaScript-filene vi skal lage.
Hvert av disse trenger ID-er slik at vi kan jobbe med dem i JavaScript. Vi legger også til referanser til CSS- og JavaScript-filene vi skal lage.
Opprett en ny fil med navnet `index.html`. Legg til følgende HTML:
Lag en ny fil som heter `index.html`. Legg til følgende HTML:
```html
<!-- inside index.html -->
@ -172,52 +171,52 @@ Opprett en ny fil med navnet `index.html`. Legg til følgende HTML:
</html>
```
**Hva denne HTML-strukturen oppnår:**
- **Lenker** CSS-stilarket i `<head>` for styling
- **Oppretter** en klar overskrift og instruksjoner for brukere
**Dette oppnår HTML-strukturen:**
- **Lenker** til CSS-stylesheet i `<head>` for styling
- **Oppretter** en tydelig overskrift og instruksjoner til brukeren
- **Etablerer** plassholderavsnitt med spesifikke ID-er for dynamisk innhold
- **Inkluderer** et inndatafelt med tilgjengelighetsattributter
- **Gir** en startknapp for å starte spillet
- **Tilbyr** en startknapp for å starte spillet
- **Laster** JavaScript-filen til slutt for optimal ytelse
### Start applikasjonen
Å teste applikasjonen din ofte under utvikling hjelper deg med å oppdage problemer tidlig og se fremgangen din i sanntid. Live Server er et uvurderlig verktøy som automatisk oppdaterer nettleseren din hver gang du lagrer endringer, noe som gjør utviklingen mye mer effektiv.
Det er lurt å teste applikasjonen ofte under utviklingen slik at du oppdager problemer tidlig og kan følge fremgangen i sanntid. Live Server er et uvurderlig verktøy som automatisk oppdaterer nettleseren hver gang du lagrer endringer, noe som gjør utviklingen mye mer effektiv.
Det er alltid best å utvikle iterativt for å se hvordan ting ser ut. La oss starte applikasjonen. Det finnes en fantastisk utvidelse for Visual Studio Code kalt [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) som både vil være vert for applikasjonen din lokalt og oppdatere nettleseren hver gang du lagrer.
Det er alltid best å utvikle trinnvis slik at du kan se hvordan ting ser ut. La oss starte applikasjonen vår. Det finnes en flott utvidelse til Visual Studio Code som heter [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) som både kan være lokal vert for applikasjonen og oppdatere nettleseren hver gang du lagrer.
**Installer [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) ved å følge lenken og klikke på Installer:**
**Installer [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) ved å følge lenken og klikke på Install:**
**Hva som skjer under installasjonen:**
- **Åpner** Visual Studio Code i nettleseren din
- **Veileder** deg gjennom installasjonsprosessen for utvidelsen
**Dette skjer under installasjonen:**
- **Ber** nettleseren din om å åpne Visual Studio Code
- **Veileder** deg gjennom utvidelsesinstallasjonsprosessen
- **Kan kreve** at du starter Visual Studio Code på nytt for å fullføre oppsettet
**Når det er installert, i Visual Studio Code, trykk Ctrl-Shift-P (eller Cmd-Shift-P) for å åpne kommandopaletten:**
**Når den er installert, trykk Ctrl-Shift-P (eller Cmd-Shift-P) i Visual Studio Code for å åpne kommandopaletten:**
**Forstå kommandopaletten:**
- **Gir** rask tilgang til alle VS Code-kommandoer
- **Søker** etter kommandoer mens du skriver
- **Tilbyr** hurtigtaster for raskere utvikling
- **Tilbyr** tastatursnarveier for raskere utvikling
**Skriv "Live Server: Open with Live Server":**
**Hva Live Server gjør:**
**Dette gjør Live Server:**
- **Starter** en lokal utviklingsserver for prosjektet ditt
- **Oppdaterer** nettleseren automatisk når du lagrer filer
- **Oppdaterer** nettleseren automatisk ved lagring av filer
- **Serverer** filene dine fra en lokal URL (vanligvis `localhost:5500`)
**Åpne en nettleser og naviger til `https://localhost:5500`:**
**Åpne en nettleser og til `https://localhost:5500`:**
Du skal nå se siden du har laget! La oss legge til litt funksjonalitet.
Du skal nå se siden du laget! La oss legge til funksjonalitet.
## Legg til CSS
Nå skal vi få ting til å se bra ut! Visuell tilbakemelding har vært avgjørende for brukergrensesnitt siden de tidlige dagene av databehandling. På 1980-tallet oppdaget forskere at umiddelbar visuell tilbakemelding dramatisk forbedrer brukerprestasjon og reduserer feil. Det er akkurat det vi skal lage.
Nå skal vi få ting til å se bra ut! Visuell tilbakemelding har vært avgjørende for brukergrensesnitt siden datamaskintidenes begynnelse. På 1980-tallet oppdaget forskere at umiddelbar visuell tilbakemelding dramatisk forbedrer brukerens ytelse og reduserer feil. Det er nettopp det vi skal lage.
Spillet vårt må være krystallklart om hva som skjer. Spillere skal umiddelbart vite hvilket ord de skal skrive, og hvis de gjør en feil, skal de se det med en gang. La oss lage en enkel, men effektiv styling:
Spillet vårt må være krystallklart på hva som skjer. Spillere bør umiddelbart vite hvilket ord de skal skrive, og om de gjør en feil, skal de se det med en gang. La oss lage enkel, men effektiv styling:
Opprett en ny fil med navnet `style.css` og legg til følgende syntaks.
Lag en ny fil som heter `style.css` og legg til følgende syntaks.
```css
/* inside style.css */
@ -232,59 +231,60 @@ Opprett en ny fil med navnet `style.css` og legg til følgende syntaks.
```
**Forstå disse CSS-klassene:**
- **Fremhever** det aktuelle ordet med en gul bakgrunn for klar visuell veiledning
- **Signalerer** skrivefeil med en lys korall bakgrunnsfarge
- **Gir** umiddelbar tilbakemelding uten å forstyrre brukerens skriveflyt
- **Bruker** kontrastfarger for tilgjengelighet og klar visuell kommunikasjon
- **Fremhever** det nåværende ordet med gul bakgrunn for tydelig visuell veiledning
- **Signaliserer** skrivefeil med en lys korallfarget bakgrunn
- **Gir** umiddelbar tilbakemelding uten å forstyrre skrivingen
- **Bruker** kontrasterende farger for tilgjengelighet og klar visuell kommunikasjon
✅ Når det gjelder CSS, kan du utforme siden din slik du ønsker. Ta litt tid og gjør siden mer tiltalende:
✅ Når det kommer til CSS kan du legge opp siden din akkurat som du vil. Ta litt tid og gjør siden mer tiltalende:
- Velg en annen font
- Fargelegg overskriftene
- Endre størrelsen på elementene
- Velg et annet fontsett
- Farg overskriftene
- Endre størrelse på elementene
## JavaScript
Her blir det interessant! 🎉 Vi har HTML-strukturen og CSS-stylingen, men akkurat nå er spillet vårt som en vakker bil uten motor. JavaScript skal være den motoren det er det som får alt til å fungere og reagere på det spillerne gjør.
Her begynner det å bli interessant! 🎉 Vi har HTML-strukturen vår og CSS-stylingen, men akkurat nå er spillet vårt som en vakker bil uten motor. JavaScript blir motoren det som gjør at alt faktisk fungerer og reagerer på det spillerne gjør.
Dette er hvor du vil se kreasjonen din komme til live. Vi skal takle dette steg for steg slik at ingenting føles overveldende:
Her vil du se skapelsen din komme til liv. Vi tar det steg for steg så ingenting føles overveldende:
| Steg | Formål | Hva du lærer |
|------|--------|--------------|
| [Lag konstantene](../../../../4-typing-game/typing-game) | Sett opp sitater og DOM-referanser | Variabelhåndtering og DOM-seleksjon |
| [Hendelseslytter for å starte spillet](../../../../4-typing-game/typing-game) | Håndter spillinitiering | Hendelseshåndtering og UI-oppdateringer |
| [Hendelseslytter for skriving](../../../../4-typing-game/typing-game) | Prosesser brukerinput i sanntid | Inputvalidering og dynamisk tilbakemelding |
|-------|---------|--------------|
| [Lag konstantene](../../../../4-typing-game/typing-game) | Sett opp sitater og DOM-referanser | Variabelhåndtering og DOM-utvalg |
| [Event listener for å starte spillet](../../../../4-typing-game/typing-game) | Håndter spillinitiering | Hendelseshåndtering og UI-oppdateringer |
| [Event listener for skriving](../../../../4-typing-game/typing-game) | Prosesser brukerinput i sanntid | Inputvalidering og dynamisk tilbakemelding |
**Denne strukturerte tilnærmingen hjelper deg:**
- **Organisere** koden din i logiske, håndterbare seksjoner
- **Bygge** funksjonalitet gradvis for enklere feilsøking
- **Forstå** hvordan forskjellige deler av applikasjonen din fungerer sammen
- **Skape** gjenbrukbare mønstre for fremtidige prosjekter
**Denne strukturerte tilnærmingen hjelper deg å:**
- **Organisere** koden i logiske og håndterbare seksjoner
- **Bygge** funksjonalitet trinnvis for enklere feilsøking
- **Forstå** hvordan ulike deler av applikasjonen jobber sammen
- **Skape** gjenbruksmønstre til fremtidige prosjekter
Men først, opprett en ny fil med navnet `script.js`.
Men først, lag en ny fil som heter `script.js`.
### Legg til konstantene
### Lag konstantene
Før vi dykker inn i handlingen, la oss samle alle ressursene våre! Akkurat som hvordan NASA sitt kontrollsenter setter opp alle overvåkingssystemene sine før oppskyting, er det mye enklere når du har alt forberedt og klart. Dette sparer oss fra å lete etter ting senere og hjelper med å unngå skrivefeil.
Før vi setter i gang, la oss samle alle ressursene våre! På samme måte som NASA sin kontrollrom setter opp alle overvåkingssystemene før oppskytning, er det mye enklere når du har alt klart og ferdig. Dette sparer oss fra å lete rundt senere og unngår skrivefeil.
Her er hva vi trenger å sette opp først:
Her er det vi må sette opp først:
| Datatype | Formål | Eksempel |
| Array av sitater | Lagre alle mulige sitater for spillet | `['Sitat 1', 'Sitat 2', ...]` |
| Ord-array | Del opp det nåværende sitatet i individuelle ord | `['Når', 'du', 'har', ...]` |
| Ordindeks | Følg med på hvilket ord spilleren skriver | `0, 1, 2, 3...` |
| Starttid | Beregn forløpt tid for poengberegning | `Date.now()` |
|-----------|---------|----------|
| Array of quotes | Lagre alle mulige sitater for spillet | `['Quote 1', 'Quote 2', ...]` |
| Word array | Del opp gjeldende sitat i individuelle ord | `['When', 'you', 'have', ...]` |
| Word index | Følg med på hvilket ord spilleren skriver | `0, 1, 2, 3...` |
| Start time | Beregn forløpt tid for poengberegning | `Date.now()` |
**Vi trenger også referanser til våre UI-elementer:**
**Vi trenger også referanser til brukergrensesnitt-elementene våre:**
| Element | ID | Formål |
|---------|----|---------|
| Tekstfelt | `typed-value` | Hvor spillere skriver |
| Tekstinput | `typed-value` | Hvor spillerne skriver |
| Sitatvisning | `quote` | Viser sitatet som skal skrives |
| Meldingsområde | `message` | Viser statusoppdateringer |
| Meldingområde | `message` | Viser statusoppdateringer |
```javascript
// inside script.js
// all of our quotes
// inne i script.js
// alle våre sitater
const quotes = [
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
'There is nothing more deceptive than an obvious fact.',
@ -294,77 +294,77 @@ const quotes = [
'Nothing clears up a case so much as stating it to another person.',
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
];
// store the list of words and the index of the word the player is currently typing
// lagre listen over ord og indeksen til ordet spilleren skriver for øyeblikket
let words = [];
let wordIndex = 0;
// the starting time
// starttiden
let startTime = Date.now();
// page elements
// sideelementer
const quoteElement = document.getElementById('quote');
const messageElement = document.getElementById('message');
const typedValueElement = document.getElementById('typed-value');
```
**Hva denne oppsett-koden oppnår:**
- **Lagrer** en liste med Sherlock Holmes-sitater ved hjelp av `const` siden sitatene ikke vil endres
- **Initialiserer** sporingsvariabler med `let` siden disse verdiene vil oppdateres under spillet
- **Henter** referanser til DOM-elementer ved hjelp av `document.getElementById()` for effektiv tilgang
**Bryter ned hva denne oppsettkoden oppnår:**
- **Lagrer** en array med Sherlock Holmes-sitater ved bruk av `const` siden sitatene ikke endres
- **Initialiserer** sporingsvariabler med `let` fordi disse verdiene oppdateres under spill
- **Fanger opp** referanser til DOM-elementer ved bruk av `document.getElementById()` for effektiv tilgang
- **Setter opp** grunnlaget for all spillfunksjonalitet med klare, beskrivende variabelnavn
- **Organiserer** relaterte data og elementer logisk for enklere vedlikehold av koden
- **Organiserer** relaterte data og elementer logisk for enklere vedlikehold av kode
✅ Gå videre og legg til flere sitater i spillet ditt
> 💡 **Profftips**: Vi kan hente elementene når som helst i koden ved å bruke `document.getElementById()`. Siden vi kommer til å referere til disse elementene regelmessig, kan vi unngå skrivefeil i strenglitteraler ved å bruke konstanter. Rammeverk som [Vue.js](https://vuejs.org/) eller [React](https://reactjs.org/) kan hjelpe deg med å bedre sentralisere koden din.
> 💡 **Profftips**: Vi kan hente elementene når som helst i koden ved bruk av `document.getElementById()`. Fordi vi skal referere til disse elementene jevnlig, unngår vi skrivefeil ved å bruke konstanter. Rammeverk som [Vue.js](https://vuejs.org/) eller [React](https://reactjs.org/) kan hjelpe deg med bedre sentralisering av koden.
>
**Hvorfor denne tilnærmingen fungerer så bra:**
- **Forhindrer** skrivefeil når elementer refereres til flere ganger
- **Forbedrer** lesbarheten i koden med beskrivende konstantnavn
- **Muliggjør** bedre støtte fra IDE med autofullføring og feilsjekk
- **Gjør** refaktorering enklere hvis element-ID-er endres senere
**Her er hvorfor denne tilnærmingen fungerer så godt:**
- **Forhindrer** stavefeil når elementer refereres flere ganger
- **Forbedrer** kode-lesbarhet med beskrivende konstantnavn
- **Muliggjør** bedre IDE-støtte med autoutfylling og feilsjekk
- **Gjør** refaktorering enklere om element-IDer endres senere
Ta et øyeblikk til å se en video om bruk av `const`, `let` og `var`
Ta et minutt og se en video om bruk av `const`, `let` og `var`
[![Typer av variabler](https://img.youtube.com/vi/JNIXfGiDWM8/0.jpg)](https://youtube.com/watch?v=JNIXfGiDWM8 "Typer av variabler")
[![Typer variabler](https://img.youtube.com/vi/JNIXfGiDWM8/0.jpg)](https://youtube.com/watch?v=JNIXfGiDWM8 "Typer variabler")
> 🎥 Klikk på bildet over for en video om variabler.
### Legg til startlogikk
Nå begynner det å skje! 🚀 Du er i ferd med å skrive din første ekte event listener, og det er noe ganske tilfredsstillende med å se koden din reagere på et knappetrykk.
Her kommer alt på plass! 🚀 Du er i ferd med å skrive din første virkelige eventlistener, og det er ganske tilfredsstillende å se koden din respondere på et knappetrykk.
Tenk på det: et sted der ute kommer en spiller til å klikke på "Start"-knappen, og koden din må være klar for dem. Vi har ingen anelse om når de vil klikke - det kan være med en gang, eller etter at de har hentet en kopp kaffe - men når de gjør det, våkner spillet ditt til liv.
Tenk på det: et sted der ute kommer en spiller til å trykke på "Start"-knappen, og koden din må være klar. Vi vet ikke når de klikker det kan være med en gang, eller etter at de har tatt seg en kaffe men når de gjør det, våkner spillet til liv.
Når brukeren klikker `start`, må vi velge et sitat, sette opp brukergrensesnittet og sette opp sporing for det nåværende ordet og tiden. Nedenfor er JavaScript-koden du må legge til; vi diskuterer den rett etter skriptblokken.
Når brukeren klikker `start`, må vi velge et sitat, sette opp UI, og starte sporing for gjeldende ord og tidtaking. Nedenfor er JavaScripten du må legge til; vi forklarer det rett etter kodeblokken.
```javascript
// at the end of script.js
// på slutten av script.js
document.getElementById('start').addEventListener('click', () => {
// get a quote
// hent et sitat
const quoteIndex = Math.floor(Math.random() * quotes.length);
const quote = quotes[quoteIndex];
// Put the quote into an array of words
// Sett sitatet inn i en matrise av ord
words = quote.split(' ');
// reset the word index for tracking
// tilbakestill ordindeksen for sporing
wordIndex = 0;
// UI updates
// Create an array of span elements so we can set a class
// UI-oppdateringer
// Lag en matrise av span-elementer slik at vi kan sette en klasse
const spanWords = words.map(function(word) { return `<span>${word} </span>`});
// Convert into string and set as innerHTML on quote display
// Konverter til streng og sett som innerHTML på sitatvisning
quoteElement.innerHTML = spanWords.join('');
// Highlight the first word
// Fremhev det første ordet
quoteElement.childNodes[0].className = 'highlight';
// Clear any prior messages
// Fjern eventuelle tidligere meldinger
messageElement.innerText = '';
// Setup the textbox
// Clear the textbox
// Sett opp tekstboksen
// Tøm tekstboksen
typedValueElement.value = '';
// set focus
// sett fokus
typedValueElement.focus();
// set the event handler
// sett hendelsesbehandleren
// Start the timer
// Start timeren
startTime = new Date().getTime();
});
```
@ -372,131 +372,130 @@ document.getElementById('start').addEventListener('click', () => {
**La oss dele opp koden i logiske seksjoner:**
**📊 Oppsett for ordsporing:**
- **Velger** et tilfeldig sitat ved hjelp av `Math.floor()` og `Math.random()` for variasjon
- **Konverterer** sitatet til en liste med individuelle ord ved hjelp av `split(' ')`
- **Nullstiller** `wordIndex` til 0 siden spillere starter med det første ordet
- **Velger** et tilfeldig sitat med `Math.floor()` og `Math.random()` for variasjon
- **Konverterer** sitatet til en array med individuelle ord ved bruk av `split(' ')`
- **Nullstiller** `wordIndex` til 0 siden spillerne starter på første ord
- **Forbereder** spilltilstanden for en ny runde
**🎨 Oppsett og visning av brukergrensesnitt:**
- **Oppretter** en liste med `<span>`-elementer, som omslutter hvert ord for individuell styling
**🎨 Oppsett og visning i UI:**
- **Lager** en array med `<span>`-elementer, pakker hvert ord inn for individuell styling
- **Slår sammen** span-elementene til en enkelt streng for effektiv DOM-oppdatering
- **Fremhever** det første ordet ved å legge til CSS-klassen `highlight`
- **Tømmer** eventuelle tidligere spillmeldinger for å gi en ren start
- **Fjerner** tidligere meldinger for å gi et rent utgangspunkt
**⌨️ Forberedelse av tekstfelt:**
- **Tømmer** eksisterende tekst i inndatafeltet
- **Setter fokus** på tekstfeltet slik at spillere kan begynne å skrive umiddelbart
- **Forbereder** inndataområdet for den nye spilløkten
**⌨️ Forberedelse av tekstboks:**
- **Tømmer** eventuelt eksisterende tekst i inputfeltet
- **Setter fokus** på tekstboksen slik at spillerne kan begynne å skrive med en gang
- **Gjør klar** inputområdet for den nye spilløkten
**⏱️ Initialisering av tidtaker:**
- **Fanger opp** det nåværende tidsstempelet ved hjelp av `new Date().getTime()`
- **Muliggjør** nøyaktig beregning av skrivehastighet og fullføringstid
- **Starter** ytelsessporing for spilløkten
**⏱️ Timer-innitialisering:**
- **Fanger** nåværende tidsstempel med `new Date().getTime()`
- **Muliggjør** nøyaktig beregning av skrivhastighet og fullføringstid
- **Starter** ytelsessporingen for spilløkten
### Legg til skrive-logikk
Her tar vi tak i hjertet av spillet vårt! Ikke bekymre deg hvis dette virker mye i starten - vi går gjennom hver del, og til slutt vil du se hvor logisk det hele er.
Her tar vi for oss kjernen i spillet vårt! Ikke bekymre deg hvis det virker mye i starten vi går gjennom hver del, og til slutt ser du hvor logisk alt er.
Det vi bygger her er ganske sofistikert: hver gang noen skriver en bokstav, vil koden vår sjekke hva de har skrevet, gi dem tilbakemelding og avgjøre hva som skal skje videre. Det ligner på hvordan tidlige tekstbehandlere som WordStar på 1970-tallet ga sanntidstilbakemelding til skrivere.
Det vi bygger her er ganske avansert: hver gang noen skriver en bokstav, vil koden sjekke hva de skrev, gi tilbakemelding, og avgjøre hva som skal skje videre. Det er likt hvordan tidlige tekstbehandlere som WordStar på 1970-tallet ga sanntidstilbakemelding til skrivere.
```javascript
// at the end of script.js
// på slutten av script.js
typedValueElement.addEventListener('input', () => {
// Get the current word
// Få det nåværende ordet
const currentWord = words[wordIndex];
// get the current value
// få den nåværende verdien
const typedValue = typedValueElement.value;
if (typedValue === currentWord && wordIndex === words.length - 1) {
// end of sentence
// Display success
// slutten av setningen
// Vis suksess
const elapsedTime = new Date().getTime() - startTime;
const message = `CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.`;
messageElement.innerText = message;
} else if (typedValue.endsWith(' ') && typedValue.trim() === currentWord) {
// end of word
// clear the typedValueElement for the new word
// slutten av ordet
// tøm typedValueElement for det nye ordet
typedValueElement.value = '';
// move to the next word
// gå til neste ord
wordIndex++;
// reset the class name for all elements in quote
// tilbakestill klassenavn for alle elementer i sitatet
for (const wordElement of quoteElement.childNodes) {
wordElement.className = '';
}
// highlight the new word
// marker det nye ordet
quoteElement.childNodes[wordIndex].className = 'highlight';
} else if (currentWord.startsWith(typedValue)) {
// currently correct
// highlight the next word
// per i dag korrekt
// marker neste ord
typedValueElement.className = '';
} else {
// error state
// feiltillatelse
typedValueElement.className = 'error';
}
});
```
**Forstå flyten i skrive-logikken:**
**Forståelse av skrive-logikkens flyt:**
Denne funksjonen bruker en trinnvis tilnærming, der den sjekker betingelser fra de mest spesifikke til de mest generelle. La oss bryte ned hvert scenario:
Denne funksjonen bruker en fossefallstilnærming, hvor den sjekker betingelsene fra mest spesifikke til mest generelle. La oss bryte ned hvert scenario:
```mermaid
flowchart TD
A[Player types character] --> B[Get current word and typed value]
B --> C{Quote complete?}
C -->|Yes| D[Show completion message with time]
C -->|No| E{Word complete with space?}
E -->|Yes| F[Clear input, move to next word, update highlight]
E -->|No| G{Typing correctly so far?}
G -->|Yes| H[Remove error styling]
G -->|No| I[Show error styling]
A[Spiller skriver tegn] --> B[Hent nåværende ord og skrevne verdi]
B --> C{Sitat ferdig?}
C -->|Ja| D[Vis fullføringsmelding med tid]
C -->|Nei| E{Ord fullført med mellomrom?}
E -->|Ja| F[Tøm inndata, gå til neste ord, oppdater utheving]
E -->|Nei| G{Skriver riktig så langt?}
G -->|Ja| H[Fjern feilstil]
G -->|Nei| I[Vis feilstil]
```
**🏁 Sitat fullført (Scenario 1):**
- **Sjekker** om skrevet verdi samsvarer med nåværende ord OG om vi er på det siste ordet
- **Beregner** forløpt tid ved å trekke starttid fra nåværende tid
**🏁 Sitat ferdig (Scenario 1):**
- **Sjekker** om skrevet verdi matcher det gjeldende ordet OG vi er på siste ord
- **Beregner** forløpt tid ved å trekke starttiden fra nåværende tid
- **Konverterer** millisekunder til sekunder ved å dele på 1 000
- **Viser** gratulasjonsmelding med fullføringstid
- **Viser** en gratulasjonsmelding med fullføringstid
**✅ Ord fullført (Scenario 2):**
- **Oppdager** at et ord er fullført når inndata slutter med et mellomrom
- **Validerer** at trimmet inndata samsvarer nøyaktig med det nåværende ordet
- **Tømmer** inndatafeltet for neste ord
**✅ Ord ferdig (Scenario 2):**
- **Oppdager** når ord er ferdig ved at input ender med et mellomrom
- **Validerer** at trimmet input matcher det gjeldende ordet nøyaktig
- **Tømmer** inputfeltet for neste ord
- **Går videre** til neste ord ved å øke `wordIndex`
- **Oppdaterer** visuell fremheving ved å fjerne alle klasser og fremheve det nye ordet
- **Oppdaterer** visuell fremheving ved å fjerne alle klasser og fremheve nytt ord
**📝 Skriving pågår (Scenario 3):**
- **Bekrefter** at det nåværende ordet starter med det som er skrevet så langt
- **Fjerner** eventuelle feilstiler for å vise at inndataene er korrekte
- **Tillater** fortsatt skriving uten avbrudd
- **Bekrefter** at gjeldende ord starter med det som er skrevet så langt
- **Fjerner** eventuell feil-styling for å vise at input er korrekt
- **Tillater** jevn skriving uten avbrudd
**❌ Feiltilstand (Scenario 4):**
- **Utløses** når skrevet tekst ikke samsvarer med begynnelsen av det forventede ordet
- **Legger til** en feil-CSS-klasse for å gi umiddelbar visuell tilbakemelding
- **Hjelper** spillere raskt med å identifisere og rette feil
**❌ Feilstatus (Scenario 4):**
- **Utløses** når skrevet tekst ikke matcher forventet ordstart
- **Legger til** CSS-klassen for feil for å gi umiddelbar visuell tilbakemelding
- **Hjelper** spillerne med å raskt identifisere og rette feil
## Test applikasjonen din
Se hva du har oppnådd! 🎉 Du har nettopp bygget et ekte, fungerende skrive-spill fra bunnen av ved hjelp av hendelsesdrevet programmering. Ta et øyeblikk til å sette pris på det - dette er ingen liten bragd!
Se hva du har fått til! 🎉 Du har nettopp laget et ekte, fungerende skrive-spill fra bunnen av med hendelsesstyrt programmering. Ta et øyeblikk for å sette pris på det dette er ikke småtteri!
Nå kommer testfasen! Vil det fungere som forventet? Har vi oversett noe? Her er tingen: hvis noe ikke fungerer perfekt med en gang, er det helt normalt. Selv erfarne utviklere finner feil i koden sin regelmessig. Det er en del av utviklingsprosessen!
Nå kommer testfasen! Vil det fungere som forventet? Har vi glemt noe? Saken er at hvis noe ikke virker helt perfekt med en gang, er det helt normalt. Selv erfarne utviklere finner feil i koden jevnlig. Det er bare en del av utviklingsprosessen!
Klikk på `start`, og begynn å skrive! Det skal se litt ut som animasjonen vi så tidligere.
Klikk på `start` og begynn å skrive! Det skal se litt ut som animasjonen vi så tidligere.
![Animasjon av spillet i aksjon](../../../../4-typing-game/images/demo.gif)
![Animasjon av spillet i arbeid](../../../../4-typing-game/images/demo.gif)
**Hva du bør teste i applikasjonen din:**
- **Bekrefter** at klikk på Start viser et tilfeldig sitat
- **Sikrer** at skriving fremhever det nåværende ordet riktig
- **Sjekker** at feilstil vises for feil skriving
- **Sikrer** at fullføring av ord flytter fremhevingen riktig
- **Tester** at fullføring av sitatet viser fullføringsmeldingen med tidtaking
**Vanlige feilsøkingstips:**
- **Sjekk** nettleserkonsollen (F12) for JavaScript-feil
- **Bekreft** at alle filnavn stemmer nøyaktig (skiller mellom store og små bokstaver)
- **Bekreft** at klikk på Start viser et tilfeldig sitat
- **Sjekk** at skriving fremhever gjeldende ord korrekt
- **Kontroller** at feil-styling dukker opp ved feil skriving
- **Sørg for** at fullførte ord flytter fremhevingen riktig
- **Test** at fullføring av sitatet viser fullføringsmeldingen med tid
**Vanlige feilsøkingsråd:**
- **Sjekk** nettleser-konsollen (F12) for JavaScript-feil
- **Bekreft** at alle filnavn stemmer helt (med store/små bokstaver)
- **Sørg for** at Live Server kjører og oppdaterer riktig
- **Test** forskjellige sitater for å bekrefte at den tilfeldige utvelgelsen fungerer
- **Test** ulike sitater for å kontrollere tilfeldig valg
---
@ -504,45 +503,103 @@ Klikk på `start`, og begynn å skrive! Det skal se litt ut som animasjonen vi s
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Utvid skrive-spillet ved å implementere et vanskelighetssystem som justerer spillet basert på spillerens prestasjoner. Denne utfordringen vil hjelpe deg med å øve på avansert hendelseshåndtering, dataanalyse og dynamiske UI-oppdateringer.
**Beskrivelse:** Utvid skrive-spillet ved å implementere et vanskelighetsnivå-system som justerer spillet basert på spillerens prestasjon. Denne utfordringen hjelper deg med avansert hendelseshåndtering, dataanalyse og dynamiske UI-oppdateringer.
**Oppgave:** Lag et vanskelighetssystem for skrive-spillet som:
**Oppgave:** Lag et system for vanskelighetsjustering i skrive-spillet som:
1. Sporer spillerens skrivehastighet (ord per minutt) og nøyaktighetsprosent
2. Justerer automatisk til tre vanskelighetsnivåer: Lett (enkle sitater), Middels (nåværende sitater), Vanskelig (komplekse sitater med tegnsetting)
3. Viser det nåværende vanskelighetsnivået og spillerstatistikk i brukergrensesnittet
4. Implementerer en streak-teller som øker vanskelighetsgraden etter 3 påfølgende gode prestasjoner
2. Justerer automatisk mellom tre vanskelighetsnivåer: Lett (enkle sitater), Medium (nåværende sitater), Vanskelig (komplekse sitater med tegnsetting)
3. Viser nåværende vanskelighetsnivå og spillerstatistikk i UI
4. Implementerer en strekkteller som øker vanskelighetsgraden etter 3 påfølgende gode prestasjoner
5. Legger til visuell tilbakemelding (farger, animasjoner) for å indikere vanskelighetsendringer
Legg til nødvendige HTML-elementer, CSS-stiler og JavaScript-funksjoner for å implementere denne funksjonen. Inkluder riktig feilhåndtering og sørg for at spillet forblir tilgjengelig med passende ARIA-etiketter.
Legg til nødvendige HTML-elementer, CSS-stiler og JavaScript-funksjoner for å implementere denne funksjonen. Inkluder god feilhåndtering og sørg for at spillet forblir tilgjengelig med passende ARIA-etiketter.
Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
Klar til å ta skrive-spillet ditt til neste nivå? Prøv å implementere disse avanserte funksjonene for å utdype forståelsen din av hendelseshåndtering og DOM-manipulasjon:
Klar til å ta skrive-spillet ditt til neste nivå? Prøv å implementere disse avanserte funksjonene for å fordype deg i hendelseshåndtering og DOM-manipulering:
**Legg til mer funksjonalitet:**
| Funksjon | Beskrivelse | Ferdigheter du vil øve på |
|----------|-------------|---------------------------|
| **Inndatakontroll** | Deaktiver `input` event listener ved fullføring, og aktiver den igjen når knappen klikkes | Hendelseshåndtering og tilstandskontroll |
| **UI-tilstandshåndtering** | Deaktiver tekstfeltet når spilleren fullfører sitatet | DOM-egenskapsmanipulasjon |
| **Modal dialog** | Vis en modal dialogboks med suksessmeldingen | Avanserte UI-mønstre og tilgjengelighet |
| **High Score System** | Lagre høyeste poengsum ved hjelp av `localStorage` | Nettleserens lagrings-API-er og datavedvarighet |
|---------|-------------|---------------------------|
| **Input-kontroll** | Deaktiver `input`-event listener ved fullføring, og aktiver på nytt når knappen klikkes | Hendelseshåndtering og tilstands-kontroll |
| **UI-tilstandsbehandling** | Deaktiver tekstboksen når spilleren fullfører sitatet | Manipulasjon av DOM-egenskaper |
| **Modaldialog** | Vis en modaldialogboks med suksessmelding | Avanserte UI-mønstre og tilgjengelighet |
| **High Score-system** | Lagre toppkarakterer ved bruk av `localStorage` | Nettleserlagring og datalagring |
**Tips til implementering:**
**Implementeringstips:**
- **Undersøk** `localStorage.setItem()` og `localStorage.getItem()` for vedvarende lagring
- **Øv** på å legge til og fjerne event listeners dynamisk
- **Utforsk** HTML-dialogelementer eller CSS-modal-mønstre
- **Tenk på** tilgjengelighet når du deaktiverer og aktiverer skjemakontroller
- **Utforsk** HTML dialog-elementer eller CSS modal-mønstre
- **Vurder** tilgjengelighet når du deaktiverer og aktiverer skjema-kontroller
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/22)
[Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/22)
---
## 🚀 Din skrive-spill-mester-tidslinje
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Test skrive-spillet med ulike sitater for å sikre at det fungerer smidig
- [ ] Eksperimenter med CSS-styling prøv å endre farge på fremheving og feil
- [ ] Åpne nettleserens DevTools (F12) og se på Konsollen mens du spiller
- [ ] Gi deg selv en utfordring ved å prøve å fullføre et sitat så raskt som mulig
### ⏰ **Hva du kan oppnå denne timen**
- [ ] Legg til flere sitater i arrayen (kanskje fra dine favorittbøker eller filmer)
- [ ] Implementer localStorage high score-systemet fra utfordringsdelen
- [ ] Lag en ord-per-minutt-kalkulator som vises etter hver runde
- [ ] Legg til lydeffekter for korrekt skriving, feil og fullføring
### 📅 **Din ukeslange reise**
- [ ] Lag en flerspiller-versjon der venner kan konkurrere side om side
- [ ] Lag ulike vanskelighetsnivåer med varierende sitatkompleksitet
- [ ] Legg til en fremdriftsindikator som viser hvor mye av sitatet som er ferdig
- [ ] Implementer brukerkontoer med personlig statistikksporing
- [ ] Design egendefinerte temaer og la brukere velge sin foretrukne stil
### 🗓️ **Din månedslange transformasjon**
- [ ] Lag et skrivekurs med leksjoner som progresivt lærer riktig fingerplassering
- [ ] Bygg analyseverktøy som viser hvilke bokstaver eller ord som gir flest feil
- [ ] Legg til støtte for forskjellige språk og tastaturoppsett
- [ ] Integrer med utdannings-APIer for å hente sitater fra litteraturdatabaser
- [ ] Publiser ditt forbedrede skrive-spill for andre å bruke og glede seg over
### 🎯 **Siste refleksjons-sjekk**
**Før du går videre, ta et øyeblikk og feir:**
- Hva var det mest tilfredsstillende øyeblikket under byggingen av dette spillet?
- Hvordan føler du deg om hendelsesstyrt programmering nå sammenlignet med da du startet?
- Hva er en funksjon du gleder deg til å legge til for å gjøre spillet unikt ditt?
- Hvordan kan du bruke hendelseshåndteringskonsepter i andre prosjekter?
```mermaid
journey
title Din Tillit til Hendelsesprogrammering Reise
section I dag
Forstå hendelser: 3: You
Bygge UI: 4: You
Skrive hendelseslyttere: 5: You
section Denne uken
Legge til funksjoner: 4: You
Feilsøke problemer: 5: You
Forbedre UX: 4: You
section Neste måned
Bygge komplekse apper: 5: You
Lære bort til andre: 5: You
Lage rammeverk: 5: You
```
> 🌟 **Husk**: Du har nettopp mestret et av kjerneprinsippene som driver alle interaktive nettsider og applikasjoner. Hendelsesstyrt programmering er det som får nettet til å føles levende og responsivt. Hver gang du ser en nedtrekksmeny, et skjema som validerer mens du skriver, eller et spill som reagerer på klikk, forstår du magien bak det. Du lærer ikke bare å kode du lærer å skape opplevelser som føles intuitive og engasjerende! 🎉
---
## Gjennomgang og selvstudium
## Review & Selvstudium
Les om [alle tilgjengelige hendelser](https://developer.mozilla.org/docs/Web/Events) for utviklere via nettleseren, og vurder scenariene der du vil bruke hver enkelt.
Les mer om [alle hendelser tilgjengelig](https://developer.mozilla.org/docs/Web/Events) for utviklere via nettleseren, og vurder i hvilke situasjoner du vil bruke hver av dem.
## Oppgave
@ -550,5 +607,7 @@ Les om [alle tilgjengelige hendelser](https://developer.mozilla.org/docs/Web/Eve
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi tilstreber nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på dets opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på originalspråket bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,15 +1,31 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "33a875c522f237a2026e4653240dfc07",
"translation_date": "2025-10-23T22:39:59+00:00",
"original_hash": "00aa85715e1efd4930c17a23e3012e69",
"translation_date": "2026-01-07T00:37:29+00:00",
"source_file": "5-browser-extension/1-about-browsers/README.md",
"language_code": "no"
}
-->
# Nettleserutvidelsesprosjekt Del 1: Alt om nettlesere
# Nettleserutvidelsesprosjekt Del 1: Alt om Nettlesere
![Sketchnote av nettleser](../../../../translated_images/browser.60317c9be8b7f84adce43e30bff8d47a1ae15793beab762317b2bc6b74337c1a.no.jpg)
```mermaid
journey
title Din Nettleserutvidelsesutviklingsreise
section Grunnlag
Forstå nettlesere: 3: Student
Lær utvidelsestyper: 4: Student
Sett opp utvikling: 4: Student
section Utvikling
Bygg grensesnitt: 4: Student
Legg til funksjonalitet: 5: Student
Håndter data: 5: Student
section Integrasjon
Test i nettleser: 5: Student
Feilsøk problemer: 4: Student
Poler opplevelsen: 5: Student
```
![Browser sketchnote](../../../../translated_images/browser.60317c9be8b7f84a.no.jpg)
> Sketchnote av [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
## Quiz før forelesning
@ -18,160 +34,246 @@ CO_OP_TRANSLATOR_METADATA:
### Introduksjon
Nettleserutvidelser er små applikasjoner som forbedrer din opplevelse av å surfe på nettet. Akkurat som Tim Berners-Lees opprinnelige visjon om et interaktivt nett, utvider utvidelser nettleserens funksjonalitet utover enkel dokumentvisning. Fra passordhåndteringsverktøy som holder kontoene dine sikre til fargevelgere som hjelper designere med å finne perfekte nyanser, løser utvidelser daglige utfordringer ved nettlesing.
Nettleserutvidelser er mini-applikasjoner som forbedrer din nettleseropplevelse. Som Tim Berners-Lees opprinnelige visjon om et interaktivt nett, utvider utvidelser nettleserens evner utover enkel dokumentvisning. Fra passordbehandlere som sikrer kontoene dine, til fargeplukkere som hjelper designere å få perfekte nyanser, løser utvidelser hverdagslige nettleserutfordringer.
Før vi bygger din første utvidelse, la oss forstå hvordan nettlesere fungerer. Akkurat som Alexander Graham Bell måtte forstå lydoverføring før han oppfant telefonen, vil kunnskap om nettleserens grunnleggende funksjoner hjelpe deg med å lage utvidelser som integreres sømløst med eksisterende nettlesersystemer.
Før vi bygger din første utvidelse, la oss forstå hvordan nettlesere fungerer. På samme måte som Alexander Graham Bell måtte forstå lydoverføring før han oppfant telefonen, vil kunnskap om nettleserens grunnprinsipper hjelpe deg å lage utvidelser som integreres sømløst med eksisterende nettlesersystemer.
Ved slutten av denne leksjonen vil du forstå nettleserarkitektur og ha startet byggingen av din første utvidelse.
## Forstå nettlesere
```mermaid
mindmap
root((Nettleserarkitektur))
Core Components
Rendering Engine
JavaScript Engine
Network Stack
Storage APIs
User Interface
Adressefelt
Fanehåndtering
Bokmerker
Utvidelsesikoner
Extension System
Manifestfiler
Innholdsskript
Bakgrunnssider
Popup-vinduer
Security Model
Samme-opprinnelses-policy
Tillatelses-API
Innholdssikkerhet
Isolerte verdener
Development Tools
DevTools-integrasjon
Feilsøkingskonsoll
Ytelsesmonitor
Utvidelsesinspektør
```
## Forstå Nettlesere
En nettleser er i hovedsak en sofistikert dokumenttolker. Når du skriver "google.com" inn i adressefeltet, utfører nettleseren en kompleks serie operasjoner - den ber om innhold fra servere over hele verden, og deretter tolker og gjengir den koden til de interaktive nettsidene du ser.
En nettleser er i hovedsak en sofistikert dokumenttolker. Når du skriver "google.com" i adressefeltet, utfører nettleseren en kompleks serie operasjoner - den forespør innhold fra servere verden over, deretter analyserer og viser den koden som interaktive nettsider du ser.
Denne prosessen speiler hvordan den første nettleseren, WorldWideWeb, ble designet av Tim Berners-Lee i 1990 for å gjøre hyperlenkede dokumenter tilgjengelige for alle.
**Litt historie**: Den første nettleseren het 'WorldWideWeb' og ble laget av Sir Timothy Berners-Lee i 1990.
![tidlige nettlesere](../../../../translated_images/earlybrowsers.d984b711cdf3a42ddac919d46c4b5ca7232f68ccfbd81395e04e5a64c0015277.no.jpg)
![early browsers](../../../../translated_images/earlybrowsers.d984b711cdf3a42d.no.jpg)
> Noen tidlige nettlesere, via [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
### Hvordan nettlesere behandler nettinnhold
### Hvordan Nettlesere Behandler Nettinnhold
Prosessen mellom å skrive inn en URL og se en nettside involverer flere koordinerte trinn som skjer i løpet av sekunder:
Prosessen mellom å skrive inn en URL og å se en nettside inneholder flere koordinerte trinn som skjer i løpet av sekunder:
```mermaid
sequenceDiagram
participant User
participant Browser
participant Extension
participant DNS
participant Server
User->>Browser: Types URL and presses Enter
Browser->>DNS: Looks up server IP address
DNS->>Browser: Returns IP address
Browser->>Server: Requests web page content
Server->>Browser: Sends HTML, CSS, and JavaScript
Browser->>User: Renders complete web page
User->>Browser: Skriver inn URL og trykker Enter
Browser->>Extension: Utløser førForespørsel-hendelse
Extension->>Extension: Sjekk om URL må endres
Browser->>DNS: Ser opp serverens IP-adresse
DNS->>Browser: Returnerer IP-adresse
Browser->>Server: Forespør websideinnhold
Server->>Browser: Sender HTML, CSS og JavaScript
Browser->>Extension: Utløser førRespons-hendelse
Extension->>Extension: Endre innhold hvis nødvendig
Browser->>User: Gjengir fullstendig webside
Extension->>User: Viser utvidelses-UI oppdateringer
```
**Dette er hva prosessen oppnår:**
- **Oversetter** den menneskelesbare URL-en til en server-IP-adresse gjennom DNS-oppslag
- **Etablerer** en sikker tilkobling til webserveren ved bruk av HTTP eller HTTPS protokoller
- **Forespør** det spesifikke websideinnholdet fra serveren
- **Mottar** HTML-markup, CSS-stil og JavaScript-kode fra serveren
- **Renderer** alt innhold til den interaktive nettsiden du ser
**Dette oppnår prosessen:**
- **Oversetter** den menneskeleselige URL-en til en server-IP-adresse gjennom DNS-oppslag
- **Etablerer** en sikker forbindelse med webserveren ved hjelp av HTTP- eller HTTPS-protokoller
- **Ber om** spesifikt nettinnhold fra serveren
- **Mottar** HTML-markup, CSS-styling og JavaScript-kode fra serveren
- **Gjengir** alt innhold til den interaktive nettsiden du ser
### Nettleserens kjernefunksjoner
### Nettleserens Kjernefunksjoner
Moderne nettlesere tilbyr en rekke funksjoner som utviklere av utvidelser kan dra nytte av:
Moderne nettlesere tilbyr mange funksjoner som utviklere av utvidelser kan bruke:
| Funksjon | Formål | Muligheter for utvidelser |
|----------|--------|---------------------------|
| **Gjengivelsesmotor** | Viser HTML, CSS og JavaScript | Innholdsmodifikasjon, stylinginjeksjon |
| **JavaScript-motor** | Utfører JavaScript-kode | Egendefinerte skript, API-interaksjoner |
| **Lokal lagring** | Lagrer data lokalt | Brukerpreferanser, hurtiglagret data |
| **Nettverksstabel** | Håndterer webforespørsler | Forespørselsmonitorering, dataanalyse |
|---------|---------|------------------------|
| **Rendering Engine** | Viser HTML, CSS og JavaScript | Innholdsmodifisering, stiltilsetting |
| **JavaScript Engine** | Utfører JavaScript-kode | Egne skript, API-interaksjoner |
| **Lokal lagring** | Lagrer data lokalt | Brukerinnstillinger, bufret data |
| **Nettverksstakk** | Håndterer nettverksforespørsler | Overvåkning av forespørsler, dataanalyse |
| **Sikkerhetsmodell** | Beskytter brukere mot skadelig innhold | Innholdsfiltrering, sikkerhetsforbedringer |
**Å forstå disse funksjonene hjelper deg med:**
- **Identifisere** hvor din utvidelse kan tilføre mest verdi
- **Velge** de riktige nettleser-API-ene for utvidelsens funksjonalitet
**Å forstå disse funksjonene hjelper deg med å:**
- **Identifisere** hvor utvidelsen din kan tilføre mest verdi
- **Velge** riktige nettleser-API-er for utvidelsens funksjonalitet
- **Designe** utvidelser som fungerer effektivt med nettlesersystemer
- **Sikre** at utvidelsen din følger beste praksis for nettlesersikkerhet
- **Sikre** at utvidelsen følger nettleserens sikkerhetspraksis
### Tverrnettleserutvikling
### Vurderinger for Utvikling på Tvers av Nettlesere
Ulike nettlesere implementerer standarder med små variasjoner, på samme måte som ulike programmeringsspråk kan håndtere den samme algoritmen forskjellig. Chrome, Firefox og Safari har hver sine unike egenskaper som utviklere må ta hensyn til under utvikling av utvidelser.
Forskjellige nettlesere implementerer standarder med små variasjoner, på samme måte som forskjellige programmeringsspråk kan håndtere samme algoritme ulikt. Chrome, Firefox og Safari har alle unike egenskaper som utviklere må ta hensyn til under utvidelsesutvikling.
> 💡 **Tips**: Bruk [caniuse.com](https://www.caniuse.com) for å sjekke hvilke webteknologier som støttes på tvers av ulike nettlesere. Dette er uvurderlig når du planlegger funksjonene til utvidelsen din!
> 💡 **Proff tips**: Bruk [caniuse.com](https://www.caniuse.com) for å sjekke hvilke webteknologier som støttes i ulike nettlesere. Dette er uvurderlig når du planlegger funksjonene til utvidelsen din!
**Viktige hensyn for utvikling av utvidelser:**
- **Test** utvidelsen din på tvers av Chrome, Firefox og Edge-nettlesere
**Viktige hensyn ved utvidelsesutvikling:**
- **Test** utvidelsen din i Chrome, Firefox og Edge
- **Tilpass** deg ulike nettleserutvidelses-API-er og manifestformater
- **Håndter** varierende ytelsesegenskaper og begrensninger
- **Tilby** alternativer for nettleserspesifikke funksjoner som kanskje ikke er tilgjengelige
- **Håndter** ulike ytelseselementer og begrensninger
- **Gi** alternative løsninger for nettleserspesifikke funksjoner som kanskje ikke er tilgjengelige
**Innsikt fra analyse**: Du kan finne ut hvilke nettlesere brukerne dine foretrekker ved å installere analysepakker i dine webutviklingsprosjekter. Disse dataene hjelper deg med å prioritere hvilke nettlesere du skal støtte først.
**Analyseinnsikt**: Du kan finne ut hvilke nettlesere brukerne dine foretrekker ved å installere analysepakker i webutviklingsprosjektene dine. Denne informasjonen hjelper deg å prioritere hvilke nettlesere du bør støtte først.
## Forstå nettleserutvidelser
## Forstå Nettleserutvidelser
Nettleserutvidelser løser vanlige utfordringer ved nettlesing ved å legge til funksjonalitet direkte i nettleserens grensesnitt. I stedet for å kreve separate applikasjoner eller komplekse arbeidsflyter, gir utvidelser umiddelbar tilgang til verktøy og funksjoner.
Nettleserutvidelser løser vanlige utfordringer ved nettlesing ved å legge til funksjonalitet direkte i nettlesergrensesnittet. I stedet for å kreve separate applikasjoner eller komplekse arbeidsflyter, gir utvidelser umiddelbar tilgang til verktøy og funksjoner.
Dette konseptet speiler hvordan tidlige datapionerer som Douglas Engelbart forestilte seg å utvide menneskelige evner med teknologi - utvidelser utvider nettleserens grunnleggende funksjonalitet.
Dette konseptet speiler hvordan pionerer som Douglas Engelbart så for seg å forsterke menneskelige evner med teknologi - utvidelser forsterker nettleserens grunnleggende funksjonalitet.
```mermaid
quadrantChart
title Nettleserutvidelseskategorier
x-axis Enkel --> Kompleks
y-axis Personlig bruk --> Profesjonelle verktøy
quadrant-1 Utviklerverktøy
quadrant-2 Bedriftløsninger
quadrant-3 Personlige verktøy
quadrant-4 Produktivitetsapper
Ad Blockers: [0.3, 0.2]
Password Managers: [0.7, 0.3]
Color Pickers: [0.4, 0.8]
Code Formatters: [0.8, 0.9]
Note Taking: [0.6, 0.5]
Video Downloaders: [0.5, 0.2]
Time Trackers: [0.7, 0.6]
Screenshot Tools: [0.4, 0.4]
```
**Populære utvidelseskategorier og deres fordeler:**
- **Produktivitetsverktøy**: Oppgavehåndteringsverktøy, notatapper og tidssporere som hjelper deg med å holde deg organisert
- **Sikkerhetsforbedringer**: Passordhåndteringsverktøy, annonseblokkerere og personvernsverktøy som beskytter dataene dine
- **Utviklerverktøy**: Kodeformaterere, fargevelgere og feilsøkingsverktøy som effektiviserer utviklingen
- **Innholdsforbedring**: Lesemodus, videonedlastere og skjermbildeverktøy som forbedrer din nettopplevelse
- **Produktivitetsverktøy**: Oppgavebehandlere, notat-apper og tidsregistreringsverktøy som hjelper deg å holde orden
- **Sikkerhetsforbedringer**: Passordbehandlere, annonseblokkere og personvernverktøy som beskytter dine data
- **Utviklerverktøy**: Kodeformaterere, fargeplukkere og feilsøkingsverktøy som effektiviserer utviklingen
- **Innholdsforbedring**: Lesemodi, videonedlastere og skjermbildeverktøy som forbedrer nettleseropplevelsen
**Refleksjonsspørsmål**: Hva er dine favorittutvidelser? Hvilke spesifikke oppgaver utfører de, og hvordan forbedrer de nettleseropplevelsen din?
**Refleksjonsspørsmål**: Hva er dine favorittnettleserutvidelser? Hvilke spesifikke oppgaver utfører de, og hvordan forbedrer de din opplevelse av å surfe på nettet?
### 🔄 **Pedagogisk sjekk**
**Forståelse av nettleserarkitektur**: Før du går videre til utvidelsesutvikling, sørg for at du kan:
- ✅ Forklare hvordan nettlesere behandler nettforespørsler og viser innhold
- ✅ Identifisere hovedkomponentene i nettleserarkitekturen
- ✅ Forstå hvordan utvidelser integreres med nettleserfunksjonalitet
- ✅ Gjenkjenne sikkerhetsmodellen som beskytter brukere
## Installere og administrere utvidelser
**Rask selvtest**: Kan du følge veien fra å skrive inn en URL til å se en nettside?
1. **DNS-oppslag** konverterer URL til IP-adresse
2. **HTTP-forespørsel** henter innhold fra serveren
3. **Parsing** bearbeider HTML, CSS og JavaScript
4. **Rendering** viser den endelige nettsiden
5. **Utvidelser** kan modifisere innhold på flere trinn
Å forstå prosessen med å installere utvidelser hjelper deg med å forutse brukeropplevelsen når folk installerer din utvidelse. Installasjonsprosessen er standardisert på tvers av moderne nettlesere, med små variasjoner i grensesnittdesign.
## Installere og Administrere Utvidelser
![skjermbilde av Edge-nettleseren som viser den åpne edge://extensions-siden og åpne innstillingsmenyen](../../../../translated_images/install-on-edge.d68781acaf0b3d3dada8b7507cde7a64bf74b7040d9818baaa9070668e819f90.no.png)
Å forstå installasjonsprosessen for utvidelser hjelper deg å forutse brukeropplevelsen når folk installerer din utvidelse. Installasjonsprosessen er standardisert på tvers av moderne nettlesere, med små variasjoner i brukergrensesnitt.
> **Viktig**: Sørg for å slå på utviklermodus og tillate utvidelser fra andre butikker når du tester dine egne utvidelser.
![screenshot of the Edge browser showing the open edge://extensions page and open settings menu](../../../../translated_images/install-on-edge.d68781acaf0b3d3d.no.png)
### Utviklingsutvidelsesinstallasjon
> **Viktig**: Husk å skru på utviklermodus og tillate utvidelser fra andre butikker når du tester dine egne utvidelser.
Når du utvikler og tester dine egne utvidelser, følg denne arbeidsflyten:
### Utviklingsinstallasjon av Utvidelser
Når du utvikler og tester egne utvidelser, følg denne arbeidsflyten:
```mermaid
flowchart TD
A[Skriv kode] --> B[Bygg utvidelse]
B --> C{Første installasjon?}
C -->|Ja| D[Last inn upakket]
C -->|Nei| E[Last inn utvidelse på nytt]
D --> F[Test funksjonalitet]
E --> F
F --> G[Fungerer korrekt?]
G -->|Nei| H[Feilsøk problemer]
G -->|Ja| I[Klar for brukere]
H --> A
I --> J[Publiser i butikk]
style A fill:#e1f5fe
style F fill:#e8f5e8
style I fill:#f3e5f5
style J fill:#fff3e0
```
```bash
# Step 1: Build your extension
# Trinn 1: Bygg utvidelsen din
npm run build
```
**Hva denne kommandoen oppnår:**
- **Kompilerer** kildekoden din til filer som er klare for nettleseren
- **Pakker** JavaScript-moduler i optimaliserte pakker
**Dette kommandoen gjør:**
- **Kompilerer** koden din til nettleserklare filer
- **Pakker** JavaScript-moduler til optimaliserte pakker
- **Genererer** de endelige utvidelsesfilene i `/dist`-mappen
- **Forbereder** utvidelsen din for installasjon og testing
- **Forbereder** utvidelsen for installasjon og testing
**Steg 2: Naviger til nettleserutvidelser**
**Steg 2: Naviger til Nettleserutvidelser**
1. **Åpne** nettleserens administrasjonsside for utvidelser
2. **Klikk** på "Innstillinger og mer"-knappen (ikonet `...`) øverst til høyre
2. **Klikk** på "Innstillinger og mer"-knappen (`...`) øverst til høyre
3. **Velg** "Utvidelser" fra rullegardinmenyen
**Steg 3: Last inn din utvidelse**
- **For nye installasjoner**: Velg `load unpacked` og velg din `/dist`-mappe
- **For oppdateringer**: Klikk `reload` ved siden av din allerede installerte utvidelse
- **For testing**: Aktiver "Utviklermodus" for å få tilgang til flere feilsøkingsfunksjoner
**Steg 3: Last inn Utvidelsen din**
- **For nye installasjoner**: Velg `load unpacked` og pek på `/dist`-mappen din
- **For oppdateringer**: Klikk `reload` ved siden av allerede installert utvidelse
- **For testing**: Aktiver "Utviklermodus" for tilgang til flere feilsøkingsfunksjoner
### Produksjonsutvidelsesinstallasjon
### Produksjonsinstallasjon av Utvidelser
> ✅ **Merk**: Disse utviklingsinstruksjonene er spesifikt for utvidelser du bygger selv. For å installere publiserte utvidelser, besøk de offisielle nettleserutvidelsesbutikkene som [Microsoft Edge Add-ons store](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home).
> ✅ **Merk**: Disse utviklingsinstruksjonene gjelder spesielt for utvidelser du bygger selv. For å installere publiserte utvidelser, gå til de offisielle nettleserutvidelsesbutikkene som [Microsoft Edge Add-ons store](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home).
**Forstå forskjellen:**
- **Utviklingsinstallasjoner** lar deg teste upubliserte utvidelser under utvikling
- **Butikkinstallasjoner** gir verifiserte, publiserte utvidelser med automatiske oppdateringer
- **Sideloading** tillater installasjon av utvidelser fra utenfor offisielle butikker (krever utviklermodus)
**Forskjellen forklart:**
- **Utviklingsinstallasjon** lar deg teste upubliserte utvidelser under utvikling
- **Butikkinstallasjoner** gir godkjente, publiserte utvidelser med automatiske oppdateringer
- **Sideloading** tillater installasjon av utvidelser utenfor offisielle butikker (krever utviklermodus)
## Bygge din karbonfotavtrykk-utvidelse
## Bygge Din Karbonavtrykk-utvidelse
Vi skal lage en nettleserutvidelse som viser karbonfotavtrykket til energiforbruket i din region. Dette prosjektet demonstrerer essensielle konsepter for utvikling av utvidelser samtidig som det skaper et praktisk verktøy for miljøbevissthet.
Vi skal lage en nettleserutvidelse som viser karbonavtrykket til energibruken i ditt område. Dette prosjektet demonstrerer grunnleggende konsepter i utvidelsesutvikling samtidig som det lager et praktisk verktøy for miljøbevissthet.
Denne tilnærmingen følger prinsippet om "learning by doing" som har vist seg effektivt siden John Deweys pedagogiske teorier - en kombinasjon av tekniske ferdigheter med meningsfulle virkelige applikasjoner.
Denne tilnærmingen følger prinsippet om "læring ved å gjøre" som har vist seg effektivt siden John Deweys pedagogiske teorier - å kombinere tekniske ferdigheter med meningsfulle virkelige anvendelser.
### Prosjektkrav
Før du begynner utviklingen, la oss samle de nødvendige ressursene og avhengighetene:
Før vi begynner utviklingen, la oss samle nødvendige ressurser og avhengigheter:
**Nødvendig API-tilgang:**
- **[CO2 Signal API-nøkkel](https://www.co2signal.com/)**: Skriv inn e-postadressen din for å motta din gratis API-nøkkel
- **[Regionkode](http://api.electricitymap.org/v3/zones)**: Finn din regionkode ved hjelp av [Electricity Map](https://www.electricitymap.org/map) (for eksempel bruker Boston 'US-NEISO')
**Påkrevd API-tilgang:**
- **[CO2 Signal API-nøkkel](https://www.co2signal.com/)**: Skriv inn e-postadressen din for å få en gratis API-nøkkel
- **[Regionkode](http://api.electricitymap.org/v3/zones)**: Finn regionkoden din med [Electricity Map](https://www.electricitymap.org/map) (for eksempel bruker Boston 'US-NEISO')
**Utviklingsverktøy:**
- **[Node.js og NPM](https://www.npmjs.com)**: Pakkehåndteringsverktøy for å installere prosjektavhengigheter
- **[Node.js og NPM](https://www.npmjs.com)**: Pakkehåndteringsverktøy for installasjon av prosjektavhengigheter
- **[Startkode](../../../../5-browser-extension/start)**: Last ned `start`-mappen for å begynne utviklingen
**Lær mer**: Forbedre dine ferdigheter innen pakkehåndtering med dette [omfattende Learn-modulet](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
**Lær mer**: Forbedre dine ferdigheter i pakkehåndtering med dette [omfattende Learn-modulet](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
### Forstå prosjektstrukturen
### Forstå Prosjektstrukturen
Å forstå prosjektstrukturen hjelper deg med å organisere utviklingsarbeidet effektivt. Akkurat som Biblioteket i Alexandria ble organisert for enkel kunnskapshenting, gjør en godt strukturert kodebase utviklingen mer effektiv:
Å forstå prosjektstrukturen hjelper deg å organisere utviklingsarbeidet effektivt. På samme måte som biblioteket i Alexandria var organisert for lett kunnskapsinnhenting, gjør en godt strukturert kodebase utviklingen smidigere:
```
project-root/
@ -180,40 +282,42 @@ project-root/
│ ├── index.html # User interface markup
│ ├── background.js # Background script functionality
│ └── main.js # Compiled JavaScript bundle
└── src/ # Source development files
└── index.js # Your main JavaScript code
├── src/ # Source development files
│ └── index.js # Your main JavaScript code
├── package.json # Project dependencies and scripts
└── webpack.config.js # Build configuration
```
**Hva hver fil gjør:**
- **`manifest.json`**: **Definerer** metadata, tillatelser og inngangspunkter for utvidelsen
- **`index.html`**: **Oppretter** brukergrensesnittet som vises når brukere klikker på utvidelsen
- **`background.js`**: **Håndterer** bakgrunnsoppgaver og nettleserhendelser
- **`main.js`**: **Inneholder** den endelige bundlingen av JavaScript etter byggeprosessen
- **`src/index.js`**: **Huser** din hovedutviklingskode som blir kompilert til `main.js`
- **`manifest.json`**: **Definerer** utvidelsesmetadata, tillatelser og inngangspunkter
- **`index.html`**: **Lager** brukergrensesnittet som vises når brukere klikker på utvidelsen din
- **`background.js`**: **Håndterer** bakgrunnsoppgaver og nettleserhendelseslyttere
- **`main.js`**: **Inneholder** den endelige pakkede JavaScript-koden etter byggeprosessen
- **`src/index.js`**: **Huser** hovedutviklingskoden som kompileres til `main.js`
> 💡 **Organiseringstips**: Lagre API-nøkkelen og regionkoden din i et sikkert notat for enkel referanse under utviklingen. Du trenger disse verdiene for å teste utvidelsens funksjonalitet.
> 💡 **Organiseringstips**: Lagre API-nøkkelen og regionkoden i en sikker notat for enkel referanse under utviklingen. Du vil trenge disse verdiene for å teste utvidelsens funksjonalitet.
**Sikkerhetsmerknad**: Aldri legg inn API-nøkler eller sensitive opplysninger i kodebasen din. Vi viser deg hvordan du håndterer dette sikkert i de neste stegene.
**Sikkerhetsmerknad**: Aldri legg inn API-nøkler eller sensitive legitimasjoner i kodearkivet ditt. Vi viser deg hvordan du håndterer dette sikkert i neste steg.
## Lage utvidelsens grensesnitt
## Lage Utvidelsens Grensesnitt
Nå skal vi bygge brukergrensesnittkomponentene. Utvidelsen bruker en to-skjerms tilnærming: en konfigurasjonsskjerm for første oppsett og en resultatskjerm for datavisning.
Nå skal vi bygge brukergrensesnittkomponentene. Utvidelsen bruker en to-skjerms tilnærming: en konfigurasjonsskjerm for oppsett og en resultatskjerm for datavisning.
Dette følger prinsippet om progressiv avsløring som brukes i grensesnittdesign siden datamaskinens tidlige dager - å avsløre informasjon og alternativer i en logisk rekkefølge for å unngå å overvelde brukere.
Dette følger prinsippet om gradvis avsløring som har vært brukt i grensesnittdesign siden tidlige datadager - å vise informasjon og valgmuligheter i en logisk rekkefølge for å unngå å overvelde brukere.
### Oversikt over utvidelsesvisninger
### Oversikt over Utvidelsens Visninger
**Oppsettsvisning** - Førstegangsbruker konfigurasjon:
![skjermbilde av den ferdige utvidelsen åpnet i en nettleser, som viser et skjema med felt for regionnavn og API-nøkkel.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.no.png)
**Oppsettvisning** - Konfigurering for første gangs bruk:
![screenshot of the completed extension open in a browser, displaying a form with inputs for region name and API key.](../../../../translated_images/1.b6da8c1394b07491.no.png)
**Resultatvisning** - Visning av karbonfotavtrykkdata:
![skjermbilde av den ferdige utvidelsen som viser verdier for karbonforbruk og fossilt brenselprosent for regionen US-NEISO.](../../../../translated_images/2.1dae52ff0804224692cd648afbf2342955d7afe3b0101b617268130dfb427f55.no.png)
**Resultatvisning** - Visning av karbonavtrykkdata:
![screenshot of the completed extension displaying values for carbon usage and fossil fuel percentage for the US-NEISO region.](../../../../translated_images/2.1dae52ff08042246.no.png)
### Lage konfigurasjonsskjemaet
### Lage Konfigurasjonsskjemaet
Oppsettskjemaet samler inn brukerens konfigurasjonsdata ved første bruk. Når det er konfigurert, lagres denne informasjonen i nettleserens lagring for fremtidige økter.
Oppsettskjemaet samler konfigurasjonsdata fra brukeren ved første gangs bruk. Når det er satt opp, lagres denne informasjonen i nettleserlagring for fremtidige økter.
I `/dist/index.html`-filen, legg til denne skjema-strukturen:
I filen `/dist/index.html`, legg til denne skjema-strukturen:
```html
<form class="form-data" autocomplete="on">
@ -232,16 +336,16 @@ I `/dist/index.html`-filen, legg til denne skjema-strukturen:
</form>
```
**Hva dette skjemaet gjør:**
- **Oppretter** en semantisk skjema-struktur med riktige etiketter og input-assosiasjoner
- **Aktiverer** nettleserens autofullføringsfunksjonalitet for forbedret brukeropplevelse
- **Krever** at begge feltene fylles ut før innsending ved hjelp av attributtet `required`
- **Organiserer** input med beskrivende klassenavn for enkel styling og JavaScript-målretting
**Dette skjemaet gjør:**
- **Oppretter** en semantisk skjemastruktur med korrekte etiketter og inputassosiasjoner
- **Aktiverer** autofullføringsfunksjonalitet for bedre brukeropplevelse
- **Krever** at begge feltene fylles ut før innsendelse ved bruk av `required`-attributtet
- **Organiserer** inputfeltene med beskrivende klassenavn for enkel styling og JavaScript-målretting
- **Gir** klare instruksjoner til brukere som setter opp utvidelsen for første gang
### Lage resultatvisningen
### Lage Resultatvisningen
Deretter lager vi resultatområdet som skal vise karbonfotavtrykkdata. Legg til denne HTML-en under skjemaet:
Deretter lager du resultatområdet som skal vise karbonavtrykkdata. Legg til denne HTML-en under skjemaet:
```html
<div class="result">
@ -257,78 +361,195 @@ Deretter lager vi resultatområdet som skal vise karbonfotavtrykkdata. Legg til
</div>
```
**Hva denne strukturen gir:**
**Hva denne strukturen tilbyr:**
- **`loading`**: **Viser** en lastemelding mens API-data hentes
- **`errors`**: **Viser** feilmeldinger hvis API-kall mislykkes eller data er ugyldige
- **`errors`**: **Viser** feilmeldinger om API-kall feiler eller data er ugyldige
- **`data`**: **Holder** rådata for feilsøking under utvikling
- **`result-container`**: **Presenterer** formatert karbonfotavtrykkinformasjon til brukere
- **`clear-btn`**: **Lar** brukere endre sin region og rekonfigurere utvidelsen
- **`result-container`**: **Presenterer** formatert informasjon om karbonavtrykk til brukere
- **`clear-btn`**: **Lar** brukere endre region og konfigurere utvidelsen på nytt
### Sette opp byggeprosessen
### Sette opp Byggeprosessen
La oss nå installere prosjektavhengighetene og teste byggeprosessen:
Nå skal vi installere prosjektavhengigheter og teste byggeprosessen:
```bash
npm install
```
**Hva denne installasjonsprosessen oppnår:**
**Dette installasjonssteget gjør:**
- **Laster ned** Webpack og andre utviklingsavhengigheter spesifisert i `package.json`
- **Konfigurerer** byggeverktøyet for å kompilere moderne JavaScript
- **Forbereder** utviklingsmiljøet for bygging og testing av utvidelsen
- **Aktiverer** kodebundling, optimalisering og tverrnettleserkompatibilitetsfunksjoner
- **Forbereder** utviklingsmiljø for bygging og testing av utvidelsen
- **Muliggjør** kodepakking, optimalisering og tverr-nettleserkompatibilitet
> 💡 **Innblikk i byggeprosessen**: Webpack pakker koden din fra `/src/index.js` til `/dist/main.js`. Denne prosessen optimaliserer koden for produksjon og sikrer nettleserkompatibilitet.
### Test din framgang
På dette punktet kan du teste utvidelsen din:
1. **Kjør** byggekommandoen for å kompilere koden din
2. **Last** utvidelsen inn i nettleseren din ved å bruke utviklermodus
3. **Bekreft** at skjemaet vises korrekt og ser profesjonelt ut
4. **Sjekk** at alle skjemaelementene er riktig justert og fungerer
> 💡 **Innsikt om byggeprosessen**: Webpack samler kildekoden din fra `/src/index.js` til `/dist/main.js`. Denne prosessen optimaliserer koden din for produksjon og sikrer nettleserkompatibilitet.
**Hva du har oppnådd:**
- **Bygget** grunnleggende HTML-struktur for utvidelsen din
- **Opprettet** både konfigurasjons- og resultatgrensesnitt med riktig semantisk oppmerking
- **Satt opp** en moderne utviklingsflyt med industristandard verktøy
- **Forberedt** grunnlaget for å legge til interaktiv JavaScript-funksjonalitet
### Teste fremgangen din
### 🔄 **Pedagogisk Sjekk-inn**
**Fremdrift i Utvidelsesutvikling**: Bekreft din forståelse før du fortsetter:
- ✅ Kan du forklare formålet med hver fil i prosjektstrukturen?
- ✅ Forstår du hvordan byggeprosessen transformerer kildekoden din?
- ✅ Hvorfor skiller vi konfigurasjon og resultater i ulike UI-seksjoner?
- ✅ Hvordan støtter skjemaets struktur både brukervennlighet og tilgjengelighet?
På dette tidspunktet kan du teste utvidelsen din:
**Forståelse av Utviklingsflyt**: Du bør nå kunne:
1. **Modifisere** HTML og CSS for utvidelsens grensesnitt
2. **Kjøre** byggekommandoen for å kompilere endringene dine
3. **Laste inn** utvidelsen på nytt i nettleseren for å teste oppdateringer
4. **Feilsøke** problemer ved hjelp av nettleserens utviklerverktøy
1. **Kjør** byggekommandoen for å kompilere koden din
2. **Last** utvidelsen inn i nettleseren din ved hjelp av utviklermodus
3. **Bekreft** at skjemaet vises korrekt og ser profesjonelt ut
4. **Sjekk** at alle skjemaelementer er riktig justert og funksjonelle
Du har fullført den første fasen av utvikling av nettleserutvidelser. Akkurat som Wright-brødrene først måtte forstå aerodynamikk før de kunne fly, forbereder forståelsen av disse grunnleggende konseptene deg på å bygge mer komplekse interaktive funksjoner i neste leksjon.
**Hva du har oppnådd:**
- **Bygget** den grunnleggende HTML-strukturen for utvidelsen din
- **Opprettet** både konfigurasjons- og resultatgrensesnitt med riktig semantisk markup
- **Satt opp** en moderne utviklingsarbeidsflyt med bransjestandardverktøy
- **Forberedt** grunnlaget for å legge til interaktiv JavaScript-funksjonalitet
## GitHub Copilot Agent Challenge 🚀
Du har fullført den første fasen av utviklingen av nettleserutvidelsen. Akkurat som brødrene Wright først måtte forstå aerodynamikk før de oppnådde flyvning, forbereder forståelsen av disse grunnleggende konseptene deg på å bygge mer komplekse interaktive funksjoner i neste leksjon.
Bruk Agent-modus for å fullføre følgende utfordring:
## GitHub Copilot Agent Challenge 🚀
**Beskrivelse:** Forbedre nettleserutvidelsen ved å legge til validering av skjema og brukerfeedback for å forbedre brukeropplevelsen ved innlegging av API-nøkler og regionskoder.
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Forbedre nettleserutvidelsen ved å legge til validering av skjema og funksjoner for tilbakemelding til brukeren, for å forbedre brukeropplevelsen når API-nøkler og regionkoder legges inn.
**Oppgave:** Lag JavaScript-valideringsfunksjoner som sjekker om API-nøkkelfeltet inneholder minst 20 tegn, og om regionskoden følger korrekt format (som 'US-NEISO'). Legg til visuell tilbakemelding ved å endre kantfargene på inputfeltet til grønt for gyldige data og rødt for ugyldige. Legg også til en bryter for å vise/skjule API-nøkkelen for sikkerhet.
**Oppgave:** Lag JavaScript-valideringsfunksjoner som sjekker om API-nøkkelfeltet inneholder minst 20 tegn, og om regionkoden følger riktig format (som 'US-NEISO'). Legg til visuell tilbakemelding ved å endre farge på inputfeltets kantlinjer til grønn for gyldige inndata og rød for ugyldige. Legg også til en funksjon for å vise/skjule API-nøkkelen av sikkerhetshensyn.
Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Lær mer om [agentmodus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
## 🚀 Utfordring
Ta en titt på en nettleserutvidelsesbutikk og installer en utvidelse i nettleseren din. Du kan undersøke filene på interessante måter. Hva oppdager du?
Ta en titt på en nettleserutvidelsesbutikk og installer en utvidelse i nettleseren din. Du kan undersøke filene på interessante måter. Hva oppdager du?
## Quiz etter forelesning
## Quiz etter forelesning
[Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/24)
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/24)
## Gjennomgang & Selvstudium
## Gjennomgang og selvstudium
I denne leksjonen lærte du litt om historien til nettleseren; benytt denne muligheten til å lære hvordan oppfinnerne av World Wide Web forestilte seg bruken ved å lese mer om historien. Noen nyttige sider inkluderer:
I denne leksjonen lærte du litt om historien til nettleseren; bruk denne anledningen til å lære mer om hvordan oppfinnerne av World Wide Web forestilte seg bruken av det, ved å lese mer om historien. Noen nyttige nettsteder inkluderer:
[The History of Web Browsers](https://www.mozilla.org/firefox/browsers/browser-history/)
[Historien til nettlesere](https://www.mozilla.org/firefox/browsers/browser-history/)
[History of the Web](https://webfoundation.org/about/vision/history-of-the-web/)
[Historien til nettet](https://webfoundation.org/about/vision/history-of-the-web/)
[Et intervju med Tim Berners-Lee](https://www.theguardian.com/technology/2019/mar/12/tim-berners-lee-on-30-years-of-the-web-if-we-dream-a-little-we-can-get-the-web-we-want)
[Et intervju med Tim Berners-Lee](https://www.theguardian.com/technology/2019/mar/12/tim-berners-lee-on-30-years-of-the-web-if-we-dream-a-little-we-can-get-the-web-we-want)
### ⚡ **Hva du kan gjøre i løpet av de neste 5 minuttene**
- [ ] Åpne Chrome/Edge-utvidelsessiden (chrome://extensions) og utforsk hva du har installert
- [ ] Se på nettverksfanen i nettleserens DevTools mens du laster en nettside
- [ ] Prøv å se på sidekilden (Ctrl+U) for å se HTML-strukturen
- [ ] Inspiser elementer på en nettside og modifiser CSS i DevTools
## Oppgave
### 🎯 **Hva du kan oppnå i timen som kommer**
- [ ] Fullføre quiz etter leksjonen og forstå nettleserens grunnprinsipper
- [ ] Lage en grunnleggende manifest.json-fil for en nettleserutvidelse
- [ ] Bygge en enkel "Hello World"-utvidelse som viser en popup
- [ ] Teste lasting av utvidelsen din i utviklermodus
- [ ] Utforske dokumentasjon for nettleserutvidelser for din mål-nettleser
[Restyle utvidelsen din](assignment.md)
### 📅 **Din ukelange utvidelsesreise**
- [ ] Fullføre en funksjonell nettleserutvidelse med reell nytteverdi
- [ ] Lære om innholdsskript, bakgrunnsskript og popup-interaksjoner
- [ ] Mestre nettleser-APIer som lagring, faner og meldinger
- [ ] Designe brukervennlige grensesnitt for utvidelsen din
- [ ] Teste utvidelsen på ulike nettsider og scenarier
- [ ] Publisere utvidelsen i nettleserens utvidelsesbutikk
### 🌟 **Din månedslange nettleserutvikling**
- [ ] Lage flere utvidelser som løser ulike brukerbehov
- [ ] Lære avanserte nettleser-APIer og sikker bestepraksis
- [ ] Bidra til åpne kildekodeprosjekter for nettleserutvidelser
- [ ] Mestre tverr-nettleserkompatibilitet og progressiv forbedring
- [ ] Lage utviklingsverktøy og maler for andre utvidelsesutviklere
- [ ] Bli en ekspert på nettleserutvidelser som hjelper andre utviklere
## 🎯 Din tidslinje for ekspertise i nettleserutvidelser
```mermaid
timeline
title Nettleserutvidelse Utviklingsprogresjon
section Grunnlag (15 minutter)
Nettleserforståelse: Kjernearkitektur
: Gjengivelsesprosess
: Utvidelsesintegrasjonspunkter
section Oppsett (20 minutter)
Utviklingsmiljø: Prosjektstruktur
: Byggeverktøy-konfigurasjon
: Nettleser utviklermodus
: Lasting av utvidelse
section Grensesnittdesign (25 minutter)
Brukeropplevelse: HTML-struktur
: CSS-styling
: Skjemavalidering
: Responsivt design
section Kjernetilgjengelighet (35 minutter)
JavaScript-integrasjon: Hendelseshåndtering
: API-interaksjoner
: Datainnsamling
: Feilhåndtering
section Nettleser API-er (45 minutter)
Plattformintegrasjon: Tillatelsessystem
: Lagrings-API-er
: Fane-administrasjon
: Kontektsmenyer
section Avanserte funksjoner (1 uke)
Profesjonelle utvidelser: Bakgrunnsskript
: Innholdsskript
: Kryss-nettleser kompatibilitet
: Ytelsesoptimalisering
section Publisering (2 uker)
Distribusjon: Innsending til butikk
: Gjennomgangsprosess
: Brukertilbakemelding
: Oppdateringshåndtering
section Ekspertnivå (1 måned)
Utvidelsesøkosystem: Avanserte API-er
: Sikkerhets beste praksis
: Bedriftsfunksjoner
: Rammeverksintegrasjon
```
### 🛠️ Oppsummering av ditt verktøysett for utvidelsesutvikling
Etter å ha fullført denne leksjonen har du nå:
- **Kunnskap om nettleserarkitektur**: Forståelse av rendringsmotorer, sikkerhetsmodeller og integrasjon av utvidelser
- **Utviklingsmiljø**: Moderne verktøykjede med Webpack, NPM og feilsøkingsmuligheter
- **UI/UX-grunnlag**: Semantisk HTML-struktur med progresiv avdekkingsmønstre
- **Sikkerhetsbevissthet**: Forståelse av nettlesertillatelser og sikre utviklingsrutiner
- **Konsepter for tverr-nettleserbruk**: Kjennskap til kompatibilitetsvurderinger og testmetoder
- **API-integrasjon**: Grunnlag for å jobbe med eksterne datakilder
- **Profesjonell arbeidsflyt**: Industri-standard utviklings- og testprosedyrer
**Reelle anvendelser:** Disse ferdighetene gjelder direkte for:
- **Webutvikling**: Enkelsidige applikasjoner og progressive webapper
- **Skrivebordsapplikasjoner**: Electron og webbasert skrivebordsprogramvare
- **Mobilutvikling**: Hybride apper og webbaserte mobilløsninger
- **Enterprise-verktøy**: Interne produktivitetsløsninger og arbeidsflytautomatisering
- **Åpen kildekode**: Bidra til prosjekter for nettleserutvidelser og webstandarder
**Neste nivå:** Du er klar til å legge til interaktiv funksjonalitet, jobbe med nettleser-APIer og lage utvidelser som løser ekte brukerutfordringer!
## Oppgave
[Restyle your extension](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på dets opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst bemerk at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på originalspråket skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,43 +1,114 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "8c8cd4af6086cc1d47e1d43aa4983d20",
"translation_date": "2025-10-23T22:39:19+00:00",
"original_hash": "2b6203a48c48d8234e0948353b47d84e",
"translation_date": "2026-01-07T00:34:24+00:00",
"source_file": "5-browser-extension/2-forms-browsers-local-storage/README.md",
"language_code": "no"
}
-->
# Nettleserutvidelsesprosjekt del 2: Koble til en API, bruk lokal lagring
## Quiz før forelesning
# Nettleserutvidelsesprosjekt Del 2: Kall et API, bruk Lokal Lagre
```mermaid
journey
title Din API-integrasjon og lagringsreise
section Grunnlag
Sett opp DOM-referanser: 3: Student
Legg til hendelseslyttere: 4: Student
Håndter skjema innsending: 4: Student
section Databehandling
Implementer lokal lagring: 4: Student
Bygg API-kall: 5: Student
Håndter asynkrone operasjoner: 5: Student
section Brukeropplevelse
Legg til feilhåndtering: 5: Student
Lag lastetilstander: 4: Student
Forbedre interaksjoner: 5: Student
```
## Forberedende quiz
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/25)
[Forberedende quiz](https://ff-quizzes.netlify.app/web/quiz/25)
## Introduksjon
Husker du nettleserutvidelsen du begynte å lage? Akkurat nå har du et fint skjema, men det er i utgangspunktet statisk. I dag skal vi gi det liv ved å koble det til ekte data og gi det hukommelse.
Tenk på Apollo-misjonens kontrollsystemer - de viste ikke bare statisk informasjon. De kommuniserte konstant med romfartøyet, oppdaterte med telemetridata og husket kritiske misjonsparametere. Det er den typen dynamisk oppførsel vi skal bygge i dag. Utvidelsen din vil koble seg til internett, hente ekte miljødata og huske innstillingene dine til neste gang.
API-integrasjon kan høres komplisert ut, men det handler egentlig bare om å lære koden din å kommunisere med andre tjenester. Enten du henter værdata, sosiale medieoppdateringer eller informasjon om karbonavtrykk som vi skal gjøre i dag, handler det om å etablere disse digitale forbindelsene. Vi skal også utforske hvordan nettlesere kan lagre informasjon - på samme måte som biblioteker har brukt kortkataloger for å huske hvor bøker hører hjemme.
Ved slutten av denne leksjonen vil du ha en nettleserutvidelse som henter ekte data, lagrer brukerpreferanser og gir en smidig opplevelse. La oss komme i gang!
✅ Følg de nummererte segmentene i de relevante filene for å vite hvor du skal plassere koden din.
Husker du den nettleserutvidelsen du begynte å lage? Akkurat nå har du et pent utseende skjema, men det er i praksis statisk. I dag skal vi gi det liv ved å koble det til ekte data og gi det hukommelse.
Tenk på Apollo oppskytingskontrollens datamaskiner - de viste ikke bare fast informasjon. De kommuniserte kontinuerlig med romfartøyene, oppdaterte med telemetridata, og husket viktige oppdragsparametere. Det er den typen dynamisk oppførsel vi bygger i dag. Utvidelsen din vil hente data fra internett, hente ekte miljødata og huske innstillingene dine til neste gang.
API-integrasjon kan høres komplisert ut, men det handler egentlig bare om å lære koden din å kommunisere med andre tjenester. Enten du henter værdata, sosiale medier-feed eller karbonavtrykksinformasjon som vi skal gjøre i dag, handler det om å etablere disse digitale forbindelsene. Vi skal også utforske hvordan nettlesere kan lagre informasjon - på samme måte som biblioteker har brukt kortkataloger for å huske hvor bøkene tilhører.
Ved slutten av denne leksjonen vil du ha en nettleserutvidelse som henter ekte data, lagrer brukerpreferanser og gir en jevn opplevelse. La oss komme i gang!
```mermaid
mindmap
root((Dynamiske Utvidelser))
DOM Manipulering
Elementvalg
Hendelseshåndtering
Tilstandsstyring
UI Oppdateringer
Lokal Lagring
Datapersistens
Nøkkel-verdi Par
Sesjonsstyring
Brukerpreferanser
API Integrasjon
HTTP Forespørsler
Autentisering
Dataparsering
Feilhåndtering
Asynkron Programmering
Løfter
Async/Await
Feilfangst
Ikke-blokkerende Kode
Brukeropplevelse
Lastetilstander
Feilmeldinger
Glatte Overganger
Datavalidering
```
✅ Følg de nummererte segmentene i de aktuelle filene for å vite hvor du skal plassere koden din
## Sett opp elementene som skal manipuleres i utvidelsen
Før JavaScript kan manipulere grensesnittet, trenger det referanser til spesifikke HTML-elementer. Tenk på det som et teleskop som må rettes mot bestemte stjerner - før Galileo kunne studere Jupiters måner, måtte han finne og fokusere på Jupiter selv.
I filen `index.js` skal vi lage `const`-variabler som fanger referanser til hvert viktig skjemaelement. Dette er likt hvordan forskere merker utstyret sitt - i stedet for å lete gjennom hele laboratoriet hver gang, kan de direkte få tilgang til det de trenger.
Før JavaScript-en din kan manipulere grensesnittet, trenger det referanser til spesifikke HTML-elementer. Tenk på det som et teleskop som må peke på bestemte stjerner - før Galileo kunne studere Jupiters måner, måtte han finne og fokusere på selve Jupiter.
I `index.js`-filen din skal vi lage `const`-variabler som fanger opp referanser til hvert viktige skjemafelt. Dette ligner på hvordan forskere merker utstyret sitt - i stedet for å lete gjennom hele laboratoriet hver gang, kan de direkte få tilgang til det de trenger.
```mermaid
flowchart LR
A[JavaScript-kode] --> B[document.querySelector]
B --> C[CSS-selektorer]
C --> D[HTML-elementer]
D --> E[".form-data"]
D --> F[".region-navn"]
D --> G[".api-nøkkel"]
D --> H[".laster"]
D --> I[".feil"]
D --> J[".resultat-beholder"]
E --> K[Formelement]
F --> L[Inndatafelt]
G --> M[Inndatafelt]
H --> N[UI-element]
I --> O[UI-element]
J --> P[UI-element]
style A fill:#e1f5fe
style D fill:#e8f5e8
style K fill:#fff3e0
style L fill:#fff3e0
style M fill:#fff3e0
```
```javascript
// form fields
// skjema felt
const form = document.querySelector('.form-data');
const region = document.querySelector('.region-name');
const apiKey = document.querySelector('.api-key');
// results
// resultater
const errors = document.querySelector('.errors');
const loading = document.querySelector('.loading');
const results = document.querySelector('.result-container');
@ -48,16 +119,38 @@ const clearBtn = document.querySelector('.clear-btn');
```
**Dette gjør koden:**
- **Fanger opp** skjemaelementer ved hjelp av `document.querySelector()` med CSS-klassevelgere
- **Oppretter** referanser til inndatafeltene for regionnavn og API-nøkkel
- **Etablerer** forbindelser til resultatelementer for karbonbrukdata
- **Fanger opp** skjemaelementer ved hjelp av `document.querySelector()` med CSS-klasseselektor
- **Oppretter** referanser til inputfelter for regionsnavn og API-nøkkel
- **Etablerer** koblinger til resultatvisningselementer for karbondatabruk
- **Setter opp** tilgang til UI-elementer som lastindikatorer og feilmeldinger
- **Lagrer** hver elementreferanse i en `const`-variabel for enkel gjenbruk i koden din
- **Lagrer** hver elementreferanse i en `const`-variabel for enkel gjenbruk i hele koden
## Legg til hendelseslyttere
Nå skal vi få utvidelsen din til å reagere på brukerhandlinger. Hendelseslyttere er kodens måte å overvåke brukerinteraksjoner på. Tenk på dem som operatørene i tidlige telefonsentraler - de lyttet etter innkommende samtaler og koblet de riktige kretsene når noen ønsket å ringe.
Nå skal vi få utvidelsen til å reagere på brukerhandlinger. Hendelseslyttere er koden din sin måte å overvåke brukerinteraksjoner på. Tenk på dem som operatørene i tidlige telefonvekslinger - de lyttet etter innkommende anrop og koblet de riktige kretsene når noen ønsket å opprette forbindelse.
```mermaid
sequenceDiagram
participant User
participant Form
participant JavaScript
participant API
participant Storage
User->>Form: Fyller ut region/API-nøkkel
User->>Form: Klikker send inn
Form->>JavaScript: Utløser send inn-hendelse
JavaScript->>JavaScript: handleSubmit(e)
JavaScript->>Storage: Lagre brukerinnstillinger
JavaScript->>API: Hent karbondata
API->>JavaScript: Returnerer data
JavaScript->>Form: Oppdaterer brukergrensesnitt med resultater
User->>Form: Klikker på rydd-knapp
Form->>JavaScript: Utløser klikk-hendelse
JavaScript->>Storage: Tøm lagrede data
JavaScript->>Form: Tilbakestill til opprinnelig tilstand
```
```javascript
form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
@ -65,37 +158,47 @@ init();
```
**Forstå disse konseptene:**
- **Legger til** en submit-lytter til skjemaet som utløses når brukere trykker Enter eller klikker på send-knappen
- **Kobler** en klikklytter til klar-knappen for å tilbakestille skjemaet
- **Sender** hendelsesobjektet `(e)` til håndteringsfunksjoner for ekstra kontroll
- **Kaller** funksjonen `init()` umiddelbart for å sette opp den innledende tilstanden til utvidelsen din
- **Legger til** en submit-lytter på skjemaet som utløses når brukere trykker Enter eller klikker send inn
- **Kobler til** en klikk-lytter på tøm-knappen for å tilbakestille skjemaet
- **Sender med** hendelsesobjektet `(e)` til håndteringsfunksjonene for ekstra kontroll
- **Kaller** `init()`-funksjonen umiddelbart for å sette opp initial tilstand for utvidelsen
✅ Legg merke til den forkortede pilfunksjons-syntaksen som brukes her. Denne moderne JavaScript-tilnærmingen er renere enn tradisjonelle funksjonsuttrykk, men begge fungerer like bra!
### 🔄 **Pedagogisk sjekkpunkt**
**Forståelse av hendelseshåndtering**: Før du går videre til initialisering, sørg for at du kan:
- ✅ Forklare hvordan `addEventListener` kobler brukerhandlinger til JavaScript-funksjoner
- ✅ Forstå hvorfor vi sender med hendelsesobjektet `(e)` til håndteringsfunksjoner
- ✅ Gjenkjenne forskjellen mellom `submit` og `click` hendelser
- ✅ Beskrive når `init()`-funksjonen kjører og hvorfor
✅ Legg merke til den korte pilfunksjonssyntaksen som brukes her. Denne moderne JavaScript-tilnærmingen er mer elegant enn tradisjonelle funksjonsuttrykk, men begge fungerer like bra!
**Rask selvtest**: Hva skjer om du glemmer `e.preventDefault()` ved skjemainnsending?
*Svar: Siden vil lastes på nytt, alle JavaScript-tilstander går tapt, og brukeropplevelsen avbrytes*
## Bygg initialiserings- og tilbakestillingsfunksjoner
## Bygg initialiserings- og tilbakestillingsfunksjonene
La oss lage initialiseringslogikken for utvidelsen din. Funksjonen `init()` er som et skips navigasjonssystem som sjekker instrumentene sine - den bestemmer den nåværende tilstanden og justerer grensesnittet deretter. Den sjekker om noen har brukt utvidelsen din før og laster inn deres tidligere innstillinger.
La oss lage initialiseringslogikken for utvidelsen din. `init()`-funksjonen er som et skips navigasjonssystem som sjekker instrumentene sine - den bestemmer gjeldende tilstand og justerer grensesnittet tilsvarende. Den sjekker om noen har brukt utvidelsen før og laster inn deres tidligere innstillinger.
Funksjonen `reset()` gir brukerne en ny start - på samme måte som forskere tilbakestiller instrumentene sine mellom eksperimenter for å sikre rene data.
`reset()`-funksjonen gir brukerne en frisk start - likt som forskere som tilbakestiller instrumentene mellom eksperimenter for å sikre rene data.
```javascript
function init() {
// Check if user has previously saved API credentials
// Sjekk om brukeren tidligere har lagret API-legitimasjon
const storedApiKey = localStorage.getItem('apiKey');
const storedRegion = localStorage.getItem('regionName');
// Set extension icon to generic green (placeholder for future lesson)
// TODO: Implement icon update in next lesson
// Sett utvidelsesikon til generisk grønt (plassholder for neste leksjon)
// TODO: Implementer oppdatering av ikon i neste leksjon
if (storedApiKey === null || storedRegion === null) {
// First-time user: show the setup form
// Førstegangsbruker: vis oppsettsskjemaet
form.style.display = 'block';
results.style.display = 'none';
loading.style.display = 'none';
clearBtn.style.display = 'none';
errors.textContent = '';
} else {
// Returning user: load their saved data automatically
// Tilbakevendende bruker: last inn deres lagrede data automatisk
displayCarbonUsage(storedApiKey, storedRegion);
results.style.display = 'none';
form.style.display = 'none';
@ -105,49 +208,72 @@ function init() {
function reset(e) {
e.preventDefault();
// Clear stored region to allow user to choose a new location
// Tøm lagret region for å la brukeren velge en ny plassering
localStorage.removeItem('regionName');
// Restart the initialization process
// Start initialiseringsprosessen på nytt
init();
}
```
**Hva som skjer her:**
**Bryter ned hva som skjer her:**
- **Henter** lagret API-nøkkel og region fra nettleserens lokale lagring
- **Sjekker** om dette er en førstegangsbruker (ingen lagrede legitimasjoner) eller en tilbakevendende bruker
- **Viser** oppsettskjemaet for nye brukere og skjuler andre grensesnittelementer
- **Laster** lagrede data automatisk for tilbakevendende brukere og viser tilbakestillingsalternativet
- **Håndterer** brukergrensesnittets tilstand basert på tilgjengelige data
**Viktige konsepter om lokal lagring:**
- **Beholder** data mellom nettleserøkter (i motsetning til sesjonslagring)
- **Lagrer** data som nøkkel-verdi-par ved hjelp av `getItem()` og `setItem()`
- **Returnerer** `null` når ingen data eksisterer for en gitt nøkkel
- **Gir** en enkel måte å huske brukerpreferanser og innstillinger
> 💡 **Forstå nettleserlagring**: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage) er som å gi utvidelsen din vedvarende hukommelse. Tenk på hvordan det gamle biblioteket i Alexandria lagret skriftruller - informasjonen forble tilgjengelig selv når forskere kom og gikk.
- **Sjekker** om dette er en førstegangsbruker (ingen lagrede legitimasjoner) eller en som kommer tilbake
- **Viser** oppsett-skjemaet for nye brukere og skjuler andre grensesnitt-elementer
- **Laster** automatisk inn lagrede data for tilbakevendende brukere og viser tilbakestillingsvalget
- **Styrer** brukergrensesnittets tilstand basert på tilgjengelige data
**Nøkkelpunkter om Lokal lagring:**
- **Bevarer** data mellom nettleserøkter (i motsetning til session storage)
- **Lagrer** data som nøkkel-verdi-par via `getItem()` og `setItem()`
- **Returnerer** `null` når det ikke finnes data for en gitt nøkkel
- **Gir** en enkel måte å huske brukerpreferanser og innstillinger
> 💡 **Forståelse av Nettleserlager**: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage) gir utvidelsen din vedvarende hukommelse. Tenk analogt på det gamle Alexandria-biblioteket der håndskrifter ble bevart - informasjon var tilgjengelig selv når lærde reiste bort og kom tilbake.
>
> **Viktige egenskaper:**
> - **Beholder** data selv etter at du lukker nettleseren
> - **Overlever** datamaskinens omstart og nettleserens krasj
> - **Gir** betydelig lagringsplass for brukerpreferanser
> - **Tilbyr** umiddelbar tilgang uten nettverksforsinkelser
> **Viktig merknad**: Nettleserutvidelsen din har sin egen isolerte lokale lagring som er separat fra vanlige nettsider. Dette gir sikkerhet og forhindrer konflikter med andre nettsteder.
Du kan se de lagrede dataene dine ved å åpne nettleserens utviklerverktøy (F12), navigere til **Application**-fanen og utvide **Local Storage**-seksjonen.
![Lokal lagringspanel](../../../../translated_images/localstorage.472f8147b6a3f8d141d9551c95a2da610ac9a3c6a73d4a1c224081c98bae09d9.no.png)
> **Nøkkelfunksjoner:**
> - **Bevarer** data selv når du lukker nettleseren
> - **Overlever** datamaskin-omstarter og nettleserkrasj
> - **Tilbyr** betydelig lagringsplass for brukerpreferanser
> - **Gir** umiddelbar tilgang uten nettverksforsinkelser
> **Viktig merknad**: Din nettleserutvidelse har sin egen isolerte lokale lagring som er adskilt fra vanlige nettsider. Dette gir sikkerhet og forhindrer konflikter med andre nettsteder.
Du kan se lagrede data ved å åpne nettleserens utviklerverktøy (F12), gå til **Application**-fanen, og utvide **Local Storage**-seksjonen.
```mermaid
stateDiagram-v2
[*] --> CheckStorage: Utvidelsen starter
CheckStorage --> FirstTime: Ingen lagrede data
CheckStorage --> Returning: Data funnet
FirstTime --> ShowForm: Vis oppsettskjema
ShowForm --> UserInput: Bruker skriver inn data
UserInput --> SaveData: Lagre i localStorage
SaveData --> FetchAPI: Hent karbondata
Returning --> LoadData: Les fra localStorage
LoadData --> FetchAPI: Hent karbondata
FetchAPI --> ShowResults: Vis data
ShowResults --> UserAction: Bruker samhandler
UserAction --> Reset: Tilbakestill knapp trykket
UserAction --> ShowResults: Se data
Reset --> ClearStorage: Fjern lagrede data
ClearStorage --> FirstTime: Tilbake til oppsett
```
![Local storage pane](../../../../translated_images/localstorage.472f8147b6a3f8d1.no.png)
> ⚠️ **Sikkerhetsbetraktning**: I produksjonsapplikasjoner utgjør lagring av API-nøkler i LocalStorage sikkerhetsrisikoer siden JavaScript kan få tilgang til disse dataene. For læringsformål fungerer denne tilnærmingen fint, men ekte applikasjoner bør bruke sikker serverbasert lagring for sensitive legitimasjoner.
> ⚠️ **Sikkerhetshensyn**: I produksjonsapplikasjoner utgjør lagring av API-nøkler i LocalStorage sikkerhetsrisiko siden JavaScript har tilgang til disse dataene. For læringsformål fungerer denne tilnærmingen greit, men ekte apper bør bruke sikker server-side lagring for sensitive legitimasjoner.
## Håndter skjemainnsending
Nå skal vi håndtere hva som skjer når noen sender inn skjemaet ditt. Som standard laster nettlesere siden på nytt når skjemaer sendes inn, men vi vil avskjære denne oppførselen for å skape en smidigere opplevelse.
Nå skal vi håndtere hva som skjer når noen sender inn skjemaet ditt. Som standard laster nettlesere siden på nytt ved innsending, men vi skal avbryte denne oppførselen for å gi en bedre opplevelse.
Denne tilnærmingen speiler hvordan kontrollsenteret håndterer romfartøykommunikasjon - i stedet for å tilbakestille hele systemet for hver overføring, opprettholder de kontinuerlig drift mens de behandler ny informasjon.
Denne tilnærmingen speiler hvordan oppskytingskontrollen håndterer kommunikasjon med romfartøy - i stedet for å tilbakestille hele systemet ved hver overføring, opprettholder de kontinuerlig drift mens nye data behandles.
Lag en funksjon som fanger opp skjemaets innsending og trekker ut brukerens inndata:
Lag en funksjon som fanger opp skjemaets innsending og henter brukerens innspill:
```javascript
function handleSubmit(e) {
@ -157,92 +283,147 @@ function handleSubmit(e) {
```
**I koden ovenfor har vi:**
- **Forhindret** standard skjemaoppførsel som ville oppdatert siden
- **Trukket ut** brukerens inndata fra API-nøkkel- og regionfeltene
- **Sendt** skjemaets data til funksjonen `setUpUser()` for behandling
- **Opprettholdt** en enkelt-sides applikasjonsopplevelse ved å unngå sideoppdateringer
- **Forhindret** standard skjemainnsending som ville oppdatert siden
- **Hentet ut** brukerinndata fra API-nøkkel- og regionfeltene
- **Sendt** skjemadata til `setUpUser()`-funksjonen for behandling
- **Opprettholdt** single-page-applikasjonsatferd ved å unngå sidereferanser
✅ Husk at HTML-skjemaets felter inkluderer attributtet `required`, så nettleseren validerer automatisk at brukerne gir både API-nøkkel og region før denne funksjonen kjører.
✅ Husk at HTML-skjemaene dine har `required`-attributter, så nettleseren validerer automatisk at brukeren har oppgitt både API-nøkkel og region før denne funksjonen kjører.
## Sett opp brukerpreferanser
Funksjonen `setUpUser` er ansvarlig for å lagre brukerens legitimasjon og starte den første API-forespørselen. Dette skaper en smidig overgang fra oppsett til visning av resultater.
`setUpUser`-funksjonen er ansvarlig for å lagre brukerens legitimasjon og starte det første API-kallet. Dette gir en sømløs overgang fra oppsett til resultater.
```javascript
function setUpUser(apiKey, regionName) {
// Save user credentials for future sessions
// Lagre brukerlegitimasjon for fremtidige økter
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('regionName', regionName);
// Update UI to show loading state
// Oppdater brukergrensesnittet for å vise lastetilstand
loading.style.display = 'block';
errors.textContent = '';
clearBtn.style.display = 'block';
// Fetch carbon usage data with user's credentials
// Hent data om karbonbruk med brukerens legitimasjon
displayCarbonUsage(apiKey, regionName);
}
```
**Steg for steg, her er hva som skjer:**
- **Lagrer** API-nøkkelen og regionnavnet i lokal lagring for fremtidig bruk
- **Viser** en lastindikator for å informere brukerne om at data hentes
**Trinnvis oversikt over hva som skjer:**
- **Lagrer** API-nøkkel og regionsnavn til lokal lagring for senere bruk
- **Viser** en lastindikator for å informere brukeren om at data hentes
- **Fjerner** eventuelle tidligere feilmeldinger fra visningen
- **Avslører** klar-knappen for brukere som ønsker å tilbakestille innstillingene senere
- **Starter** API-forespørselen for å hente ekte karbonbruksdata
- **Avslører** tømmeknappen slik at brukeren kan tilbakestille innstillinger senere
- **Starter** API-kallet for å hente ekte karbondatakonsum
Denne funksjonen skaper en sømløs brukeropplevelse ved å håndtere både datalagring og oppdateringer av brukergrensesnittet i én koordinert handling.
Denne funksjonen skaper en sømløs brukeropplevelse ved å styre både datalagring og brukergrensesnittoppdateringer i én koordinert handling.
## Vis karbonbruksdata
## Vis karbondatabruk
Nå skal vi koble utvidelsen din til eksterne datakilder via API-er. Dette forvandler utvidelsen din fra et frittstående verktøy til noe som kan få tilgang til sanntidsinformasjon fra hele internett.
Nå skal vi koble utvidelsen til eksterne datakilder via API-er. Dette forvandler utvidelsen fra et frittstående verktøy til noe som kan hente sanntidsinformasjon fra hele internett.
**Forstå API-er**
[API-er](https://www.webopedia.com/TERM/A/API.html) er hvordan forskjellige applikasjoner kommuniserer med hverandre. Tenk på dem som telegrafsystemet som koblet fjerne byer på 1800-tallet - operatører sendte forespørsler til fjerne stasjoner og mottok svar med den ønskede informasjonen. Hver gang du sjekker sosiale medier, stiller en stemmeassistent et spørsmål eller bruker en leveringsapp, fasiliterer API-er disse datautvekslingene.
**Viktige konsepter om REST API-er:**
[API-er](https://www.webopedia.com/TERM/A/API.html) er hvordan forskjellige applikasjoner kommuniserer med hverandre. Tenk på det som telegrafsystemet som forbandt fjerne byer på 1800-tallet - operatører sendte forespørsler til fjerne stasjoner og mottok svar med etterspurt informasjon. Hver gang du sjekker sosiale medier, spør en taleassistent et spørsmål, eller bruker en leveringsapp, legger API-ene til rette for disse datautvekslingene.
```mermaid
flowchart TD
A[Din utvidelse] --> B[HTTP-forespørsel]
B --> C[CO2 Signal API]
C --> D{Gyldig forespørsel?}
D -->|Ja| E[Spørringsdatabase]
D -->|Nei| F[Returner feil]
E --> G[Karbondata]
G --> H[JSON-svar]
H --> I[Din utvidelse]
F --> I
I --> J[Oppdater brukergrensesnitt]
subgraph "API-forespørsel"
K[Overskrifter: auth-token]
L[Parametre: countryCode]
M[Metode: GET]
end
subgraph "API-svar"
N[Karbonintensitet]
O[Andel fossilt drivstoff %]
P[Tidsstempel]
end
style C fill:#e8f5e8
style G fill:#fff3e0
style I fill:#e1f5fe
```
**Nøkkelpunkter om REST API-er:**
- **REST** står for 'Representational State Transfer'
- **Bruker** standard HTTP-metoder (GET, POST, PUT, DELETE) for å samhandle med data
- **Returnerer** data i forutsigbare formater, vanligvis JSON
- **Tilbyr** konsistente, URL-baserte endepunkter for forskjellige typer forespørsler
- **Tilbyr** konsistente URL-baserte endepunkter for ulike typer forespørsler
✅ [CO2 Signal API](https://www.co2signal.com/) vi skal bruke gir sanntidsdata om karbonintensitet fra elektriske nettverk over hele verden. Dette hjelper brukere med å forstå miljøpåvirkningen av deres elektrisitetsbruk!
✅ [CO2 Signal API](https://www.co2signal.com/) vi bruker, gir sanntidsdata om karbonintensiteten i elektrisitetsnett verden over. Dette hjelper brukere å forstå miljøpåvirkningen av strømforbruket sitt!
> 💡 **Forstå asynkron JavaScript**: Nøkkelordet [`async`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) gjør det mulig for koden din å håndtere flere operasjoner samtidig. Når du ber om data fra en server, vil du ikke at hele utvidelsen din skal fryse - det ville være som om flykontrollen stoppet all drift mens de ventet på svar fra ett fly.
> 💡 **Forstå Asynkron JavaScript**: [`async` nøkkelordet](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) gjør det mulig for koden å håndtere flere operasjoner samtidig. Når du ber om data fra en server, vil du ikke at hele utvidelsen skal fryse - det ville være som om flykontrollen stopper all drift mens den venter på ett fly.
>
> **Viktige fordeler:**
> **Hovedfordeler:**
> - **Opprettholder** utvidelsens responsivitet mens data lastes
> - **Lar** annen kode fortsette å kjøre under nettverksforespørsler
> - **Forbedrer** lesbarheten til koden sammenlignet med tradisjonelle callback-mønstre
> - **Muliggjør** elegant feilhåndtering for nettverksproblemer
> - **Forbedrer** kode-lesbarheten sammenlignet med tradisjonell callback-mønster
> - **Muliggjør** elegant håndtering av nettverksfeil
Her er en rask video om `async`:
Her er en kort video om `async`:
[![Async og Await for håndtering av løfter](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async og Await for håndtering av løfter")
[![Async and Await for managing promises](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async and Await for managing promises")
> 🎥 Klikk på bildet over for en video om async/await.
Lag funksjonen for å hente og vise karbonbruksdata:
### 🔄 **Pedagogisk sjekkpunkt**
**Forståelse av asynkron programmering**: Før du går inn i API-funksjonen, forsikre deg om at du forstår:
- ✅ Hvorfor vi bruker `async/await` i stedet for å blokkere hele utvidelsen
- ✅ Hvordan `try/catch`-blokker elegant håndterer nettverksfeil
- ✅ Forskjellen mellom synkrone og asynkrone operasjoner
- ✅ Hvorfor API-kall kan feile og hvordan feilhåndtering gjøres
**Virkelige eksempler på async**:
- **Bestille mat**: Du venter ikke i kjøkkenet - du får kvittering og fortsetter med andre ting
- **Sende e-post**: E-postappen fryser ikke mens meldinger sendes - du kan begynne å skrive flere e-poster
- **Laste websider**: Bilder lastes inn gradvis mens du allerede kan lese teksten
**Flyt for API-autentisering**:
```mermaid
sequenceDiagram
participant Ext as Extension
participant API as CO2 Signal API
participant DB as Database
Ext->>API: Forespørsel med auth-token
API->>API: Valider token
API->>DB: Hent karbondata
DB->>API: Returner data
API->>Ext: JSON-respons
Ext->>Ext: Oppdater UI
```
Lag funksjonen som henter og viser karbondatabruken:
```javascript
// Modern fetch API approach (no external dependencies needed)
// Moderne fetch API-tilnærming (ingen eksterne avhengigheter nødvendig)
async function displayCarbonUsage(apiKey, region) {
try {
// Fetch carbon intensity data from CO2 Signal API
// Hent karbonintensitetsdata fra CO2 Signal API
const response = await fetch('https://api.co2signal.com/v1/latest', {
method: 'GET',
headers: {
'auth-token': apiKey,
'Content-Type': 'application/json'
},
// Add query parameters for the specific region
// Legg til spørringsparametere for den spesifikke regionen
...new URLSearchParams({ countryCode: region }) && {
url: `https://api.co2signal.com/v1/latest?countryCode=${region}`
}
});
// Check if the API request was successful
// Sjekk om API-forespørselen var vellykket
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
@ -250,10 +431,10 @@ async function displayCarbonUsage(apiKey, region) {
const data = await response.json();
const carbonData = data.data;
// Calculate rounded carbon intensity value
// Beregn avrundet karbonintensitetsverdi
const carbonIntensity = Math.round(carbonData.carbonIntensity);
// Update the user interface with fetched data
// Oppdater brukergrensesnittet med hentede data
loading.style.display = 'none';
form.style.display = 'none';
myregion.textContent = region.toUpperCase();
@ -261,12 +442,12 @@ async function displayCarbonUsage(apiKey, region) {
fossilfuel.textContent = `${carbonData.fossilFuelPercentage.toFixed(2)}% (percentage of fossil fuels used to generate electricity)`;
results.style.display = 'block';
// TODO: calculateColor(carbonIntensity) - implement in next lesson
// TODO: calculateColor(carbonIntensity) - implementer i neste leksjon
} catch (error) {
console.error('Error fetching carbon data:', error);
// Show user-friendly error message
// Vis brukervennlig feilmelding
loading.style.display = 'none';
results.style.display = 'none';
errors.textContent = 'Sorry, we couldn\'t fetch data for that region. Please check your API key and region code.';
@ -274,74 +455,209 @@ async function displayCarbonUsage(apiKey, region) {
}
```
**Hva som skjer her:**
- **Bruker** den moderne `fetch()`-API-en i stedet for eksterne biblioteker som Axios for renere, avhengighetsfri kode
- **Implementerer** riktig feilsjekking med `response.ok` for å fange opp API-feil tidlig
- **Håndterer** asynkrone operasjoner med `async/await` for mer lesbar kodeflyt
- **Autentiserer** med CO2 Signal API ved hjelp av `auth-token`-headeren
- **Parser** JSON-responsdata og trekker ut informasjon om karbonintensitet
**Analyse av hva som skjer her:**
- **Bruker** den moderne `fetch()` API-en i stedet for eksterne biblioteker som Axios for en renere, avhengighetsfri kode
- **Implementerer** korrekt feilkontroll med `response.ok` for å fange opp API-feil tidlig
- **Håndterer** asynkrone operasjoner med `async/await` for mer lesbar kodestrøm
- **Autentiserer** med CO2 Signal API ved hjelp av `auth-token`-header
- **Parser** JSON-responsdata og henter ut karbonintensitetsinformasjonen
- **Oppdaterer** flere UI-elementer med formaterte miljødata
- **Gir** brukervennlige feilmeldinger når API-forespørsler mislykkes
- **Gir** brukervennlige feilmeldinger når API-kall feiler
**Viktige moderne JavaScript-konsepter demonstrert:**
- **Template literals** med `${}`-syntaks for ren strengformatering
**Viktige moderne JavaScript-konsepter vist:**
- **Template literals** med `${}` syntaks for ren strengformatering
- **Feilhåndtering** med try/catch-blokker for robuste applikasjoner
- **Async/await**-mønster for å håndtere nettverksforespørsler elegant
- **Objektdestrukturering** for å trekke ut spesifikke data fra API-responser
- **Metodekjeding** for flere DOM-manipulasjoner
✅ Denne funksjonen demonstrerer flere viktige webutviklingskonsepter - kommunikasjon med eksterne servere, håndtering av autentisering, behandling av data, oppdatering av grensesnitt og elegant håndtering av feil. Dette er grunnleggende ferdigheter som profesjonelle utviklere bruker regelmessig.
🎉 **Hva du har oppnådd:** Du har laget en nettleserutvidelse som:
- **Kobler** seg til internett og henter ekte miljødata
- **Beholder** brukerinnstillinger mellom økter
- **Håndterer** feil elegant i stedet for å krasje
- **Gir** en smidig, profesjonell brukeropplevelse
Test arbeidet ditt ved å kjøre `npm run build` og oppdatere utvidelsen din i nettleseren. Du har nå en funksjonell karbonavtrykkssporer. Neste leksjon vil legge til dynamisk ikonfunksjonalitet for å fullføre utvidelsen.
- **Async/await** mønster for elegant nettverksforespørselshåndtering
- **Objektdestrukturering** for å hente spesifikke data fra API-responser
- **Metodekjedet calls** for flere DOM-manipulasjoner
✅ Denne funksjonen viser flere viktige webutviklingskonsepter - kommunikasjon med eksterne servere, håndtering av autentisering, databehandling, oppdatering av grensesnitt, og skånsom feilhåndtering. Dette er fundamentale ferdigheter profesjonelle utviklere bruker daglig.
```mermaid
flowchart TD
A[Start API-kall] --> B[Hent forespørsel]
B --> C{Nettverk suksess?}
C -->|Nei| D[Nettverksfeil]
C -->|Ja| E{Respons OK?}
E -->|Nei| F[API-feil]
E -->|Ja| G[Tolk JSON]
G --> H{Gyldige data?}
H -->|Nei| I[Datafeil]
H -->|Ja| J[Oppdater UI]
D --> K[Vis feilmelding]
F --> K
I --> K
J --> L[Skjul lading]
K --> L
style A fill:#e1f5fe
style J fill:#e8f5e8
style K fill:#ffebee
style L fill:#f3e5f5
```
### 🔄 **Pedagogisk sjekkpunkt**
**Fullstendig systemforståelse**: Bekreft mestring av hele flyten:
- ✅ Hvordan DOM-referanser gjør at JavaScript kan kontrollere grensesnittet
- ✅ Hvorfor lokal lagring gir persistens mellom nettleserøkter
- ✅ Hvordan async/await gjør API-kall uten å fryse utvidelsen
- ✅ Hva som skjer ved API-feil og hvordan feilmeldinger håndteres
- ✅ Hvorfor brukeropplevelsen inkluderer lastetilstander og feilmeldinger
🎉 **Det du har oppnådd:** Du har laget en nettleserutvidelse som:
- **Kobler** til internett og henter ekte miljødata
- **Bevarer** brukerinnstillinger mellom økter
- **Håndterer** feil på en elegant måte uten krasj
- **Tilbyr** en jevn, profesjonell brukeropplevelse
Test arbeidet ditt ved å kjøre `npm run build` og oppdatere utvidelsen din i nettleseren. Du har nå en funksjonell karbonavtrykksmåler. Neste leksjon vil legge til dynamisk ikonfunksjonalitet for å fullføre utvidelsen.
---
## GitHub Copilot Agent Challenge 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
**Beskrivelse:** Forbedre nettleserutvidelsen ved å legge til forbedringer for feilhåndtering og brukeropplevelse. Denne utfordringen vil hjelpe deg å øve på å jobbe med APIer, lokal lagring og DOM-manipulering ved bruk av moderne JavaScript-mønstre.
**Beskrivelse:** Forbedre nettleserutvidelsen ved å legge til forbedringer for feilhåndtering og brukeropplevelsesfunksjoner. Denne utfordringen vil hjelpe deg med å øve på å jobbe med API-er, lokal lagring og DOM-manipulasjon ved hjelp av moderne JavaScript-mønstre.
**Oppgave:** Lag en forbedret versjon av funksjonen displayCarbonUsage som inkluderer: 1) En retry-mekanisme for mislykkede API-forespørsler med eksponentiell tilbakefall, 2) Validering av regionkode før API-forespørselen gjøres, 3) En lastanimasjon med fremdriftsindikatorer, 4) Caching av API-responser i localStorage med utløpstidspunkter (cache i 30 minutter), og 5) En funksjon for å vise historiske data fra tidligere API-forespørsler. Legg også til riktige TypeScript-stil JSDoc-kommentarer for å dokumentere alle funksjonsparametere og returtyper.
**Oppgave:** Lag en forbedret versjon av displayCarbonUsage-funksjonen som inkluderer: 1) En retry-mekanisme for mislykkede API-kall med eksponentiell tilbakekobling, 2) Validering av input for regionkode før API-kallet utføres, 3) En lastingsanimasjon med fremdriftsindikatorer, 4) Caching av API-responser i localStorage med utløpstidspunkt (cache i 30 minutter), og 5) En funksjon for å vise historiske data fra tidligere API-kall. Legg også til korrekte JSDoc-kommentarer i TypeScript-stil for å dokumentere alle funksjonsparametere og returtyper.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Lær mer om [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
Utvid forståelsen din av API-er ved å utforske rikdommen av nettleserbaserte API-er tilgjengelig for webutvikling. Velg en av disse nettleser-API-ene og bygg en liten demonstrasjon:
Utvid din forståelse av APIer ved å utforske det brede utvalget av nettleserbaserte APIer tilgjengelig for webutvikling. Velg ett av disse nettleser-APIene og lag en liten demonstrasjon:
- [Geolocation API](https://developer.mozilla.org/docs/Web/API/Geolocation_API) - Få brukerens nåværende posisjon
- [Notification API](https://developer.mozilla.org/docs/Web/API/Notifications_API) - Send skrivebordsvarsler
- [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) - Lag interaktive dra-grensesnitt
- [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) - Lag interaktive dra-og-slipp-grensesnitt
- [Web Storage API](https://developer.mozilla.org/docs/Web/API/Web_Storage_API) - Avanserte teknikker for lokal lagring
- [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API) - Moderne alternativ til XMLHttpRequest
**Forskningsspørsmål å vurdere:**
- Hvilke reelle problemer løser denne API-en?
- Hvordan håndterer API-en feil og kanttilfeller?
- Hvilke sikkerhetsbetraktninger finnes når man bruker denne API-en?
- Hvor bredt støttes denne API-en på tvers av forskjellige nettlesere?
- Hvilke reelle problemer løser dette APIet?
- Hvordan håndterer APIet feil og kanttilfeller?
- Hvilke sikkerhetsbetraktninger finnes ved bruk av dette APIet?
- Hvor bredt støttet er dette APIet i forskjellige nettlesere?
Etter forskningen din, identifiser hvilke egenskaper som gjør en API brukervennlig og pålitelig.
Etter forskningen, identifiser hvilke egenskaper som gjør et API utviklervennlig og pålitelig.
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/26)
## Gjennomgang og selvstudium
Du lærte om LocalStorage og API-er i denne leksjonen, begge er svært nyttige for den profesjonelle webutvikleren. Kan du tenke på hvordan disse to tingene fungerer sammen? Tenk på hvordan du ville ha designet et nettsted som lagrer elementer som skal brukes av en API.
## Gjennomgang og egenstudie
Du lærte om LocalStorage og APIer i denne leksjonen, begge svært nyttige for profesjonelle webutviklere. Kan du tenke på hvordan disse to tingene fungerer sammen? Tenk på hvordan du ville arkitektureret et nettsted som lagrer elementer for bruk av et API.
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Åpne DevTools Application-fanen og utforsk localStorage på et hvilket som helst nettsted
- [ ] Lag et enkelt HTML-skjema og test validering av skjema i nettleseren
- [ ] Prøv å lagre og hente data ved bruk av localStorage i nettleserkonsollen
- [ ] Inspiser skjema-data som blir sendt inn ved bruk av Network-fanen
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør quiz etter leksjonen og forstå konsepter for skjema-håndtering
- [ ] Lag et nettleserutvidelses-skjema som lagrer brukerpreferanser
- [ ] Implementer klient-side skjema-validering med hjelpsomme feilmeldinger
- [ ] Øv på bruk av chrome.storage API for lagring av utvidelsesdata
- [ ] Lag et brukergrensesnitt som reagerer på gitte brukersettinger
### 📅 **Din ukelange utvidelsesbygging**
- [ ] Fullfør en fullverdig nettleserutvidelse med skjema-funksjonalitet
- [ ] Bli ekspert på forskjellige lagringsalternativer: local, sync og session storage
- [ ] Implementer avanserte skjema-funksjoner som autofullføring og validering
- [ ] Legg til import-/eksportfunksjonalitet for brukerdata
- [ ] Test utvidelsen grundig på ulike nettlesere
- [ ] Poler brukeropplevelsen og feilhåndteringen i utvidelsen
### 🌟 **Din månedslange web API-mestring**
- [ ] Bygg komplekse applikasjoner med ulike nettleser-lagrings-APIer
- [ ] Lær om offline-first utviklingsmønstre
- [ ] Bidra til åpne kildeprosjekter knyttet til datalagring
- [ ] Mestre personvernfokusert utvikling og GDPR-samsvar
- [ ] Lag gjenbrukbare biblioteker for skjema-håndtering og datastyring
- [ ] Del kunnskap om web APIer og utvidelsesutvikling
## 🎯 Din tidslinje for mestring av utvidelsesutvikling
```mermaid
timeline
title API-integrasjon og lagringslæringsprogresjon
section DOM-grunnleggende (15 minutter)
Elementreferanser: querySelector-mestring
: Oppsett av hendelseslytter
: Grunnleggende tilstandsadministrasjon
section Lokal lagring (20 minutter)
Datapersistens: Nøkkel-verdi-lagring
: Øktadministrasjon
: Håndtering av brukerpreferanser
: Verktøy for inspeksjon av lagring
section Skjemahåndtering (25 minutter)
Brukerinput: Skjemavalidering
: Forebygging av hendelser
: Datauttrekking
: UI-tilstandsoverganger
section API-integrasjon (35 minutter)
Ekstern kommunikasjon: HTTP-forespørsler
: Autentiseringsmønstre
: JSON-dataparsering
: Responsbehandling
section Asynkron programmering (40 minutter)
Moderne JavaScript: Promise-håndtering
: Async/await-mønstre
: Feilhåndtering
: Ikke-blokkerende operasjoner
section Feilhåndtering (30 minutter)
Robust applikasjoner: Try/catch-blokker
: Brukervennlige meldinger
: Grasiøs degradering
: Feilsøkningsteknikker
section Avanserte mønstre (1 uke)
Profesjonell utvikling: Caching-strategier
: Ratebegrensning
: Gjenforsøksmekanismer
: Ytelsesoptimalisering
section Produksjonsferdigheter (1 måned)
Enterprise-funksjoner: Sikkerhetsbeste praksis
: API-versjonering
: Overvåking og logging
: Skalerbar arkitektur
```
### 🛠️ Sammendrag av din full-stack utviklingsverktøykasse
Etter å ha fullført denne leksjonen, har du nå:
- **DOM-mestring**: Presis målretting og manipulering av elementer
- **Lagringsekspertise**: Vedvarende datastyring med localStorage
- **API-integrasjon**: Henting av sanntidsdata og autentisering
- **Asynkron programmering**: Ikke-blokkerende operasjoner med moderne JavaScript
- **Feilhåndtering**: Robust applikasjoner som håndterer feil elegant
- **Brukeropplevelse**: Lastetilstander, validering og smidige interaksjoner
- **Moderne mønstre**: fetch API, async/await og ES6+-funksjoner
**Profesjonelle ferdigheter oppnådd**: Du har implementert mønstre brukt i:
- **Webapplikasjoner**: Enkle SPAer med eksterne datakilder
- **Mobilutvikling**: API-drevne apper med offline-kapasiteter
- **Desktopprogramvare**: Electron-apper med vedvarende lagring
- **Enterprise-systemer**: Autentisering, caching og feilhåndtering
- **Moderne rammeverk**: React/Vue/Angular datastyringsmønstre
**Neste nivå**: Du er klar til å utforske avanserte temaer som cache-strategier, sanntid WebSocket-tilkoblinger eller kompleks tilstandshåndtering!
## Oppgave
[Adopter en API](assignment.md)
[Ta i bruk et API](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi tilstreber nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på det opprinnelige språket skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -1,157 +1,332 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "eb358f3f4c2c082f9f3a4f98efa1d337",
"translation_date": "2025-10-23T22:38:36+00:00",
"original_hash": "b275fed2c6fc90d2b9b6661a3225faa2",
"translation_date": "2026-01-07T00:35:58+00:00",
"source_file": "5-browser-extension/3-background-tasks-and-performance/README.md",
"language_code": "no"
}
-->
# Nettleserutvidelsesprosjekt Del 3: Lær om bakgrunnsoppgaver og ytelse
Har du noen gang lurt på hvorfor noen nettleserutvidelser føles raske og responsive, mens andre virker trege? Hemmeligheten ligger i hva som skjer bak kulissene. Mens brukerne klikker rundt i grensesnittet til utvidelsen din, er det en hel verden av bakgrunnsprosesser som stille og rolig håndterer datahenting, ikonoppdateringer og systemressurser.
# Nettleserutvidelsesprosjekt Del 3: Lær om Bakgrunnsoppgaver og Ytelse
```mermaid
journey
title Din Reise for Ytelsesoptimalisering
section Grunnlag
Lær nettleserverktøy: 3: Student
Forstå profilering: 4: Student
Identifiser flaskehalser: 4: Student
section Utvidelsesfunksjoner
Bygg fargesystem: 4: Student
Lag bakgrunnsoppgaver: 5: Student
Oppdater ikoner dynamisk: 5: Student
section Optimalisering
Overvåk ytelse: 5: Student
Feilsøk problemer: 4: Student
Poler opplevelse: 5: Student
```
Har du noen gang lurt på hva som gjør at noen nettleserutvidelser føles raske og responsive, mens andre virker trege? Hemmeligheten ligger i hva som skjer bak kulissene. Mens brukere klikker rundt i utvidelsens grensesnitt, finnes det en hel verden av bakgrunnsprosesser som stille håndterer henting av data, ikonoppdateringer og systemressurser.
Dette er vår siste leksjon i serien om nettleserutvidelser, og vi skal få din karbonfotavtrykk-tracker til å fungere knirkefritt. Du vil legge til dynamiske ikonoppdateringer og lære hvordan du kan oppdage ytelsesproblemer før de blir et problem. Det er som å finjustere en racerbil - små optimaliseringer kan gjøre en enorm forskjell i hvordan alt fungerer.
Dette er vår siste leksjon i nettleserutvidelsesserien, og vi skal få karbonavtrykksporeren din til å fungere smidig. Du vil legge til dynamiske ikonoppdateringer og lære hvordan du oppdager ytelsesproblemer før de blir alvorlige. Det er som å tune en racerbilen små optimaliseringer kan gjøre en enorm forskjell i hvordan alt fungerer.
Når vi er ferdige, vil du ha en polert utvidelse og forstå ytelsesprinsippene som skiller gode webapplikasjoner fra de virkelig gode. La oss dykke inn i nettleseroptimaliseringens verden.
Når vi er ferdige, vil du ha en polert utvidelse og forstå ytelsesprinsippene som skiller gode nettapper fra de flotte. La oss dykke ned i nettleseroptimaliseringens verden.
## Quiz før leksjonen
## Forhåndsforelesnings-Quiz
[Quiz før leksjonen](https://ff-quizzes.netlify.app/web/quiz/27)
[Forhåndsforelesnings-quiz](https://ff-quizzes.netlify.app/web/quiz/27)
### Introduksjon
I våre tidligere leksjoner har du laget et skjema, koblet det til en API og taklet asynkron datahenting. Utvidelsen din begynner å ta form.
Nå må vi legge til de siste detaljene - som å få ikonet til utvidelsen til å endre farger basert på karbondataene. Dette minner meg om hvordan NASA måtte optimalisere hvert system på Apollo-romfartøyet. De kunne ikke tillate noen bortkastede sykluser eller minne fordi liv avhang av ytelsen. Selv om nettleserutvidelsen vår ikke er fullt så kritisk, gjelder de samme prinsippene - effektiv kode skaper bedre brukeropplevelser.
## Grunnleggende om webytelse
Når koden din kjører effektivt, kan folk faktisk *føle* forskjellen. Du vet det øyeblikket når en side lastes umiddelbart eller en animasjon flyter jevnt? Det er god ytelse i arbeid.
Ytelse handler ikke bare om hastighet - det handler om å skape webopplevelser som føles naturlige i stedet for klønete og frustrerende. Tilbake i datamaskinens tidlige dager hadde Grace Hopper berømt en nanosekund (et stykke ledning omtrent en fot lang) på skrivebordet sitt for å vise hvor langt lyset reiser på en milliarddel av et sekund. Det var hennes måte å forklare hvorfor hver mikrosekund betyr noe i databehandling. La oss utforske detektivverktøyene som hjelper deg med å finne ut hva som bremser ting.
> "Nettstedsytelse handler om to ting: hvor raskt siden lastes, og hvor raskt koden på den kjører." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
Temaet om hvordan du gjør nettstedene dine lynraske på alle slags enheter, for alle slags brukere, i alle slags situasjoner, er ikke overraskende omfattende. Her er noen punkter å huske på når du bygger enten et standard webprosjekt eller en nettleserutvidelse.
Det første steget i å optimalisere nettstedet ditt er å forstå hva som faktisk skjer under panseret. Heldigvis kommer nettleseren din med kraftige detektivverktøy innebygd.
For å åpne Developer Tools i Edge, klikk på de tre prikkene øverst til høyre, gå deretter til Flere verktøy > Utviklerverktøy. Eller bruk hurtigtasten: `Ctrl` + `Shift` + `I` på Windows eller `Option` + `Command` + `I` på Mac. Når du er der, klikker du på Ytelse-fanen - det er her du skal gjøre undersøkelsene dine.
**Her er ditt ytelsesdetektivverktøy:**
- **Åpne** Developer Tools (du vil bruke disse konstant som utvikler!)
- **Gå til** Ytelse-fanen - tenk på det som din webapps treningssporer
- **Trykk** på opptaksknappen og se siden din i aksjon
- **Studer** resultatene for å finne ut hva som bremser ting
La oss prøve dette. Åpne et nettsted (Microsoft.com fungerer godt for dette) og klikk på 'Opptak'-knappen. Oppdater siden og se hvordan profileren fanger alt som skjer. Når du stopper opptaket, vil du se en detaljert oversikt over hvordan nettleseren 'skriver', 'renderer' og 'maler' siden. Det minner meg om hvordan kontrollsenteret overvåker hvert system under en rakettoppskyting - du får sanntidsdata om nøyaktig hva som skjer og når.
✅ [Microsoft-dokumentasjonen](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) har massevis av detaljer hvis du vil dykke dypere.
> Proff-tips: Tøm nettleserens cache før testing for å se hvordan nettstedet ditt presterer for førstegangsbesøkende - det er vanligvis ganske annerledes enn ved gjentatte besøk!
Velg elementer i profilens tidslinje for å zoome inn på hendelser som skjer mens siden din lastes.
Få et øyeblikksbilde av sidens ytelse ved å velge en del av profilens tidslinje og se på oppsummeringspanelet:
✅ Bli kjent med profileren din! Åpne utviklerverktøyene på dette nettstedet og se om det er noen flaskehalser. Hva er den tregest lastende ressursen? Den raskeste?
I våre tidligere leksjoner har du laget et skjema, koblet det til en API, og håndtert asynkron datahenting. Utvidelsen din tar form på en fin måte.
Nå trenger vi å legge de siste detaljene som å få ikonet til utvidelsen til å endre farge basert på karbondata. Dette minner meg om hvordan NASA måtte optimalisere hvert system på Apollo-romfartøyet. De hadde ikke råd til noen bortkastede sykluser eller minne fordi liv var avhengig av ytelsen. Selv om vår nettleserutvidelse ikke er like kritisk, gjelder de samme prinsippene effektiv kode gir bedre brukeropplevelser.
```mermaid
mindmap
root((Ytelse og bakgrunnsoppgaver))
Browser Performance
Rendering Pipeline
Asset Optimization
DOM Manipulation
JavaScript Execution
Profiling Tools
Developer Tools
Performance Tab
Timeline Analysis
Bottleneck Detection
Extension Architecture
Background Scripts
Content Scripts
Message Passing
Icon Management
Optimization Strategies
Code Splitting
Lazy Loading
Caching
Resource Compression
Visual Feedback
Dynamic Icons
Color Coding
Real-time Updates
User Experience
```
## Grunnleggende om Nettleserytelse
Når koden din kjører effektivt, kan folk faktisk *føle* forskjellen. Du vet det øyeblikket når en side laster umiddelbart eller en animasjon flyter jevnt? Det er god ytelse på jobb.
Ytelse handler ikke bare om hastighet det handler om å lage nettopplevelser som føles naturlige i stedet for klønete og frustrerende. Tidlig i databehandlingens dager hadde Grace Hopper berømt en nanosekund (et stykke ledning som var omtrent en fot langt) på skrivebordet for å vise hvor langt lys reiser i en milliarddel av et sekund. Det var hennes måte å forklare hvorfor hvert mikrosekund teller i databehandling. La oss utforske detektivverktøyene som hjelper deg å finne ut hva som sinker ting.
> "Nettstedets ytelse handler om to ting: hvor raskt siden lastes, og hvor raskt koden på den kjører." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
Temaet om hvordan du får nettsidene dine lynraske på alle slags enheter, for alle slags brukere, i alle slags situasjoner, er selvsagt omfattende. Her er noen punkter å ha i bakhodet når du bygger enten et standard nettoprojekt eller en nettleserutvidelse.
Det første steget i å optimalisere nettstedet ditt er å forstå hva som faktisk skjer under panseret. Heldigvis har nettleseren din kraftige detektivverktøy innebygd.
```mermaid
flowchart LR
A[HTML] --> B[Tolk]
B --> C[DOM-tre]
D[CSS] --> E[Tolk]
E --> F[CSSOM]
G[JavaScript] --> H[Utfør]
C --> I[Rendererings-tre]
F --> I
H --> I
I --> J[Oppsett]
J --> K[Maling]
K --> L[Sammensetning]
L --> M[Visning]
subgraph "Kritisk rendereringsvei"
N["1. Tolk HTML"]
O["2. Tolk CSS"]
P["3. Utfør JS"]
Q["4. Bygg rendererings-tre"]
R["5. Oppsett elementer"]
S["6. Mal piksler"]
T["7. Sett sammen lag"]
end
style M fill:#e8f5e8
style I fill:#fff3e0
style H fill:#ffebee
```
For å åpne Utviklerverktøy i Edge, klikk på de tre prikkene øverst til høyre, gå deretter til Flere verktøy > Utviklerverktøy. Eller bruk hurtigtasten: `Ctrl` + `Shift` + `I` på Windows eller `Option` + `Command` + `I` på Mac. Når du er der, klikker du på Ytelsestabben her skal du gjøre undersøkelsen din.
**Her er din detektivverktøykasse for ytelse:**
- **Åpne** Utviklerverktøy (du kommer til å bruke disse konstant som utvikler!)
- **Gå** til Ytelsestabben tenk på det som nettappens aktivitetsmåler
- **Trykk** på Spill inn-knappen og se siden i aksjon
- **Studer** resultatene for å oppdage hva som sinker ting
La oss prøve dette. Åpne et nettsted (Microsoft.com fungerer bra for dette) og trykk på 'Spill inn'-knappen. Last deretter siden på nytt og se profilereren fange alt som skjer. Når du stopper opptaket, vil du se en detaljert oversikt over hvordan nettleseren 'skriver skript', 'renderer' og 'maler' siden. Det minner meg om hvordan oppdragskontrollen overvåker hvert system under en rakettoppskyting du får sanntidsdata på eksakt hva som skjer og når.
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01c.no.png)
✅ [Microsoft-dokumentasjonen](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) har mange flere detaljer hvis du vil dykke dypere.
> Proftips: Tøm nettleserens hurtigbuffer før du tester for å se hvordan siden din oppfører seg for førstegangsbesøkende det er vanligvis ganske annerledes enn ved gjentatte besøk!
Velg elementer på profiltidslinjen for å zoome inn på hendelser som skjer mens siden laster.
Få et øyeblikksbilde av sidens ytelse ved å velge deler av tidslinjen og se på oppsummeringspanelet:
![Edge snapshot](../../../../translated_images/snapshot.97750180ebcad737.no.png)
Sjekk hendelsesloggen for å se om noen hendelser tok lengre tid enn 15 ms:
![Edge event log](../../../../translated_images/log.804026979f3707e0.no.png)
✅ Bli kjent med profilereren din! Åpne utviklerverktøyene på dette nettstedet og se om det finnes noen flaskehalser. Hva er den tregest lastende ressursen? Den raskeste?
```mermaid
flowchart TD
A[Åpne DevTools] --> B[Naviger til Ytelsesfane]
B --> C[Klikk på opptaksknapp]
C --> D[Utfør handlinger]
D --> E[Stopp opptak]
E --> F{Analyser resultater}
F --> G[Sjekk tidslinje]
F --> H[Se gjennom nettverk]
F --> I[Undersøk skript]
F --> J[Identifiser malehendelser]
G --> K{Lange oppgaver?}
H --> L{Store ressurser?}
I --> M{Rendreblokkering?}
J --> N{Kostbare malinger?}
K -->|Ja| O[Optimaliser JavaScript]
L -->|Ja| P[Komprimer ressurser]
M -->|Ja| Q[Legg til Async/Defer]
N -->|Ja| R[Forenkle stiler]
O --> S[Test igjen]
P --> S
Q --> S
R --> S
style A fill:#e1f5fe
style F fill:#fff3e0
style S fill:#e8f5e8
```
## Hva du bør se etter når du profilerer
Å kjøre profileren er bare begynnelsen - den virkelige ferdigheten er å vite hva de fargerike diagrammene faktisk forteller deg. Ikke bekymre deg, du vil lære å lese dem. Erfarne utviklere har lært å oppdage faresignalene før de blir fullverdige problemer.
Å kjøre profilereren er bare begynnelsen den virkelige ferdigheten ligger i å vite hva de fargerike grafene faktisk forteller deg. Ikke bekymre deg, du vil lære deg å lese dem. Erfarne utviklere har lært å oppdage varselsignaler før de utvikler seg til fullverdige problemer.
La oss snakke om de vanlige mistenkte - ytelsesproblemene som har en tendens til å snike seg inn i webprosjekter. Som Marie Curie måtte nøye overvåke strålingsnivåene i laboratoriet sitt, må vi se etter visse mønstre som indikerer problemer som brygger. Å fange disse tidlig vil spare deg (og brukerne dine) for mye frustrasjon.
La oss snakke om vanlige syndere ytelsesproblemene som ofte sniker seg inn i nettprosjekter. Som Marie Curie måtte overvåke strålingsnivåer nøye i laboratoriet sitt, må vi følge med på visse mønstre som indikerer trøbbel på vei. Å fange disse tidlig sparer deg (og brukerne dine) mye frustrasjon.
**Ressursstørrelser**: Nettsteder har blitt "tyngre" gjennom årene, og mye av den ekstra vekten kommer fra bilder. Det er som om vi har stappet mer og mer inn i våre digitale kofferter.
**Ressursstørrelser**: Nettsteder har blitt "tyngre" over årene, og mye av denne ekstra vekten kommer fra bilder. Det er som om vi har pakket mer og mer i våre digitale kofferter.
✅ Sjekk ut [Internet Archive](https://httparchive.org/reports/page-weight) for å se hvordan sidestørrelser har vokst over tid - det er ganske avslørende.
✅ Sjekk ut [Internet Archive](https://httparchive.org/reports/page-weight) for å se hvordan sidestørrelser har vokst over tid det er ganske avslørende.
**Slik holder du ressursene dine optimalisert:**
- **Komprimer** bildene! Moderne formater som WebP kan redusere filstørrelser dramatisk
- **Server** riktig bildestørrelse for hver enhet - det er ikke nødvendig å sende store skrivebordsbilder til telefoner
- **Minimer** CSS og JavaScript - hver byte teller
- **Bruk** lazy loading slik at bilder bare lastes ned når brukerne faktisk ruller til dem
- **Server** riktig bildestørrelse for hver enhet ingen grunn til å sende enorme desktop-bilder til telefoner
- **Minifiser** CSS og JavaScript hvert byte teller
- **Bruk** lazy loading slik at bilder bare lastes når brukeren faktisk blar til dem
**DOM-traverseringer**: Nettleseren må bygge sitt Document Object Model basert på koden du skriver, så det er i interesse for god sideytelse å holde taggene minimale, og bare bruke og style det siden trenger. For eksempel kan overflødig CSS assosiert med en side optimaliseres; stiler som bare trenger å brukes på én side, trenger ikke å inkluderes i hovedstilarket.
**DOM-gjennomganger**: Nettleseren må bygge sin Document Object Model basert på koden du skriver, så for god sidens ytelse lønner det seg å holde taggene minimale og bare bruke og style det siden trenger. I denne sammenheng kan overflødig CSS knyttet til en side optimaliseres; stiler som kun skal brukes på én side, trenger for eksempel ikke å inkluderes i hovedstilarket.
**Nøkkelstrategier for DOM-optimalisering:**
- **Minimerer** antall HTML-elementer og nivåer av nesting
- **Fjerner** ubrukte CSS-regler og konsoliderer stilark effektivt
- **Organiserer** CSS for å laste bare det som trengs for hver side
- **Strukturerer** HTML semantisk for bedre nettleserparsing
- **Minimerer** antall HTML-elementer og nestingsnivåer
- **Fjerner** ubrukt CSS og samler stilark effektivt
- **Organiserer** CSS slik at bare nødvendig lastes for hver side
- **Strukturerer** HTML semantisk for bedre nettlesertolkning
**JavaScript**: Hver JavaScript-utvikler bør passe på 'render-blocking'-skript som må lastes før resten av DOM kan traverseres og males til nettleseren. Vurder å bruke `defer` med dine inline-skript (som gjort i Terrarium-modulen).
**JavaScript**: Alle JavaScript-utviklere bør se opp for 'render-blocking'-skript som må lastes før resten av DOM kan gjennomgås og gjengis i nettleseren. Vurder å bruke `defer` med inline-skriptene dine (som i Terrarium-modulen).
**Moderne JavaScript-optimaliseringsteknikker:**
- **Bruker** `defer`-attributtet for å laste skript etter DOM-parsing
- **Implementerer** kode-splitting for å laste bare nødvendig JavaScript
- **Bruker** lazy loading for ikke-kritisk funksjonalitet
- **Minimerer** bruken av tunge biblioteker og rammeverk når mulig
- **Bruker** `defer`-attributtet for å laste skripter etter DOM-parsing
- **Implementerer** kodedeling for å laste kun nødvendig JavaScript
- **Benytter** lazy loading for ikke-kritisk funksjonalitet
- **Minimerer** bruken av tunge biblioteker og rammeverk når det er mulig
✅ Prøv noen nettsteder på en [Site Speed Test-nettside](https://www.webpagetest.org/) for å lære mer om de vanlige kontrollene som gjøres for å bestemme nettstedets ytelse.
✅ Prøv noen nettsteder på en [Test for nettstedshastighet](https://www.webpagetest.org/) for å lære mer om vanlige sjekker som gjøres for å fastslå nettstedsytelse.
Nå som du har en idé om hvordan nettleseren renderer ressursene du sender til den, la oss se på de siste tingene du trenger å gjøre for å fullføre utvidelsen din:
### 🔄 **Pedagogisk Sjekk-inn**
**Ytelsesforståelse**: Før du bygger funksjoner i utvidelsen, sørg for at du kan:
- ✅ Forklare den kritiske rendering-stien fra HTML til piksler
- ✅ Identifisere vanlige ytelsesflaskehalser i nettapplikasjoner
- ✅ Bruke nettleserens utviklerverktøy for å profilere sidens ytelse
- ✅ Forstå hvordan ressursstørrelse og DOM-kompleksitet påvirker hastighet
### Lag en funksjon for å beregne farge
**Rask Selvtest**: Hva skjer når du har render-blocking JavaScript?
*Svar: Nettleseren må laste ned og kjøre skriptet før den kan fortsette å analysere HTML og gjengi siden*
Nå skal vi lage en funksjon som gjør numeriske data om til meningsfulle farger. Tenk på det som et trafikklyssystem - grønt for ren energi, rødt for høy karbonintensitet.
**Reell verdens ytelseseffekt**:
- **100 ms forsinkelse**: Brukere merker tregheten
- **1 sekunds forsinkelse**: Brukere begynner å miste fokus
- **3+ sekunder**: 40 % av brukerne forlater siden
- **Mobilt nettverk**: Ytelse er enda viktigere
Denne funksjonen vil ta CO2-dataene fra vår API og bestemme hvilken farge som best representerer miljøpåvirkningen. Det ligner på hvordan forskere bruker fargekoding i varmekart for å visualisere komplekse dataprofiler - fra havtemperaturer til stjernedannelse. La oss legge dette til `/src/index.js`, rett etter de `const`-variablene vi satte opp tidligere:
Nå som du har en idé om hvordan nettleseren renderer ressursene du sender til den, la oss se på de siste tingene du må gjøre for å fullføre utvidelsen din:
### Lag en funksjon for å beregne farge
Nå skal vi lage en funksjon som gjør numeriske data om til meningsfulle farger. Tenk på det som et trafikksignalsystem grønt for ren energi, rødt for høy karbonintensitet.
Denne funksjonen tar CO2-data fra APIen vår og bestemmer hvilken farge som best representerer miljøpåvirkningen. Det er likt hvordan vitenskapsfolk bruker fargekoding i varmekart for å visualisere komplekse datapattern fra havtemperaturer til stjernedannelse. La oss legge dette til i `/src/index.js`, rett etter de `const`-variablene vi definerte tidligere:
```mermaid
flowchart LR
A[CO2 Verdi] --> B[Finn Nærmeste Skala Punkt]
B --> C[Hent Skala Indeks]
C --> D[Kartlegg til Farge]
D --> E[Send til Bakgrunn]
subgraph "Fargeskala"
F["0-150: Grønn (Ren)"]
G["150-600: Gul (Moderat)"]
H["600-750: Oransje (Høy)"]
I["750+: Brun (Veldig Høy)"]
end
subgraph "Meldingsformidling"
J[Innholdsskript]
K[chrome.runtime.sendMessage]
L[Bakgrunnsskript]
M[Oppdater Ikon]
end
style A fill:#e1f5fe
style D fill:#e8f5e8
style E fill:#fff3e0
```
```javascript
function calculateColor(value) {
// Define CO2 intensity scale (grams per kWh)
// Definer CO2-intensitetsskala (gram per kWh)
const co2Scale = [0, 150, 600, 750, 800];
// Corresponding colors from green (clean) to dark brown (high carbon)
// Tilsvarende farger fra grønn (ren) til mørk brun (høyt karbon)
const colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02'];
// Find the closest scale value to our input
// Finn nærmeste skala-verdi til vår input
const closestNum = co2Scale.sort((a, b) => {
return Math.abs(a - value) - Math.abs(b - value);
})[0];
console.log(`${value} is closest to ${closestNum}`);
// Find the index for color mapping
// Finn indeksen for fargekartlegging
const num = (element) => element > closestNum;
const scaleIndex = co2Scale.findIndex(num);
const closestColor = colors[scaleIndex];
console.log(scaleIndex, closestColor);
// Send color update message to background script
// Send fargeoppdateringsmelding til bakgrunnsskript
chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: closestColor } });
}
```
**La oss bryte ned denne smarte lille funksjonen:**
- **Setter opp** to arrays - en for CO2-nivåer, en annen for farger (grønn = ren, brun = skitten!)
- **Finner** den nærmeste matchen til vår faktiske CO2-verdi ved hjelp av noen smarte array-sorteringer
- **Henter** den matchende fargen ved hjelp av findIndex()-metoden
- **Sender** en melding til Chromes bakgrunnsskript med vår valgte farge
- **Bruker** malstrenger (de backticks) for renere strengformatering
**La oss bryte ned denne smarte lille funksjonen:**
- **Setter opp** to arrayer - en for CO2-nivåer, en annen for farger (grønn = ren, brun = skitten!)
- **Finner** nærmeste match til vår faktiske CO2-verdi ved hjelp av smart array-sortering
- **Henter** den matchende fargen ved å bruke findIndex()-metoden
- **Sender** en melding til Chromes bakgrunnsskript med den valgte fargen
- **Bruker** template literals (de backtick-tegnene) for ryddigere strengformatering
- **Holder** alt organisert med const-deklarasjoner
`chrome.runtime` [API](https://developer.chrome.com/extensions/runtime) er som nervesystemet til utvidelsen din - det håndterer all kommunikasjon og oppgaver bak kulissene:
> "Bruk chrome.runtime API for å hente bakgrunnssiden, returnere detaljer om manifestet, og lytte til og svare på hendelser i appen eller utvidelsens livssyklus. Du kan også bruke denne API-en for å konvertere relative URL-stier til fullt kvalifiserte URL-er."
**Hvorfor Chrome Runtime API er så nyttig:**
- **Lar** forskjellige deler av utvidelsen din snakke med hverandre
- **Håndterer** bakgrunnsarbeid uten å fryse brukergrensesnittet
- **Administrerer** utvidelsens livssyklus-hendelser
- **Gjør** meldingsutveksling mellom skript superenkelt
✅ Hvis du utvikler denne nettleserutvidelsen for Edge, kan det overraske deg at du bruker en Chrome API. De nyere Edge-nettleserversjonene kjører på Chromium-nettlesermotoren, så du kan dra nytte av disse verktøyene.
> **Proff-tips**: Hvis du vil profilere en nettleserutvidelse, åpne utviklerverktøyene fra selve utvidelsen, da den er sin egen separate nettleserinstans. Dette gir deg tilgang til utvidelsesspesifikke ytelsesmetrikker.
`chrome.runtime` [API](https://developer.chrome.com/extensions/runtime) er som nervessystemet til utvidelsen din det håndterer all kommunikasjon og oppgaver bak kulissene:
> "Bruk chrome.runtime API for å hente bakgrunnssiden, returnere detaljer om manifest, og lytte til og svare på hendelser i appens eller utvidelsens livssyklus. Du kan også bruke dette API til å konvertere relative URL-stier til fullstendige URLer."
**Hvorfor Chrome Runtime API er så nyttig:**
- **Lar** forskjellige deler av utvidelsen snakke med hverandre
- **Håndterer** bakgrunnsarbeid uten å fryse brukergrensesnittet
- **Administrerer** livssyklus-hendelser i utvidelsen
- **Gjør** meldingsoverføring mellom skript superenkelt
✅ Hvis du utvikler denne nettleserutvidelsen for Edge, kan det overraske deg at du bruker en chrome API. De nyere Edge-nettleserversjonene kjører på Chromium-nettlesermotoren, så du kan benytte disse verktøyene.
```mermaid
architecture-beta
group browser(logos:chrome)[Nettleser]
service popup(logos:html5)[Popup UI] in browser
service content(logos:javascript)[Innholdsskript] in browser
service background(database)[Bakgrunnsskript] in browser
service api(logos:api)[Ekstern API] in browser
popup:R -- L:content
content:R -- L:background
background:T -- B:api
content:T -- B:api
junction junctionCenter in browser
popup:R -- L:junctionCenter
junctionCenter:R -- L:background
```
> **Proftips**: Hvis du vil profilere en nettleserutvidelse, start utviklerverktøyene fra selve utvidelsen, siden det er en egen egen nettleserinstans. Dette gir deg tilgang til ytelsesmetrikker spesifikke for utvidelsen.
### Sett en standard ikonfarge
Før vi begynner å hente ekte data, la oss gi utvidelsen vår et utgangspunkt. Ingen liker å stirre på et tomt eller ødelagt ikon. Vi starter med en grønn farge slik at brukerne vet at utvidelsen fungerer fra det øyeblikket de installerer den.
Før vi begynner å hente ekte data, la oss gi utvidelsen et utgangspunkt. Ingen liker å se på et tomt eller ødelagt ikon. Vi starter med en grønn farge slik at brukerne vet utvidelsen virker fra det øyeblikket de installerer den.
I din `init()`-funksjon, la oss sette opp det standard grønne ikonet:
I `init()`-funksjonen din setter vi opp det grønne standardikonet:
```javascript
chrome.runtime.sendMessage({
@ -162,104 +337,253 @@ chrome.runtime.sendMessage({
});
```
**Hva denne initialiseringen oppnår:**
- **Setter** en nøytral grønn farge som standardtilstand
- **Gir** umiddelbar visuell tilbakemelding når utvidelsen lastes
- **Etablerer** kommunikasjonsmønsteret med bakgrunnsskriptet
- **Sikrer** at brukerne ser en funksjonell utvidelse før data lastes
**Dette oppsettet oppnår:**
- **Setter** en nøytral grønn farge som standardtilstand
- **Gir** umiddelbar visuell tilbakemelding når utvidelsen lastes
- **Etablerer** kommunikasjonsmønsteret med bakgrunnsskriptet
- **Sikrer** at brukerne ser en fungerende utvidelse før data hentes
### Kall funksjonen, utfør kallet
### Kall funksjonen, utfør kall
Nå skal vi koble alt sammen slik at når ferske CO2-data kommer inn, oppdateres ikonet ditt automatisk med riktig farge. Det er som å koble den siste kretsen i en elektronisk enhet - plutselig fungerer alle de individuelle komponentene som ett system.
Nå skal vi koble alt sammen slik at når ferske CO2-data kommer inn, oppdateres ikonet automatisk med riktig farge. Det er som å koble den siste kretsen i en elektronisk enhet plutselig fungerer alle delene som ett system.
Legg til denne linjen rett etter at du får CO2-dataene fra API-en:
Legg til denne linjen rett etter du har hentet CO2-dataene fra APIen:
```javascript
// After retrieving CO2 data from the API
// let CO2 = data.data[0].intensity.actual;
// Etter å ha hentet CO2-data fra API-en
// la CO2 = data.data[0].intensity.actual;
calculateColor(CO2);
```
**Denne integrasjonen oppnår:**
- **Kobler** API-datastrømmen med det visuelle indikator-systemet
- **Trigger** ikonoppdateringer automatisk når nye data ankommer
- **Sikrer** sanntids visuell tilbakemelding basert på nåværende karbonintensitet
- **Opprettholder** separasjonen mellom datahenting og visningslogikk
**Denne integrasjonen oppnår:**
- **Kobler** API-datatilførselen med det visuelle indikatorystemet
- **Trigger** ikonoppdateringer automatisk når nye data kommer
- **Sikrer** sanntids visuell tilbakemelding basert på nåværende karbonintensitet
- **Opprettholder** separasjonen mellom datainnhenting og visningslogikk
Og til slutt, i `/dist/background.js`, legg til lytteren for disse bakgrunnsaksjonskallene:
```javascript
// Listen for messages from the content script
// Lytt etter meldinger fra innholdsskriptet
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.action === 'updateIcon') {
chrome.action.setIcon({ imageData: drawIcon(msg.value) });
}
});
// Draw dynamic icon using Canvas API
// Borrowed from energy lollipop extension - nice feature!
// Tegn dynamisk ikon ved bruk av Canvas API
// Lånt fra energy lollipop-utvidelsen - fint trekk!
function drawIcon(value) {
// Create an offscreen canvas for better performance
// Lag et offscreen-canvas for bedre ytelse
const canvas = new OffscreenCanvas(200, 200);
const context = canvas.getContext('2d');
// Draw a colored circle representing carbon intensity
// Tegn en farget sirkel som representerer karbonintensitet
context.beginPath();
context.fillStyle = value.color;
context.arc(100, 100, 50, 0, 2 * Math.PI);
context.fill();
// Return the image data for the browser icon
// Returner billeddataene for nettleserikonet
return context.getImageData(50, 50, 100, 100);
}
```
**Hva dette bakgrunnsskriptet gjør:**
- **Lytter** etter meldinger fra hovedskriptet ditt (som en resepsjonist som tar imot samtaler)
- **Behandler** disse 'updateIcon'-forespørslene for å endre verktøylinjeikonet ditt
- **Oppretter** nye ikoner på farten ved hjelp av Canvas API
- **Tegner** en enkel farget sirkel som viser nåværende karbonintensitet
- **Oppdaterer** nettleserens verktøylinje med det ferske ikonet
- **Bruker** OffscreenCanvas for jevn ytelse (ingen UI-blokkering)
**Dette bakgrunnsskriptet gjør følgende:**
- **Lytter** etter meldinger fra hovedskriptet ditt (som en resepsjonist som tar imot anrop)
- **Behandler** disse 'updateIcon'-forespørslene for å endre ikon i verktøylinjen
- **Lager** nye ikoner på sparket ved hjelp av Canvas API
- **Tegner** en enkel farget sirkel som viser gjeldende karbonintensitet
- **Oppdaterer** nettleserens verktøylinje med det nye ikonet
- **Bruker** OffscreenCanvas for jevn ytelse (unngår UI-blokkering)
✅ Du vil lære mer om Canvas API i [Space Game-leksjonene](../../6-space-game/2-drawing-to-canvas/README.md).
```mermaid
sequenceDiagram
participant CS as Innholdsskript
participant BG as Bakgrunnsskript
participant Canvas as OffscreenCanvas
participant Browser as Nettleserikon
CS->>BG: sendMessage({action: 'updateIcon', color})
BG->>Canvas: new OffscreenCanvas(200, 200)
Canvas->>Canvas: getContext('2d')
Canvas->>Canvas: beginPath() + fillStyle + arc()
Canvas->>Canvas: fill() + getImageData()
Canvas->>BG: Returner bilde-data
BG->>Browser: chrome.action.setIcon(imageData)
Browser->>Browser: Oppdater verktøylinjeikon
```
### 🔄 **Pedagogisk Sjekk-inn**
**Full Forståelse av Utvidelsen**: Verifiser at du mestrer hele systemet:
- ✅ Hvordan fungerer meldingsoverføring mellom forskjellige utvidelsesskript?
- ✅ Hvorfor bruker vi OffscreenCanvas i stedet for vanlig Canvas for ytelse?
- ✅ Hvilken rolle spiller Chrome Runtime API i utvidelsesarkitekturen?
- ✅ Hvordan kartlegger fargeberegningsalgoritmen data til visuell tilbakemelding?
**Ytelsesbetraktninger**: Utvidelsen din demonstrerer nå:
- **Effektiv meldingshåndtering**: Ryddig kommunikasjon mellom skriptkontekster
- **Optimalisert gjengivelse**: OffscreenCanvas forhindrer blokkering av brukergrensesnittet
- **Sanntidsoppdateringer**: Dynamiske ikonendringer basert på live data
- **Minnehåndtering**: Korrekt opprydding og ressursbehandling
**Tid for å teste utvidelsen din:**
- **Bygg** alt med `npm run build`
- **Last** utvidelsen din på nytt i nettleseren (ikke glem dette steget)
- **Åpne** utvidelsen din og se ikonet endre farger
- **Sjekk** hvordan det reagerer på ekte karbondata fra hele verden
- **Last inn utvidelsen på nytt i nettleseren** (ikke glem dette trinnet)
- **Åpne** utvidelsen din og se at ikonet endrer farger
- **Sjekk** hvordan den reagerer på ekte karbondata fra hele verden
Nå vil du vite med et blikk om det er et godt tidspunkt for den klesvasken eller om du bør vente på renere energi. Du har nettopp bygget noe genuint nyttig og lært om nettleserytelse underveis.
Nå vil du på et øyeblikk vite om det er et godt tidspunkt å kjøre den vaskemaskinen eller om du bør vente på renere energi. Du har nettopp bygget noe virkelig nyttig og lært om nettleserens ytelse underveis.
## GitHub Copilot Agent-utfordring 🚀
## GitHub Copilot Agent Challenge 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
Bruk Agent-modus til å fullføre følgende utfordring:
**Beskrivelse:** Forbedre nettleserutvidelsens ytelsesovervåkingskapabiliteter ved å legge til en funksjon som sporer og viser lastetider for forskjellige komponenter i utvidelsen.
**Beskrivelse:** Forbedre nettleserutvidelsens ytelsesovervåkingsmuligheter ved å legge til en funksjon som sporer og viser lastetider for forskjellige komponenter i utvidelsen.
**Prompt:** Lag et ytelsesovervåkingssystem for nettleserutvidelsen som måler og logger tiden det tar å hente CO2-data fra API-en, beregne farger og oppdatere ikonet. Legg til en funksjon kalt `performanceTracker` som bruker Performance API for å måle disse operasjonene og viser resultatene i nettleserkonsollen med tidsstempler og varighetsmetrikker.
**Oppgave:** Lag et ytelsesovervåkingssystem for nettleserutvidelsen som måler og logger tiden det tar å hente CO2-data fra API-et, beregne farger og oppdatere ikonet. Legg til en funksjon kalt `performanceTracker` som bruker Performance API for å måle disse operasjonene og viser resultatene i nettleserkonsollen med tidsstempler og varighetsmålinger.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
Lær mer om [agent-mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
Her er et interessant detektivoppdrag: velg noen åpne kildekode-nettsteder som har eksistert i flere år (tenk Wikipedia, GitHub eller Stack Overflow) og dykk ned i deres commit-historikk. Kan du finne ut hvor de har gjort ytelsesforbedringer? Hvilke problemer dukker stadig opp?
**Din undersøkelsesmetode:**
- **Søk** i commit-meldinger etter ord som "optimalisere," "ytelse," eller "raskere"
- **Se** etter mønstre - fikser de stadig de samme typene problemer?
- **Identifiser** de vanlige årsakene til at nettsteder blir tregere
- **Del** det du oppdager - andre utviklere kan lære av eksempler fra virkeligheten
## Quiz etter forelesning
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/28)
Her er en spennende detektivoppgave: Velg noen få åpne kilder-nettsteder som har eksistert i mange år (tenk Wikipedia, GitHub eller Stack Overflow) og gransk deres commit-historikk. Kan du se hvor de gjorde ytelsesforbedringer? Hvilke problemer dukket stadig opp?
## Gjennomgang og selvstudium
Vurder å melde deg på et [nyhetsbrev om ytelse](https://perf.email/)
Undersøk noen av måtene nettlesere måler webytelse ved å se gjennom ytelsesfanene i deres webverktøy. Finner du noen store forskjeller?
**Din undersøkelsesmetode:**
- **Søk** commit-meldinger etter ord som "optimize", "performance" eller "faster"
- **Se** etter mønstre - reparerer de de samme problemtypene?
- **Identifiser** de vanlige syndebukkene som bremser ned nettsteder
- **Del** hva du oppdager - andre utviklere lærer av ekte eksempler
## Post-forelesningsquiz
[Post-forelesningsquiz](https://ff-quizzes.netlify.app/web/quiz/28)
## Oppsummering & Selvstudium
Vurder å melde deg på et [ytelsesnyhetsbrev](https://perf.email/)
Undersøk noen av måtene nettlesere måler webytelse på ved å se gjennom ytelsesfanene i deres nettverktøy. Finnes det store forskjeller?
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Åpne nettleserens Oppgavebehandling (Shift+Esc i Chrome) for å se ressursbruk for utvidelser
- [ ] Bruk DevTools Ytelses-fanen for å ta opp og analysere nettsideytelse
- [ ] Sjekk nettleserens Utvidelsesside for å se hvilke utvidelser som påvirker oppstartstid
- [ ] Prøv å deaktivere utvidelser midlertidig for å se ytelsesforskjeller
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør post-lesson-quiz og forstå ytelseskonsepter
- [ ] Implementer et bakgrunnsskript for nettleserutvidelsen din
- [ ] Lær å bruke browser.alarms for effektive bakgrunnsoppgaver
- [ ] Øv på meldingsutveksling mellom innholdsskript og bakgrunnsskript
- [ ] Mål og optimaliser utvidelsens ressursbruk
### 📅 **Din ukelange ytelsesreise**
- [ ] Utvikle en høyytelses nettleserutvidelse med bakgrunnsfunksjonalitet
- [ ] Mestre service workers og moderne utvidelsesarkitektur
- [ ] Implementer effektive datasynkronisering- og bufferstrategier
- [ ] Lær avanserte feilsøkingsteknikker for ytelse i utvidelser
- [ ] Optimaliser utvidelsen for både funksjonalitet og ressurseffektivitet
- [ ] Lag omfattende tester for ytelsesscenarier i utvidelsen
### 🌟 **Din månedslange optimaliseringsmestring**
- [ ] Bygg bedriftsnivå nettleserutvidelser med optimal ytelse
- [ ] Lær om Web Workers, Service Workers og moderne webytelse
- [ ] Bidra til åpen kilde-prosjekter fokusert på ytelsesoptimalisering
- [ ] Mestre nettleserens interne mekanismer og avansert feilsøking
- [ ] Lag verktøy for ytelsesovervåkning og beste praksis-guider
- [ ] Bli en ytelseseekspert som hjelper med å optimalisere webapplikasjoner
## 🎯 Din tidslinje for studier av nettleserutvidelser
```mermaid
timeline
title Fullstendig Utvidelsesutviklingsprogresjon
section Grunnleggende ytelse (20 minutter)
Nettleserprofilering: DevTools mestring
: Tidslinjeanalyse
: Flaskehalsidentifisering
: Kritisk gjengivelsesbane
section Bakgrunnsoppgaver (25 minutter)
Utvidelsesarkitektur: Meldingsoverføring
: Bakgrunnsskript
: Runtime API-bruk
: Kommunikasjon på tvers av kontekster
section Visuell tilbakemelding (30 minutter)
Dynamisk UI: Fargekalkulasjonsalgoritmer
: Canvas API-integrasjon
: Ikongenerering
: Oppdateringer i sanntid
section Ytelsesoptimalisering (35 minutter)
Effektiv kode: Asynkrone operasjoner
: Minnehåndtering
: Ressursopprydding
: Ytelsesovervåkning
section Produksjonsklar (45 minutter)
Polering og Testing: Tverrleserkompatibilitet
: Feilhåndtering
: Brukeropplevelse
: Ytelsesvalidering
section Avanserte funksjoner (1 uke)
Utvidelsesøkosystem: Chrome Nettbutikk
: Brukertilbakemelding
: Analyseintegrasjon
: Oppdateringshåndtering
section Profesjonell utvikling (2 uker)
Bedriftsutvidelser: Team-samarbeid
: Kodegjennomganger
: CI/CD-pipelines
: Sikkerhetsrevisjoner
section Ekspertmestring (1 måned)
Plattformekspertise: Avanserte Chrome-APIer
: Ytelsesoptimalisering
: Arkitekturmønstre
: Bidrag til åpen kildekode
```
### 🛠️ Ditt komplette verktøykasse for utvidelsesutvikling
Etter å ha fullført denne trilogien har du mestret:
- **Nettleserarkitektur**: Dyp forståelse av hvordan utvidelser integreres med nettlesersystemer
- **Ytelsesprofilering**: Evne til å identifisere og fikse flaskehalser med utviklerverktøy
- **Asynkron programmering**: Moderne JavaScript-mønstre for responsiv, ikke-blokkerende drift
- **API-integrasjon**: Henting av eksterne data med autentisering og feilbehandling
- **Visuell design**: Dynamiske UI-oppdateringer og grafikkgenerering basert på Canvas
- **Meldingsoverføring**: Kommunikasjon mellom skript i utvidelsesarkitekturer
- **Brukeropplevelse**: Lastetilstander, feilhåndtering og intuitive interaksjoner
- **Produksjonsferdigheter**: Testing, feilsøking og optimalisering for ekte distribusjon
**Reelle brukstilfeller:** Ferdighetene dine innen utvidelsesutvikling gjelder direkte for:
- **Progressive Web Apps**: Liknende arkitektur og ytelsesmønstre
- **Electron desktop-apper**: Tverrplattform-applikasjoner med webteknologier
- **Mobile hybrid-apper**: Cordova/PhoneGap-utvikling som bruker web-API-er
- **Bedriftswebapplikasjoner**: Komplekse dashbord og produktivitetsverktøy
- **Chrome DevTools-utvidelser**: Avanserte utviklerverktøy og feilsøking
- **Web API-integrasjon**: Enhver app som kommuniserer med eksterne tjenester
**Profesjonell effekt:** Du kan nå:
- **Bygge** produksjonsklare nettleserutvidelser fra idé til lansering
- **Optimalisere** webapplikasjoners ytelse med bransjestandard profileringsverktøy
- **Arkitektere** skalerbare systemer med riktig bekymringsseparasjon
- **Feilsøke** komplekse asynkrone operasjoner og kommunikasjon på tvers av kontekster
- **Bidra** til åpen kilde-utvidelsesprosjekter og nettleserstandarder
**Muligheter på neste nivå:**
- **Chrome Web Store-utvikler**: Publiser utvidelser til millioner av brukere
- **Web Performance Engineer**: Spesialiser deg på optimalisering og brukeropplevelse
- **Nettleserplattformutvikler**: Bidra til utvikling av nettlesermotorer
- **Utviklerverktøy-skaper**: Lag verktøy som hjelper andre utviklere
- **Utviklerrelasjoner**: Del kunnskap via undervisning og innholdsproduksjon
🌟 **Utmerkelse oppnådd**: Du har bygd en komplett, funksjonell nettleserutvidelse som demonstrerer profesjonell utviklingspraksis og moderne webstandarder!
## Oppgave
@ -267,5 +591,7 @@ Undersøk noen av måtene nettlesere måler webytelse ved å se gjennom ytelsesf
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på dets opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst merk at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på det opprinnelige språket skal anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi påtar oss ikke ansvar for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->

@ -23,7 +23,7 @@ Denne utvidelsen kan kalles ad hoc av en bruker når en API-nøkkel og regionkod
### Krediteringer
![en grønn nettleserutvidelse](../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![en grønn nettleserutvidelse](../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Krediteringer

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Ved å bruke tmrow sin CO2 Signal API for å spore strømforbruk, kan du lage en nettleserutvidelse som gir deg en påminnelse direkte i nettleseren om hvor tungt strømforbruket er i din region. Å bruke denne utvidelsen sporadisk kan hjelpe deg med å ta bedre vurderinger av aktivitetene dine basert på denne informasjonen.
![utvidelse skjermbilde](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![utvidelse skjermbilde](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Komme i gang
@ -31,7 +31,7 @@ npm run build
For å installere på Edge, bruk menyen med 'tre prikker' øverst til høyre i nettleseren for å finne Utvidelser-panelet. Derfra velger du 'Last inn pakket utvidelse' for å laste inn en ny utvidelse. Åpne 'dist'-mappen når du blir bedt om det, og utvidelsen vil lastes inn. For å bruke den, trenger du en API-nøkkel for CO2 Signal API ([få en her via e-post](https://www.co2signal.com/) skriv inn e-posten din i boksen på denne siden) og koden for din region ([finn den her](http://api.electricitymap.org/v3/zones)) som tilsvarer [Electricity Map](https://www.electricitymap.org/map) (for eksempel bruker jeg 'US-NEISO' i Boston).
![installasjon](../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![installasjon](../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når API-nøkkelen og regionen er lagt inn i utvidelsesgrensesnittet, bør den fargede prikken i nettleserens utvidelseslinje endre seg for å gjenspeile energiforbruket i din region og gi deg en pekepinn på hvilke energikrevende aktiviteter som kan være passende å utføre. Konseptet bak dette 'prikk'-systemet ble inspirert av [Energy Lollipop-utvidelsen](https://energylollipop.com/) for utslipp i California.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Ved å bruke CO2 Signal API fra tmrow for å spore strømforbruket, kan du lage en nettleserutvidelse som gir deg en påminnelse direkte i nettleseren om strømforbruket i ditt område. Bruken av denne ad hoc-utvidelsen hjelper deg med å ta beslutninger om aktivitetene dine basert på denne informasjonen.
![utvidelsesskjermbilde](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![utvidelsesskjermbilde](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Kom i gang
@ -31,7 +31,7 @@ npm run build
For å installere på Edge, bruk menyen med 'tre prikker' øverst til høyre i nettleseren for å finne panelet Utvidelser. Derfra velger du 'Last inn ukomprimert utvidelse' for å laste inn en ny utvidelse. Åpne mappen 'dist' når du blir bedt om det, og utvidelsen vil lastes inn. For å bruke den trenger du en API-nøkkel for CO2 Signal API ([få en her via e-post](https://www.co2signal.com/) - skriv inn e-posten din i feltet på denne siden) og [koden for ditt område](http://api.electricitymap.org/v3/zones) som tilsvarer [Elektrisitetskartet](https://www.electricitymap.org/map) (i Boston, for eksempel, bruker jeg 'US-NEISO').
![installasjon](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![installasjon](../../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når API-nøkkelen og regionen er lagt inn i utvidelsens grensesnitt, skal den fargede prikken i nettleserens utvidelseslinje endre seg for å gjenspeile energiforbruket i ditt område og gi deg en indikator på hvilke energikrevende aktiviteter det kan være passende å utføre. Konseptet bak dette 'prikk'-systemet ble inspirert av [utvidelsen Energy Lollipop](https://energylollipop.com/) for utslipp i California.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Ved å bruke tmrow sin CO2 Signal API for å spore strømforbruk, bygger vi en nettleserutvidelse som gir deg en påminnelse om hvor belastet strømforbruket i ditt område er. Ved å bruke denne utvidelsen kan du ta beslutninger om aktivitetene dine basert på denne informasjonen.
![Utvidelse skjermbilde](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![Utvidelse skjermbilde](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Kom i gang
@ -31,7 +31,7 @@ npm run build
For å installere på Edge, bruk 'tre prikker'-menyen øverst til høyre i nettleseren for å finne utvidelsespanelet. Derfra velger du 'Last inn upakket' for å laste inn en ny utvidelse. Åpne 'dist'-mappen ved prompten, og utvidelsen vil bli lastet inn. For å bruke den trenger du en API-nøkkel fra CO2 Signal ([få den via e-post her](https://www.co2snal.com/) - skriv inn e-posten din i boksen på denne siden) og [kode for ditt område](http://api.electricitymap.org/v3/zones) fra [Electricity Map](https://www.electricitymap.org/map) (for eksempel, i Boston bruker jeg 'US-NEISO').
![installering](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![installering](../../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når API-nøkkelen og området er lagt inn i utvidelsesgrensesnittet, bør den fargede prikken i nettleserutvidelseslinjen endre seg for å reflektere energiforbruket i ditt område og gi deg en indikator på hvilke energiintensive aktiviteter som passer for deg. Konseptet bak dette 'prikk'-systemet ble inspirert av [Energy Lollipop Extension](https://energylollipop.com/) for utslipp i California.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Vi skal bruke tmrow sin Signal CO2-API for å overvåke strømforbruket og lage en nettleserutvidelse som gir deg en påminnelse direkte i nettleseren om hvor belastende strømforbruket er i ditt område. Bruken av denne spesialutviklede utvidelsen vil hjelpe deg med å vurdere aktivitetene dine basert på denne informasjonen.
![skjermbilde av utvidelsen](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![skjermbilde av utvidelsen](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Kom i gang
@ -31,7 +31,7 @@ npm run build
For å installere på Edge, bruk "tre prikker"-menyen øverst til høyre i nettleseren for å finne utvidelsespanelet. Hvis det ikke allerede er aktivert, slå på Utviklermodus (nederst til venstre). Velg "Last inn pakket utvidelse" for å laste opp en ny utvidelse. Åpne "dist"-mappen når du blir bedt om det, og utvidelsen vil bli lastet inn. For å bruke den trenger du en API-nøkkel for CO2 Signal-API-en (du kan [få en her via e-post](https://www.co2signal.com/) skriv inn e-posten din i feltet på denne siden) og [koden for din region](http://api.electricitymap.org/v3/zones) som tilsvarer [elektrisitetskartet](https://www.electricitymap.org/map) (for eksempel er koden for Boston "US-NEISO").
![installasjon](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![installasjon](../../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når API-nøkkelen og regionen er lagt inn i utvidelsens grensesnitt, skal den fargede prikken i nettleserens utvidelseslinje endre seg for å gjenspeile energiforbruket i regionen din og gi en indikasjon på hvilke aktiviteter med høyt energiforbruk som kan være passende å utføre. Konseptet bak dette "prikk"-systemet er inspirert av [Energy Lollipop-utvidelsen](https://energylollipop.com/) for utslipp i California.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Bygg en nettleserutvidelse som bruker tmrow sin CO2 Signal API for å spore strømforbruket i ditt område og vise det som en påminnelse i nettleseren. Ved å bruke denne utvidelsen kan du ta beslutninger om aktivitetene dine basert på denne informasjonen.
![utvidelse skjermbilde](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![utvidelse skjermbilde](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Kom i gang
@ -31,7 +31,7 @@ npm run build
For å installere på Edge, finn "Utvidelser"-panelet via "tre prikker"-menyen øverst til høyre i nettleseren. Derfra velger du "Load Unpacked" for å laste inn den nye utvidelsen. Når du blir bedt om det, åpner du "dist"-mappen, og utvidelsen vil bli lastet inn. For å bruke den trenger du en API-nøkkel for CO2 Signal API ([få en her via e-post](https://www.co2signal.com/) - skriv inn e-posten din i boksen på denne siden) og en [kode for ditt område](http://api.electricitymap.org/v3/zones) som er kompatibel med [Electricity Map](https://www.electricitymap.org/map) (for eksempel bruker Boston 'US-NEISO').
![installering](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![installering](../../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når du har lagt inn API-nøkkelen og området i utvidelsesgrensesnittet, vil en farget prikk vises i nettleserens utvidelseslinje. Denne prikken endrer farge for å reflektere energiforbruket i ditt område og gir deg en indikasjon på hvilke aktiviteter som krever energi det er passende å utføre. Konseptet med dette "prikk"-systemet ble inspirert av [Energy Lollipop-utvidelsen](https://energylollipop.com/) for utslipp i California.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Ved å bruke CO2 Signal API fra tmrow for å overvåke strømforbruk, kan du bygge en nettleserutvidelse som gir deg varsler om hvor tungt strømforbruket er i ditt område. Å bruke denne utvidelsen kan hjelpe deg med å ta informerte valg om aktivitetene dine basert på denne informasjonen.
![skjermbilde av nettleserutvidelsen](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![skjermbilde av nettleserutvidelsen](../../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Kom i Gang
@ -31,7 +31,7 @@ npm run build
For å installere i Edge, bruk menyen med 'tre prikker' øverst til høyre i nettleseren for å finne panelet Utvidelser. Derfra velger du 'Load Unpacked' for å laste inn en ny utvidelse. Åpne 'dist'-mappen når du blir bedt om det, og utvidelsen vil bli lastet inn. For å bruke den, trenger du en API-nøkkel for CO2 Signal API ([få en her via e-post](https://www.co2signal.com/) - skriv inn e-posten din i boksen på denne siden) og [koden for ditt område](http://api.electricitymap.org/v3/zones) som samsvarer med [Electricity Map](https://www.electricitymap.org/map) (i Boston, for eksempel, bruker jeg 'US-NEISO').
![laster ned](../../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![laster ned](../../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når API-nøkkelen og området er lagt inn i utvidelsens grensesnitt, vil en farget prikk i nettleserens utvidelseslinje endre seg for å reflektere energiforbruket i ditt område og gi deg anbefalinger om passende aktiviteter basert på dette. Konseptet bak dette 'prikk'-systemet ble inspirert av [Energy Lollipop nettleserutvidelsen](https://energylollipop.com/) for utslipp i California.

@ -11,7 +11,7 @@ CO_OP_TRANSLATOR_METADATA:
Ved å bruke tmrow's CO2 Signal API for å spore strømforbruk, kan du lage en nettleserutvidelse som gir deg en påminnelse direkte i nettleseren om hvor tungt strømforbruket er i din region. Å bruke denne utvidelsen ad hoc vil hjelpe deg med å ta vurderinger om aktivitetene dine basert på denne informasjonen.
![utvidelsesskjermbilde](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3875e1bc9405edd45a3d2e02963e48900adb91926a62a5807.no.png)
![utvidelsesskjermbilde](../../../../translated_images/extension-screenshot.0e7f5bfa110e92e3.no.png)
## Komme i gang
@ -31,7 +31,7 @@ npm run build
For å installere på Edge, bruk menyen med 'tre prikker' øverst til høyre i nettleseren for å finne utvidelsespanelet. Derfra velger du 'Last inn pakket utvidelse' for å laste inn en ny utvidelse. Åpne 'dist'-mappen når du blir bedt om det, og utvidelsen vil lastes inn. For å bruke den, trenger du en API-nøkkel for CO2 Signal's API ([få en her via e-post](https://www.co2signal.com/) - skriv inn e-posten din i boksen på denne siden) og koden for din region ([finn den her](http://api.electricitymap.org/v3/zones)) som tilsvarer [Electricity Map](https://www.electricitymap.org/map) (for eksempel bruker jeg 'US-NEISO' i Boston).
![installering](../../../../translated_images/install-on-edge.78634f02842c48283726c531998679a6f03a45556b2ee99d8ff231fe41446324.no.png)
![installering](../../../../translated_images/install-on-edge.78634f02842c4828.no.png)
Når API-nøkkelen og regionen er lagt inn i utvidelsesgrensesnittet, bør den fargede prikken i nettleserens utvidelseslinje endres for å gjenspeile energiforbruket i din region og gi deg en pekepinn på hvilke energikrevende aktiviteter som kan være passende å utføre. Konseptet bak dette 'prikk'-systemet ble gitt til meg av [Energy Lollipop-utvidelsen](https://energylollipop.com/) for utslipp i California.

@ -1,59 +1,142 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "862f7f2ef320f6f8950fae379e6ece45",
"translation_date": "2025-10-23T22:37:52+00:00",
"original_hash": "a6332a7bb4d0be3bfd24199c83993777",
"translation_date": "2026-01-07T00:31:19+00:00",
"source_file": "6-space-game/1-introduction/README.md",
"language_code": "no"
}
-->
# Bygg et romspill Del 1: Introduksjon
![Animasjon av romspill som viser gameplay](../../../../6-space-game/images/pewpew.gif)
```mermaid
journey
title Din spillutviklingsreise
section Grunnlag
Lær spillarkitektur: 3: Student
Forstå arv: 4: Student
Utforsk sammensetning: 4: Student
section Kommunikasjon
Bygg pub/sub-system: 4: Student
Design hendelsesflyt: 5: Student
Koble komponenter: 5: Student
section Applikasjon
Lag spillobjekter: 5: Student
Implementer mønstre: 5: Student
Planlegg spillstruktur: 5: Student
```
![Romspill animasjon som viser spill](../../../../6-space-game/images/pewpew.gif)
Akkurat som NASAs oppdragskontroll koordinerer flere systemer under en romferd, skal vi bygge et romspill som demonstrerer hvordan ulike deler av et program kan fungere sømløst sammen. Mens vi lager noe du faktisk kan spille, vil du lære essensielle programmeringskonsepter som gjelder for ethvert programvareprosjekt.
Akkurat som NASAs kontrollsenter koordinerer flere systemer under en romoppskyting, skal vi bygge et romspill som demonstrerer hvordan forskjellige deler av et program kan samarbeide sømløst. Mens du lager noe du faktisk kan spille, vil du lære essensielle programmeringskonsepter som gjelder for ethvert programvareprosjekt.
Vi skal utforske to grunnleggende tilnærminger til organisering av kode: arv og komposisjon. Dette er ikke bare akademiske konsepter de er de samme mønstrene som driver alt fra videospill til banksystemer. Vi skal også implementere et kommunikasjonssystem kalt pub/sub som fungerer som kommunikasjonsnettverkene som brukes i romfartøy, og lar ulike komponenter dele informasjon uten å skape avhengigheter.
Vi skal utforske to grunnleggende tilnærminger for å organisere kode: arv og komposisjon. Dette er ikke bare akademiske konsepter de er de samme mønstrene som driver alt fra videospill til banksystemer. Vi skal også implementere et kommunikasjonssystem kalt pub/sub som fungerer som kommunikasjonsnettverkene brukt i romfartøy, og lar forskjellige komponenter dele informasjon uten å skape avhengigheter.
Ved slutten av denne serien vil du forstå hvordan du bygger applikasjoner som kan skaleres og utvikles enten du utvikler spill, nettapplikasjoner eller andre programvaresystemer.
```mermaid
mindmap
root((Game Architecture))
Objektorganisering
Arv
Komposisjon
Klassehierarkier
Atferdsblanding
Kommunikasjonsmønstre
Pub/Sub-system
Hendelsesutstedere
Meldingsformidling
Løs kobling
Spilleobjekter
Egenskaper (x, y)
Atferder (beveg, kollider)
Livssyklusstyring
Tilstandsadministrasjon
Designmønstre
Fabrikkfunksjoner
Observatørmønster
Komponentsystem
Hendelsesdrevet arkitektur
Skalerbarhet
Modulær design
Vedlikeholdbar kode
Teststrategier
Ytelsesoptimalisering
```
## Quiz før forelesning
[Quiz før forelesning](https://ff-quizzes.netlify.app/web/quiz/29)
## Arv og komposisjon i spillutvikling
Når prosjekter blir mer komplekse, blir organisering av kode kritisk. Det som begynner som et enkelt skript kan bli vanskelig å vedlikeholde uten riktig struktur akkurat som Apollo-oppdragene krevde nøye koordinering mellom tusenvis av komponenter.
Etterhvert som prosjekter vokser i kompleksitet, blir kodeorganisering kritisk. Det som starter som et enkelt skript kan bli vanskelig å vedlikeholde uten riktig struktur akkurat som Apollo-oppdragene krevde nøye koordinering mellom tusenvis av komponenter.
Vi skal utforske to grunnleggende tilnærminger for organisering av kode: arv og komposisjon. Hver har sine unike fordeler, og det å forstå begge hjelper deg med å velge riktig tilnærming for ulike situasjoner. Vi skal demonstrere disse konseptene gjennom vårt romspill, der helter, fiender, power-ups og andre objekter må samhandle effektivt.
Vi skal utforske to grunnleggende tilnærminger for å organisere kode: arv og komposisjon. Hver har tydelige fordeler, og det å forstå begge hjelper deg å velge riktig tilnærming for ulike situasjoner. Vi skal demonstrere disse konseptene gjennom vårt romspill, hvor helter, fiender, power-ups og andre objekter må samhandle effektivt.
✅ En av de mest berømte programmeringsbøkene som noen gang er skrevet handler om [designmønstre](https://en.wikipedia.org/wiki/Design_Patterns).
✅ En av de mest berømte programmeringsbøkene som noensinne er skrevet handler om [designmønstre](https://en.wikipedia.org/wiki/Design_Patterns).
I ethvert spill har du `spillobjekter` de interaktive elementene som fyller spillverdenen din. Helter, fiender, power-ups og visuelle effekter er alle spillobjekter. Hvert eksisterer på spesifikke skjermkoordinater ved bruk av `x` og `y` verdier, likt som å plotte punkter på et koordinatplan.
I ethvert spill har du `spillobjekter` de interaktive elementene som fyller spillverdenen din. Helter, fiender, power-ups og visuelle effekter er alle spillobjekter. Hvert eksisterer på spesifikke skjermkoordinater ved bruk av `x` og `y` verdier, lik plotting av punkter i et koordinatsystem.
Til tross for deres visuelle forskjeller, deler disse objektene ofte grunnleggende oppførsel:
Til tross for deres visuelle forskjeller, deler disse objektene ofte grunnleggende atferder:
- **De eksisterer et sted** Hvert objekt har x- og y-koordinater slik at spillet vet hvor det skal tegnes
- **Mange kan bevege seg rundt** Helter løper, fiender jager, kuler flyr over skjermen
- **De har en levetid** Noen blir værende for alltid, andre (som eksplosjoner) dukker opp kort og forsvinner
- **De reagerer på ting** Når ting kolliderer, samles power-ups, helsebarer oppdateres
✅ Tenk på et spill som Pac-Man. Kan du identifisere de fire objekttypene som er nevnt ovenfor i dette spillet?
### Uttrykke oppførsel gjennom kode
- **Mange kan bevege seg** Helter løper, fiender jager, kuler flyr over skjermen
- **De har en levetid** Noen er der for alltid, andre (som eksplosjoner) vises kortvarig og forsvinner
- **De reagerer på hendelser** Når ting kolliderer, samles power-ups inn, helsebarer oppdateres
✅ Tenk på et spill som Pac-Man. Kan du identifisere de fire objekttypene nevnt over i dette spillet?
```mermaid
classDiagram
class GameObject {
+x: number
+y: number
+type: string
+exists_somewhere()
}
class MovableObject {
+moveTo(x, y)
+kan_bevege_seg()
}
class TemporaryObject {
+levetid: number
+har_levetid()
}
class InteractiveObject {
+vedKollisjon()
+reagerer_på_ting()
}
GameObject <|-- MovableObject
GameObject <|-- TemporaryObject
GameObject <|-- InteractiveObject
MovableObject <|-- Hero
MovableObject <|-- Enemy
MovableObject <|-- Bullet
TemporaryObject <|-- PowerUp
TemporaryObject <|-- Explosion
InteractiveObject <|-- Collectible
InteractiveObject <|-- Obstacle
```
### Å uttrykke atferd gjennom kode
Nå som du forstår de vanlige oppførslene spillobjekter deler, la oss utforske hvordan vi implementerer disse oppførslene i JavaScript. Du kan uttrykke objektoppførsel gjennom metoder knyttet til enten klasser eller individuelle objekter, og det finnes flere tilnærminger å velge mellom.
Nå som du forstår de vanlige atferdene spillobjekter deler, la oss utforske hvordan vi kan implementere disse atferdene i JavaScript. Du kan uttrykke objektatferd gjennom metoder knyttet enten til klasser eller individuelle objekter, og det finnes flere tilnærminger å velge mellom.
**Den klassebaserte tilnærmingen**
Klasser og arv gir en strukturert tilnærming til organisering av spillobjekter. Som det taksonomiske klassifikasjonssystemet utviklet av Carl Linnaeus, starter du med en grunnklasse som inneholder vanlige egenskaper, og deretter oppretter du spesialiserte klasser som arver disse grunnleggende egenskapene mens de legger til spesifikke kapabiliteter.
Klasser og arv gir en strukturert måte å organisere spillobjekter på. Akkurat som taksonomisk klassifiseringssystem utviklet av Carl Linnaeus, starter du med en basis-klasse som inneholder felles egenskaper, deretter lager du spesialiserte klasser som arver disse grunnleggende egenskapene samtidig som de legger til spesifikke funksjoner.
✅ Arv er et viktig konsept å forstå. Lær mer i [MDNs artikkel om arv](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
Slik kan du implementere spillobjekter ved hjelp av klasser og arv:
Slik kan du implementere spillobjekter ved bruk av klasser og arv:
```javascript
// Step 1: Create the base GameObject class
// Trinn 1: Lag den grunnleggende GameObject-klassen
class GameObject {
constructor(x, y, type) {
this.x = x;
@ -63,19 +146,19 @@ class GameObject {
}
```
**La oss bryte dette ned steg for steg:**
- Vi lager en grunnleggende mal som hvert spillobjekt kan bruke
- Konstruktøren lagrer hvor objektet er (`x`, `y`) og hva slags ting det er
- Dette blir grunnlaget som alle spillobjektene dine vil bygge på
**La oss bryte det ned steg for steg:**
- Vi lager en grunnmal som alle spillobjekter kan bruke
- Konstruktøren lagrer hvor objektet er (`x`, `y`) og hva slags type det er
- Dette blir grunnlaget som alle spillobjektene dine vil bygge videre
```javascript
// Step 2: Add movement capability through inheritance
// Steg 2: Legg til bevegelsesevne gjennom arv
class Movable extends GameObject {
constructor(x, y, type) {
super(x, y, type); // Call parent constructor
super(x, y, type); // Kall forelderens konstruktør
}
// Add the ability to move to a new position
// Legg til muligheten til å bevege seg til en ny posisjon
moveTo(x, y) {
this.x = x;
this.y = y;
@ -83,47 +166,47 @@ class Movable extends GameObject {
}
```
**I det ovennevnte har vi:**
**I koden over har vi:**
- **Utvidet** GameObject-klassen for å legge til bevegelsesfunksjonalitet
- **Kalt** foreldrekonstruktøren ved hjelp av `super()` for å initialisere arvede egenskaper
- **Lagt til** en `moveTo()`-metode som oppdaterer objektets posisjon
- **Kalt** foreldrekonstruktøren med `super()` for å initialisere arvede egenskaper
- **Lagt til** en `moveTo()` metode som oppdaterer objektets posisjon
```javascript
// Step 3: Create specific game object types
// Trinn 3: Lag spesifikke spillobjekttyper
class Hero extends Movable {
constructor(x, y) {
super(x, y, 'Hero'); // Set type automatically
super(x, y, 'Hero'); // Sett type automatisk
}
}
class Tree extends GameObject {
constructor(x, y) {
super(x, y, 'Tree'); // Trees don't need movement
super(x, y, 'Tree'); // Trær trenger ikke bevegelse
}
}
// Step 4: Use your game objects
// Trinn 4: Bruk spillobjektene dine
const hero = new Hero(0, 0);
hero.moveTo(5, 5); // Hero can move!
hero.moveTo(5, 5); // Helten kan bevege seg!
const tree = new Tree(10, 15);
// tree.moveTo() would cause an error - trees can't move
// tree.moveTo() ville forårsake en feil - trær kan ikke bevege seg
```
**Forstå disse konseptene:**
- **Oppretter** spesialiserte objekttyper som arver passende oppførsel
- **Demonstrerer** hvordan arv tillater selektiv funksjonalitet
- **Viser** at helter kan bevege seg mens trær forblir stasjonære
- **Oppretter** spesialiserte objekttyper som arver riktige atferder
- **Demonstrerer** hvordan arv tillater selektiv innsnevring av funksjoner
- **Viser** at helter kan bevege seg mens trær står stille
- **Illustrerer** hvordan klassehierarkiet forhindrer upassende handlinger
✅ Ta noen minutter til å forestille deg en Pac-Man-helt (Inky, Pinky eller Blinky, for eksempel) og hvordan det ville bli skrevet i JavaScript.
✅ Ta noen minutter til å forestille deg en Pac-Man helt (f.eks. Inky, Pinky eller Blinky) og hvordan den ville blitt skrevet i JavaScript.
**Komposisjonstilnærmingen**
**Den komposisjonelle tilnærmingen**
Komposisjon følger en modulær designfilosofi, likt hvordan ingeniører designer romfartøy med utskiftbare komponenter. I stedet for å arve fra en foreldreklasse, kombinerer du spesifikke oppførsler for å lage objekter med akkurat den funksjonaliteten de trenger. Denne tilnærmingen gir fleksibilitet uten stive hierarkiske begrensninger.
Komposisjon følger en modulær designfilosofi, lik hvordan ingeniører designer romfartøy med utskiftbare komponenter. I stedet for å arve fra en foreldreklasse, kombinerer du spesifikke atferder for å lage objekter med akkurat den funksjonaliteten de trenger. Denne tilnærmingen gir fleksibilitet uten rigide hierarkiske begrensninger.
```javascript
// Step 1: Create base behavior objects
// Trinn 1: Opprett grunnleggende atferdsobjekter
const gameObject = {
x: 0,
y: 0,
@ -138,16 +221,16 @@ const movable = {
};
```
**Her er hva denne koden gjør:**
- **Definerer** et grunnleggende `gameObject` med posisjons- og typeegenskaper
- **Oppretter** et separat `movable` oppførselsobjekt med bevegelsesfunksjonalitet
- **Skiller** bekymringer ved å holde posisjonsdata og bevegelseslogikk uavhengig
**Dette gjør denne koden:**
- **Definerer** et basis `gameObject` med posisjon- og typeegenskaper
- **Lager** et separat `movable` atferdsobjekt med bevegelsesfunksjonalitet
- **Separerer** ansvar ved å holde posisjonsdata og bevegelseslogikk uavhengige
```javascript
// Step 2: Compose objects by combining behaviors
// Steg 2: Sett sammen objekter ved å kombinere atferd
const movableObject = { ...gameObject, ...movable };
// Step 3: Create factory functions for different object types
// Steg 3: Lag fabrikkfunksjoner for forskjellige objekttyper
function createHero(x, y) {
return {
...movableObject,
@ -167,68 +250,128 @@ function createStatic(x, y, type) {
}
```
**I det ovennevnte har vi:**
- **Kombinert** grunnleggende objektegenskaper med bevegelsesoppførsel ved hjelp av spread-syntaks
**I koden over har vi:**
- **Kombinert** basisobjektets egenskaper med bevegelsesatferd ved bruk av spread-syntaks
- **Opprettet** fabrikkfunksjoner som returnerer tilpassede objekter
- **Muliggjort** fleksibel objektopprettelse uten stive klassehierarkier
- **Tillatt** objekter å ha akkurat de oppførslene de trenger
- **Muliggjort** fleksibel objektopprettelse uten rigide klassehierarkier
- **Tillatt** at objekter har akkurat de atferdene de trenger
```javascript
// Step 4: Create and use your composed objects
// Trinn 4: Opprett og bruk dine sammensatte objekter
const hero = createHero(10, 10);
hero.moveTo(5, 5); // Works perfectly!
hero.moveTo(5, 5); // Fungerer perfekt!
const tree = createStatic(0, 0, 'Tree');
// tree.moveTo() is undefined - no movement behavior was composed
// tree.moveTo() er udefinert - ingen bevegelsesatferd ble satt sammen
```
**Viktige punkter å huske:**
- **Komponerer** objekter ved å blande oppførsler i stedet for å arve dem
- **Gir** mer fleksibilitet enn stive arvhierarkier
- **Tillater** objekter å ha akkurat de funksjonene de trenger
- **Setter sammen** objekter ved å blande atferder i stedet for å arve dem
- **Gir** mer fleksibilitet enn rigide arvshierarkier
- **Lar** objekter ha akkurat de funksjonene de trenger
- **Bruker** moderne JavaScript spread-syntaks for ren objektkombinasjon
```
**Which Pattern Should You Choose?**
> 💡 **Pro Tip**: Both patterns have their place in modern JavaScript development. Classes work well for clearly defined hierarchies, while composition shines when you need maximum flexibility.
>
**Here's when to use each approach:**
- **Choose** inheritance when you have clear "is-a" relationships (a Hero *is-a* Movable object)
- **Select** composition when you need "has-a" relationships (a Hero *has* movement abilities)
- **Consider** your team's preferences and project requirements
- **Remember** that you can mix both approaches in the same application
## Communication Patterns: The Pub/Sub System
As applications grow complex, managing communication between components becomes challenging. The publish-subscribe pattern (pub/sub) solves this problem using principles similar to radio broadcasting one transmitter can reach multiple receivers without knowing who's listening.
Consider what happens when a hero takes damage: the health bar updates, sound effects play, visual feedback appears. Rather than coupling the hero object directly to these systems, pub/sub allows the hero to broadcast a "damage taken" message. Any system that needs to respond can subscribe to this message type and react accordingly.
**Which Pattern Should You Choose?**
**Pub/Sub** stands for 'publish-subscribe'
```mermaid
quadrantChart
title Code Organization Patterns
x-axis Simple --> Complex
y-axis Rigid --> Flexible
quadrant-1 Advanced Composition
quadrant-2 Hybrid Approaches
quadrant-3 Basic Inheritance
quadrant-4 Modern Composition
Class Inheritance: [0.3, 0.2]
Interface Implementation: [0.6, 0.4]
Mixin Patterns: [0.7, 0.7]
Pure Composition: [0.8, 0.9]
Factory Functions: [0.5, 0.8]
Prototype Chain: [0.4, 0.3]
```
### Understanding the Pub/Sub Architecture
> 💡 **Tips:** Begge mønstrene har sin plass i moderne JavaScript-utvikling. Klasser fungerer godt for klart definerte hierarkier, mens komposisjon lyser når du trenger maksimal fleksibilitet.
>
**Her er når du bør bruke hver tilnærming:**
- **Velg** arv når du har klare "er-en" relasjoner (en Helt *er en* Bevegelig objekt)
- **Velg** komposisjon når du har "har-en" relasjoner (en Helt *har* bevegelsesegenskaper)
- **Ta hensyn til** teamets preferanser og prosjektkrav
- **Husk** at du kan blande begge tilnærminger i samme applikasjon
### 🔄 **Pedagogisk sjekk**
**Forståelse av objektorganisering**: Før du går videre til kommunikasjonsmønstre, sørg for at du kan:
- ✅ Forklare forskjellen mellom arv og komposisjon
- ✅ Identifisere når man skal bruke klasser vs fabrikkfunksjoner
- ✅ Forstå hvordan `super()` nøkkelordet fungerer i arv
- ✅ Anerkjenne fordelene med hver tilnærming for spillutvikling
**Raske spørsmål:** Hvordan ville du laget en Flyvende Fiende som både kan flytte seg og fly?
- **Arvstilnærming**: `class FlyingEnemy extends Movable`
- **Komposisjonstilnærming**: `{ ...movable, ...flyable, ...gameObject }`
**Virkelighetsforbindelse:** Disse mønstrene finnes overalt:
- **React-komponenter**: Props (komposisjon) vs klassearv
- **Spillmotorer**: Entitet-komponent-systemer bruker komposisjon
- **Mobilapper**: UI-rammeverk bruker ofte arvehierarkier
## Kommunikasjonsmønstre: Pub/Sub-systemet
Etterhvert som applikasjoner vokser i kompleksitet, blir det utfordrende å håndtere kommunikasjon mellom komponenter. Publish-subscribe-mønsteret (pub/sub) løser dette problemet ved å bruke prinsipper som ligner på radioutsending én sender kan nå flere mottakere uten å vite hvem som lytter.
Tenk på hva som skjer når en helt tar skade: helsebaren oppdateres, lydeffekter spilles av, visuell feedback vises. I stedet for å koble helt-objektet direkte til disse systemene, lar pub/sub helten sende ut en melding om "skade tatt". Ethvert system som må reagere, kan abonnere på denne meldingstypen og svare deretter.
**Pub/Sub** står for 'publish-subscribe'
```mermaid
flowchart TD
A[Helten Tar Skade] --> B[Publiser: HERO_DAMAGED]
B --> C[Hendelsessystem]
C --> D[Helsetrakt Abonnent]
C --> E[Lydsystem Abonnent]
C --> F[Visuelle Effekter Abonnent]
C --> G[Prestasjonssystem Abonnent]
D --> H[Oppdater Helsevisning]
E --> I[Spill Skadelyd]
F --> J[Vis Rødt Blink]
G --> K[Sjekk Overlevelsesprestasjoner]
style A fill:#ffebee
style B fill:#e1f5fe
style C fill:#e8f5e8
style H fill:#fff3e0
style I fill:#fff3e0
style J fill:#fff3e0
style K fill:#fff3e0
```
### Forståelse av Pub/Sub-arkitekturen
The pub/sub pattern keeps different parts of your application loosely coupled, meaning they can work together without being directly dependent on each other. This separation makes your code more maintainable, testable, and flexible to changes.
Pub/sub-mønsteret holder forskjellige deler av applikasjonen løst koblet, noe som betyr at de kan samarbeide uten å være direkte avhengige av hverandre. Denne separasjonen gjør koden din mer vedlikeholdbar, testbar og fleksibel for endringer.
**The key players in pub/sub:**
- **Messages** Simple text labels like `'PLAYER_SCORED'` that describe what happened (plus any extra info)
- **Publishers** The objects that shout out "Something happened!" to anyone who's listening
- **Subscribers** The objects that say "I care about that event" and react when it happens
- **Event System** The middleman that makes sure messages get to the right listeners
**Hovedaktørene i pub/sub:**
- **Meldinger** Enkle tekstetiketter som `'PLAYER_SCORED'` som beskriver hva som skjedde (pluss ekstra info)
- **Utgivere** Objektene som roper ut "Noe skjedde!" til alle som lytter
- **Abonnenter** Objektene som sier "Jeg bryr meg om denne hendelsen" og reagerer når den skjer
- **Hendelsessystemet** Mellommannen som sørger for at meldinger når rett mottakere
### Building an Event System
### Bygge et hendelsessystem
Let's create a simple but powerful event system that demonstrates these concepts:
La oss lage et enkelt men kraftig hendelsessystem som demonstrerer disse konseptene:
```javascript
// Step 1: Create the EventEmitter class
// Trinn 1: Opprett EventEmitter-klassen
class EventEmitter {
constructor() {
this.listeners = {}; // Store all event listeners
this.listeners = {}; // Lagre alle hendelseslyttere
}
// Register a listener for a specific message type
// Registrer en lytter for en bestemt meldingstype
on(message, listener) {
if (!this.listeners[message]) {
this.listeners[message] = [];
@ -236,7 +379,7 @@ class EventEmitter {
this.listeners[message].push(listener);
}
// Send a message to all registered listeners
// Send en melding til alle registrerte lyttere
emit(message, payload = null) {
if (this.listeners[message]) {
this.listeners[message].forEach(listener => {
@ -247,37 +390,37 @@ class EventEmitter {
}
```
**Bryter ned hva som skjer her:**
- **Oppretter** et sentralt hendelseshåndteringssystem ved hjelp av en enkel klasse
**Forklarer hva som skjer her:**
- **Lager** et sentralt hendelseshåndteringssystem med en enkel klasse
- **Lagrer** lyttere i et objekt organisert etter meldingstype
- **Registrerer** nye lyttere ved hjelp av `on()`-metoden
- **Sender** meldinger til alle interesserte lyttere ved hjelp av `emit()`
- **Støtter** valgfrie datalaster for å sende relevant informasjon
- **Registrerer** nye lyttere med `on()`-metoden
- **Sender ut** meldinger til alle interesserte lyttere med `emit()`
- **Støtter** valgfrie dataparametere for å overføre relevant info
### Sette alt sammen: Et praktisk eksempel
### Sette det hele sammen: Et praktisk eksempel
Ok, la oss se dette i aksjon! Vi skal bygge et enkelt bevegelsessystem som viser hvor rent og fleksibelt pub/sub kan være:
La oss se dette i praksis! Vi skal bygge et enkelt bevegelsessystem som viser hvor rent og fleksibelt pub/sub kan være:
```javascript
// Step 1: Define your message types
// Trinn 1: Definer meldingstypene dine
const Messages = {
HERO_MOVE_LEFT: 'HERO_MOVE_LEFT',
HERO_MOVE_RIGHT: 'HERO_MOVE_RIGHT',
ENEMY_SPOTTED: 'ENEMY_SPOTTED'
};
// Step 2: Create your event system and game objects
// Trinn 2: Lag ditt hendelsessystem og spillobjekter
const eventEmitter = new EventEmitter();
const hero = createHero(0, 0);
```
**Her er hva denne koden gjør:**
**Dette gjør denne koden:**
- **Definerer** et konstantobjekt for å forhindre skrivefeil i meldingsnavn
- **Oppretter** en instans av hendelsesutstederen for å håndtere all kommunikasjon
- **Initialiserer** et helteobjekt ved startposisjonen
- **Oppretter** en event emitter-instans for all kommunikasjon
- **Initialiserer** en helt med startposisjon
```javascript
// Step 3: Set up event listeners (subscribers)
// Trinn 3: Sett opp hendelseslyttere (abonnenter)
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
hero.moveTo(hero.x - 5, hero.y);
console.log(`Hero moved to position: ${hero.x}, ${hero.y}`);
@ -289,14 +432,14 @@ eventEmitter.on(Messages.HERO_MOVE_RIGHT, () => {
});
```
**I det ovennevnte har vi:**
**I koden over har vi:**
- **Registrert** hendelseslyttere som reagerer på bevegelsesmeldinger
- **Oppdatert** heltens posisjon basert på bevegelsesretningen
- **Lagt til** konsolllogging for å spore endringer i heltens posisjon
- **Skilt** bevegelseslogikken fra inputhåndteringen
- **Oppdatert** heltens posisjon basert på bevegelsesretning
- **Lagt til** logging i konsollen for å spore heltens posisjonsendringer
- **Separert** bevegelseslogikk fra input-håndtering
```javascript
// Step 4: Connect keyboard input to events (publishers)
// Trinn 4: Koble tastaturinngang til hendelser (utgivere)
window.addEventListener('keydown', (event) => {
switch(event.key) {
case 'ArrowLeft':
@ -310,60 +453,211 @@ window.addEventListener('keydown', (event) => {
```
**Forstå disse konseptene:**
- **Kobler** tastaturinput til spillhendelser uten tett kobling
- **Muliggjør** at inputsystemet kan kommunisere med spillobjekter indirekte
- **Tillater** flere systemer å reagere på de samme tastaturhendelsene
- **Kobler** tastaturinput til spillets hendelser uten tett kobling
- **Muliggjør** at inputsystemet kommuniserer indirekte med spillobjekter
- **Lar** flere systemer svare på de samme tastaturhendelsene
- **Gjør** det enkelt å endre tastebindinger eller legge til nye inputmetoder
> 💡 **Profftips**: Det vakre med dette mønsteret er fleksibiliteten! Du kan enkelt legge til lydeffekter, skjermrystelser eller partikkeffekter ved bare å legge til flere hendelseslyttere ingen behov for å endre eksisterende tastatur- eller bevegelseskode.
```mermaid
sequenceDiagram
participant User
participant Keyboard
participant EventEmitter
participant Hero
participant SoundSystem
participant Camera
User->>Keyboard: Trykker på PilVenstre
Keyboard->>EventEmitter: emit('HERO_MOVE_LEFT')
EventEmitter->>Hero: Flytt venstre 5 piksler
EventEmitter->>SoundSystem: Spill fottrinnlyd
EventEmitter->>Camera: Følg helten
Hero->>Hero: Oppdater posisjon
SoundSystem->>SoundSystem: Spill lyd
Camera->>Camera: Juster synsfelt
```
> 💡 **Tips:** Det fine med dette mønsteret er fleksibiliteten! Du kan enkelt legge til lydeffekter, skjermrystelser eller partikkeffekter ved å bare legge til flere hendelseslyttere uten å endre eksisterende tastatur- eller bevegelseskode.
>
**Her er hvorfor du vil elske denne tilnærmingen:**
- Å legge til nye funksjoner blir superenkelt bare lytt etter hendelsene du bryr deg om
- Flere ting kan reagere på den samme hendelsen uten å komme i konflikt
**Derfor vil du like denne tilnærmingen:**
- Å legge til nye funksjoner blir superenkelt bare hør på hendelser du bryr deg om
- Flere ting kan reagere på samme hendelse uten å forstyrre hverandre
- Testing blir mye enklere fordi hver del fungerer uavhengig
- Når noe går galt, vet du nøyaktig hvor du skal lete
### Hvorfor Pub/Sub skalerer effektivt
Pub/sub-mønsteret opprettholder enkelhet når applikasjoner vokser i kompleksitet. Enten det gjelder å håndtere dusinvis av fiender, dynamiske UI-oppdateringer eller lydsystemer, håndterer mønsteret økt skala uten arkitektoniske endringer. Nye funksjoner integreres i det eksisterende hendelsessystemet uten å påvirke etablert funksjonalitet.
Pub/sub-mønsteret holder ting enkelt selv når applikasjoner vokser i kompleksitet. Enten det handler om å styre dusinvis av fiender, dynamiske UI-oppdateringer eller lydsystemer, håndterer mønsteret økt skala uten arkitektoniske endringer. Nye funksjoner integreres i eksisterende hendelsessystem uten å påvirke etablert funksjonalitet.
> ⚠️ **Vanlig feil**: Ikke opprett for mange spesifikke meldingstyper tidlig. Start med brede kategorier og finjuster dem etter hvert som spillets behov blir tydeligere.
> ⚠️ **Vanlig feil:** Ikke lag for mange spesifikke meldingstyper tidlig. Start med brede kategorier og gjør dem mer detaljerte etter hvert som spillets behov blir tydeligere.
>
**Beste praksis å følge:**
- **Grupperer** relaterte meldinger i logiske kategorier
- **Bruker** beskrivende navn som tydelig indikerer hva som skjedde
- **Holder** meldingsdatalaster enkle og fokuserte
- **Dokumenterer** meldingstypene dine for samarbeid i teamet
- **Holder** meldingsdata enkle og fokuserte
- **Dokumenterer** meldingstypene for team-samarbeid
### 🔄 **Pedagogisk sjekk**
**Forståelse av hendelsesdrevet arkitektur**: Sjekk forståelsen din av hele systemet:
- ✅ Hvordan hindrer pub/sub tett kobling mellom komponenter?
- ✅ Hvorfor er det enklere å legge til nye funksjoner med hendelsesdrevet arkitektur?
- ✅ Hvilken rolle spiller EventEmitter i kommunikasjonsflyten?
- ✅ Hvordan hjelper meldingkonstanter med å unngå feil og forbedre vedlikehold?
**Designutfordring:** Hvordan ville du håndtert disse spillscenariene med pub/sub?
1. **Fiende dør**: Oppdatere poengsum, spille lyd, spawn power-up, fjerne fra skjerm
2. **Nivå fullført**: Stoppe musikk, vise UI, lagre fremdrift, laste neste nivå
3. **Power-up samlet**: Forbedre evner, oppdatere UI, spille effekt, starte timer
**Profesjonell forbindelse:** Dette mønsteret finnes i:
- **Frontend-rammeverk**: React/Vue hendelsessystemer
- **Backend-tjenester**: Mikrotjenestekommunikasjon
- **Spillmotorer**: Unitys hendelsessystem
- **Mobilutvikling**: iOS/Android notifikasjonssystemer
---
## GitHub Copilot Agent Challenge 🚀
## GitHub Copilot Agent-utfordring 🚀
Bruk Agent-modus for å fullføre følgende utfordring:
Bruk Agent-modus til å fullføre følgende utfordring:
**Beskrivelse:** Lag et enkelt system for spillobjekter ved hjelp av både arv og pub/sub-mønsteret. Du skal implementere et grunnleggende spill der ulike objekter kan kommunisere gjennom hendelser uten å kjenne direkte til hverandre.
**Beskrivelse:** Lag et enkelt system for spillobjekter ved bruk av både arv og pub/sub-mønsteret. Du skal implementere et grunnleggende spill hvor forskjellige objekter kan kommunisere gjennom hendelser uten å vite direkte om hverandre.
**Oppgave:** Lag et JavaScript-spillsystem med følgende krav: 1) Lag en grunnleggende GameObject-klasse med x-, y-koordinater og en type-egenskap. 2) Lag en Hero-klasse som utvider GameObject og kan bevege seg. 3) Lag en Enemy-klasse som utvider GameObject og kan jage helten. 4) Implementer en EventEmitter-klasse for pub/sub-mønsteret. 5) Sett opp hendelseslyttere slik at når helten beveger seg, mottar nærliggende fiender en 'HERO_MOVED'-hendelse og oppdaterer posisjonen sin for å bevege seg mot helten. Inkluder console.log-utsagn for å vise kommunikasjonen mellom objektene.
**Oppgave:** Lag et JavaScript-spillsystem med disse kravene: 1) Lag en basis GameObject-klasse med x, y-koordinater og en type-egenskap. 2) Lag en Hero-klasse som arver fra GameObject og kan bevege seg. 3) Lag en Enemy-klasse som arver fra GameObject og kan jage helten. 4) Implementer en EventEmitter-klasse for pub/sub-mønsteret. 5) Sett opp hendelseslyttere slik at når helten beveger seg, mottar nærliggende fiender en 'HERO_MOVED'-hendelse og oppdaterer posisjonen sin for å bevege seg mot helten. Inkluder console.log-statementer for å vise kommunikasjonen mellom objektene.
Lær mer om [agent-modus](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) her.
## 🚀 Utfordring
Vurder hvordan pub-sub-mønsteret kan forbedre spillarkitektur. Identifiser hvilke komponenter som bør sende ut hendelser og hvordan systemet bør reagere. Design et spillkonsept og kartlegg kommunikasjonsmønstrene mellom komponentene.
Tenk over hvordan pub-sub-mønsteret kan forbedre spillarkitekturen. Identifiser hvilke komponenter som bør sende ut hendelser og hvordan systemet bør reagere. Design et spillkonsept og kartlegg kommunikasjonsmønstrene mellom komponentene.
## Quiz etter forelesning
## Post-forelesningsquiz
[Quiz etter forelesning](https://ff-quizzes.netlify.app/web/quiz/30)
[Post-forelesningsquiz](https://ff-quizzes.netlify.app/web/quiz/30)
## Gjennomgang og selvstudium
## Gjennomgang & Selvstudium
Lær mer om Pub/Sub ved å [lese om det](https://docs.microsoft.com/azure/architecture/patterns/publisher-subscriber/?WT.mc_id=academic-77807-sagibbon).
### ⚡ **Hva du kan gjøre de neste 5 minuttene**
- [ ] Åpne et hvilket som helst HTML5-spill på nettet og inspiser koden med DevTools
- [ ] Lag et enkelt HTML5 Canvas-element og tegn en grunnleggende form
- [ ] Prøv å bruke `setInterval` for å lage en enkel animasjonsloop
- [ ] Utforsk Canvas API-dokumentasjonen og prøv en tegnemetode
### 🎯 **Hva du kan oppnå denne timen**
- [ ] Fullfør post-leksjonsquizen og forstå spillutviklingskonsepter
- [ ] Sett opp spillprosjektstrukturen med HTML, CSS og JavaScript-filer
- [ ] Lag en grunnleggende spill-løkke som oppdaterer og tegner kontinuerlig
- [ ] Tegn dine første spillsprites på canvasen
- [ ] Implementer grunnleggende lasting av ressurser for bilder og lyder
### 📅 **Din ukelange spillutvikling**
- [ ] Fullfør hele romspillet med alle planlagte funksjoner
- [ ] Legg til polert grafikk, lydeffekter og jevne animasjoner
- [ ] Implementer spilltilstander (startskjerm, spilling, spill over)
- [ ] Lag et scoringssystem og spor spillerens fremgang
- [ ] Gjør spillet ditt responsivt og tilgjengelig på tvers av enheter
- [ ] Del spillet ditt på nettet og samle tilbakemeldinger fra spillere
### 🌟 **Din månedslange spillutvikling**
- [ ] Bygg flere spill som utforsker forskjellige sjangere og mekanikker
- [ ] Lær et spillutviklingsrammeverk som Phaser eller Three.js
- [ ] Bidra til open source spillutviklingsprosjekter
- [ ] Mestre avanserte spillprogrammeringsmønstre og optimalisering
- [ ] Lag en portefølje som viser frem dine ferdigheter innen spillutvikling
- [ ] Veilede andre som er interessert i spillutvikling og interaktive medier
## 🎯 Din tidslinje for mestring av spillutvikling
```mermaid
timeline
title Spillarkitektur Læringsprogresjon
section Objektmønstre (20 minutter)
Kodeorganisering: Klassearv
: Komposisjonsmønstre
: Fabrikkfunksjoner
: Atferdsblanding
section Kommunikasjonssystemer (25 minutter)
Hendelsesarkitektur: Pub/Sub-implementering
: Meldingsdesign
: Hendelsesutløsere
: Løs kobling
section Spillobjektdesign (30 minutter)
Enhetssystemer: Egenskapshåndtering
: Atferdskomposisjon
: Tilstandshåndtering
: Livssyklusadministrasjon
section Arkitekturmønstre (35 minutter)
Systemdesign: Komponentssystemer
: Observatørmønster
: Kommandomønster
: Tilstandsautomater
section Avanserte Konsepter (45 minutter)
Skalerbar Arkitektur: Ytelsesoptimalisering
: Minnehåndtering
: Modulær design
: Teststrategier
section Spillmotor Konsepter (1 uke)
Profesjonell Utvikling: Scenesystemer
: Ressursforvaltning
: Renderingsrørledninger
: Fysikkintegrasjon
section Rammeverk Mestring (2 uker)
Moderne Spillutvikling: React spillmønstre
: Canvasoptimalisering
: Grunnleggende WebGL
: PWA-spill
section Industripraksis (1 måned)
Profesjonelle Ferdigheter: Team-samarbeid
: Kodegjennomganger
: Spilldesigmønstre
: Ytelsesprofilering
```
### 🛠️ Sammendrag av ditt spillarkitekturverktøy
Etter å ha fullført denne leksjonen har du nå:
- **Mestring av designmønstre**: Forståelse av arv vs. komposisjon og deres kompromisser
- **Hendelsesdrevet arkitektur**: Pub/sub-implementasjon for skalerbar kommunikasjon
- **Objektorientert design**: Klassehierarkier og atferdskomposisjon
- **Moderne JavaScript**: Fabrikkfunksjoner, spread-syntaks og ES6+-mønstre
- **Skalerbar arkitektur**: Løst koblede og modulære designprinsipper
- **Grunnlag for spillutvikling**: Enhetssystemer og komponentmønstre
- **Profesjonelle mønstre**: Industristandarder for kodeorganisering
**Virkelige bruksområder**: Disse mønstrene anvendes direkte på:
- **Frontend-rammeverk**: React/Vue-komponentarkitektur og tilstandsadministrasjon
- **Backend-tjenester**: Mikrotjenestekommunikasjon og hendelsesdrevne systemer
- **Mobilutvikling**: iOS/Android-apparkitektur og varslingssystemer
- **Spillmotorer**: Unity, Unreal og nettbasert spillutvikling
- **Enterprise-programvare**: Hendelseskildring og distribuert systemdesign
- **API-design**: RESTful tjenester og sanntidskommunikasjon
**Profesjonelle ferdigheter oppnådd**: Du kan nå:
- **Designe** skalerbare programvarearkitekturer med beprøvde mønstre
- **Implementere** hendelsesdrevne systemer som håndterer komplekse interaksjoner
- **Velge** passende kodeorganiseringsstrategier for ulike scenarioer
- **Feilsøke** og vedlikeholde løst koblede systemer effektivt
- **Kommunisere** tekniske beslutninger ved bruk av industristandard terminologi
**Neste nivå**: Du er klar til å implementere disse mønstrene i et ekte spill, utforske avanserte temaer innen spillutvikling, eller anvende disse arkitekturkonseptene på nettapplikasjoner!
🌟 **Prestasjon oppnådd**: Du har mestret grunnleggende programvarearkitektur-mønstre som driver alt fra enkle spill til komplekse bedriftsystemer!
## Oppgave
[Mock opp et spill](assignment.md)
[Skissér et spill](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Ansvarsfraskrivelse**:
Dette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vennligst vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på dets opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår fra bruken av denne oversettelsen.
<!-- CO-OP TRANSLATOR DISCLAIMER END -->
Loading…
Cancel
Save