🌐 Update translations via Co-op Translator

pull/1497/head
leestott 4 months ago committed by GitHub
parent 709470750e
commit 425e0f6fbe

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "c63675cfaf1d223b37bb9fecbfe7c252",
"translation_date": "2025-08-26T22:24:00+00:00",
"original_hash": "2dcbb9259dee4f20a4f08d9a1aa2bd4c",
"translation_date": "2025-08-29T08:22:39+00:00",
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md",
"language_code": "da"
}
@ -32,7 +32,7 @@ I denne lektion vil vi dække:
Programmering (også kendt som kodning) er processen med at skrive instruktioner til en enhed som en computer eller mobil enhed. Vi skriver disse instruktioner med et programmeringssprog, som derefter bliver fortolket af enheden. Disse sæt af instruktioner kan kaldes forskellige ting, men *program*, *computerprogram*, *applikation (app)* og *eksekverbar fil* er nogle populære navne.
Et *program* kan være alt, der er skrevet med kode; hjemmesider, spil og mobilapps er programmer. Selvom det er muligt at skabe et program uden at skrive kode, bliver den underliggende logik fortolket af enheden, og den logik er sandsynligvis skrevet med kode. Et program, der *kører* eller *eksekverer* kode, udfører instruktioner. Den enhed, du læser denne lektion på, kører et program for at vise den på din skærm.
Et *program* kan være alt, der er skrevet med kode; hjemmesider, spil og telefonapps er programmer. Selvom det er muligt at skabe et program uden at skrive kode, bliver den underliggende logik fortolket af enheden, og den logik er sandsynligvis skrevet med kode. Et program, der *kører* eller *eksekverer* kode, udfører instruktioner. Enheden, du læser denne lektion på, kører et program for at vise den på din skærm.
✅ Lav lidt research: Hvem anses for at være verdens første computerprogrammør?
@ -83,7 +83,7 @@ back add r0,r1
end
```
Tro det eller ej, *de gør begge det samme*: de udskriver en Fibonacci-sekvens op til 10.
Tro det eller ej, *de gør begge det samme*: udskriver en Fibonacci-sekvens op til 10.
✅ En Fibonacci-sekvens er [defineret](https://en.wikipedia.org/wiki/Fibonacci_number) som en række tal, hvor hvert tal er summen af de to foregående, startende fra 0 og 1. De første 10 tal i Fibonacci-sekvensen er 0, 1, 1, 2, 3, 5, 8, 13, 21 og 34.
@ -91,7 +91,7 @@ Tro det eller ej, *de gør begge det samme*: de udskriver en Fibonacci-sekvens o
En enkelt instruktion i et program kaldes en *statement* og vil normalt have et tegn eller en linjeafstand, der markerer, hvor instruktionen slutter, eller *terminerer*. Hvordan et program terminerer varierer med hvert sprog.
Statements i et program kan afhænge af data, der leveres af en bruger eller andetsteds, for at udføre instruktioner. Data kan ændre, hvordan et program opfører sig, så programmeringssprog kommer med en måde at midlertidigt gemme data, så de kan bruges senere. Disse kaldes *variabler*. Variabler er statements, der instruerer en enhed i at gemme data i sin hukommelse. Variabler i programmer ligner variabler i algebra, hvor de har et unikt navn, og deres værdi kan ændre sig over tid.
Statements i et program kan afhænge af data, der leveres af en bruger eller andetsteds, for at udføre instruktioner. Data kan ændre, hvordan et program opfører sig, så programmeringssprog kommer med en måde at midlertidigt gemme data, så det kan bruges senere. Disse kaldes *variabler*. Variabler er statements, der instruerer en enhed til at gemme data i sin hukommelse. Variabler i programmer ligner variabler i algebra, hvor de har et unikt navn, og deres værdi kan ændre sig over tid.
Der er en chance for, at nogle statements ikke bliver eksekveret af en enhed. Dette er normalt med vilje, når det er skrevet af udvikleren, eller ved et uheld, når en uventet fejl opstår. Denne type kontrol over en applikation gør den mere robust og vedligeholdelsesvenlig. Typisk sker disse ændringer i kontrol, når visse betingelser er opfyldt. En almindelig statement, der bruges i moderne programmering til at kontrollere, hvordan et program kører, er `if..else` statement.
@ -113,12 +113,12 @@ Et af de mest afgørende værktøjer til softwareudvikling er editoren. Editorer
Udviklere stoler på editorer af flere grunde:
- *Debugging* hjælper med at finde fejl og problemer ved at gennemgå koden linje for linje. Nogle editorer har debugging-funktioner; de kan tilpasses og tilføjes for specifikke programmeringssprog.
- *Debugging* hjælper med at finde fejl og problemer ved at gennemgå koden linje for linje. Nogle editorer har debugging-funktioner; de kan tilpasses og tilføjes til specifikke programmeringssprog.
- *Syntax highlighting* tilføjer farver og tekstformatering til kode, hvilket gør det lettere at læse. De fleste editorer tillader tilpasset syntax highlighting.
- *Extensions og integrationer* er specialiserede værktøjer for udviklere, lavet af udviklere. Disse værktøjer var ikke indbygget i den grundlæggende editor. For eksempel dokumenterer mange udviklere deres kode for at forklare, hvordan den fungerer. De kan installere en stavekontrol-extension for at finde stavefejl i dokumentationen. De fleste extensions er beregnet til brug inden for en specifik editor, og de fleste editorer har en måde at søge efter tilgængelige extensions.
- *Tilpasning* gør det muligt for udviklere at skabe et unikt udviklingsmiljø, der passer til deres behov. De fleste editorer er ekstremt tilpasselige og kan også give udviklere mulighed for at skabe egne extensions.
- *Extensions og integrationer* er specialiserede værktøjer for udviklere, lavet af udviklere. Disse værktøjer var ikke indbygget i den grundlæggende editor. For eksempel dokumenterer mange udviklere deres kode for at forklare, hvordan den fungerer. De kan installere en stavekontrol-udvidelse for at finde stavefejl i dokumentationen. De fleste udvidelser er beregnet til brug inden for en specifik editor, og de fleste editorer kommer med en måde at søge efter tilgængelige udvidelser.
- *Tilpasning* gør det muligt for udviklere at skabe et unikt udviklingsmiljø, der passer til deres behov. De fleste editorer er ekstremt tilpasselige og kan også give udviklere mulighed for at skabe egne udvidelser.
#### Populære editorer og webudviklings-extensions
#### Populære editorer og webudviklingsudvidelser
- [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon)
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
@ -147,7 +147,7 @@ Mange browsere kommer med *udviklerværktøjer* (DevTools), der indeholder et s
### Kommandolinjeværktøjer
Nogle udviklere foretrækker en mindre grafisk visning til deres daglige opgaver og stoler på kommandolinjen for at opnå dette. At skrive kode kræver en betydelig mængde tastning, og nogle udviklere foretrækker ikke at forstyrre deres flow på tastaturet. De vil bruge tastaturgenveje til at skifte mellem desktop-vinduer, arbejde på forskellige filer og bruge værktøjer. De fleste opgaver kan udføres med en mus, men en fordel ved at bruge kommandolinjen er, at meget kan gøres med kommandolinjeværktøjer uden behov for at skifte mellem mus og tastatur. En anden fordel ved kommandolinjen er, at den kan konfigureres, og du kan gemme en brugerdefineret konfiguration, ændre den senere og importere den til andre udviklingsmaskiner. Fordi udviklingsmiljøer er så unikke for hver udvikler, vil nogle undgå at bruge kommandolinjen, nogle vil stole helt på den, og nogle foretrækker en blanding af de to.
Nogle udviklere foretrækker en mindre grafisk visning til deres daglige opgaver og stoler på kommandolinjen for at opnå dette. At skrive kode kræver en betydelig mængde tastning, og nogle udviklere foretrækker ikke at forstyrre deres flow på tastaturet. De vil bruge tastaturgenveje til at skifte mellem desktopvinduer, arbejde på forskellige filer og bruge værktøjer. De fleste opgaver kan udføres med en mus, men en fordel ved at bruge kommandolinjen er, at meget kan gøres med kommandolinjeværktøjer uden behov for at skifte mellem mus og tastatur. En anden fordel ved kommandolinjen er, at den kan konfigureres, og du kan gemme en brugerdefineret konfiguration, ændre den senere og importere den til andre udviklingsmaskiner. Fordi udviklingsmiljøer er så unikke for hver udvikler, vil nogle undgå at bruge kommandolinjen, nogle vil stole helt på den, og nogle foretrækker en blanding af de to.
### Populære kommandolinjevalg
@ -158,7 +158,7 @@ Valg for kommandolinjen vil variere afhængigt af det operativsystem, du bruger.
#### Windows
- [Powershell](https://docs.microsoft.com/powershell/scripting/overview?view=powershell-7/?WT.mc_id=academic-77807-sagibbon) 💻
- [Command Line](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands/?WT.mc_id=academic-77807-sagibbon) (også kendt som CMD) 💻
- [Kommandolinje](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands/?WT.mc_id=academic-77807-sagibbon) (også kendt som CMD) 💻
- [Windows Terminal](https://docs.microsoft.com/windows/terminal/?WT.mc_id=academic-77807-sagibbon)
- [mintty](https://mintty.github.io/)
@ -201,17 +201,17 @@ Når en udvikler ønsker at lære noget nyt, vil de sandsynligvis vende sig mod
Sammenlign nogle programmeringssprog. Hvad er nogle af de unikke træk ved JavaScript vs. Java? Hvad med COBOL vs. Go?
## Quiz efter lektionen
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/2)
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/)
## Gennemgang & Selvstudie
Undersøg lidt om de forskellige sprog, der er tilgængelige for programmører. Prøv at skrive en linje i ét sprog og omskriv den derefter i to andre. Hvad lærte du?
Undersøg lidt om de forskellige sprog, der er tilgængelige for programmøren. Prøv at skrive en linje i ét sprog og derefter omskrive den i to andre. Hvad lærte du?
## Opgave
[Læs dokumentationen](assignment.md)
[Læse dokumentationen](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "05666cecb8983a72cf0ce1d18932b5b7",
"translation_date": "2025-08-26T22:14:28+00:00",
"original_hash": "361249da70432ddfd4741c917d1a6f50",
"translation_date": "2025-08-29T08:24:24+00:00",
"source_file": "1-getting-started-lessons/2-github-basics/README.md",
"language_code": "da"
}
@ -15,29 +15,29 @@ Denne lektion dækker det grundlæggende i GitHub, en platform til at hoste og a
> Sketchnote af [Tomomi Imura](https://twitter.com/girlie_mac)
## Quiz før lektionen
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/3)
[Quiz før lektionen](https://ff-quizzes.netlify.app)
## Introduktion
I denne lektion vil vi gennemgå:
- hvordan du sporer det arbejde, du laver på din maskine
- hvordan du arbejder på projekter med andre
- hvordan du arbejder på projekter sammen med andre
- hvordan du bidrager til open source-software
### Forudsætninger
Før du begynder, skal du tjekke, om Git er installeret. I terminalen skal du skrive:
Før du begynder, skal du tjekke, om Git er installeret. Skriv i terminalen:
`git --version`
Hvis Git ikke er installeret, [download Git](https://git-scm.com/downloads). Derefter skal du opsætte din lokale Git-profil i terminalen:
Hvis Git ikke er installeret, [download Git](https://git-scm.com/downloads). Opsæt derefter din lokale Git-profil i terminalen:
* `git config --global user.name "dit-navn"`
* `git config --global user.email "din-email"`
For at tjekke, om Git allerede er konfigureret, kan du skrive:
For at tjekke, om Git allerede er konfigureret, kan du skrive:
`git config --list`
Du skal også have en GitHub-konto, en kodeeditor (som Visual Studio Code), og du skal åbne din terminal (eller: kommandoprompt).
Du skal også bruge en GitHub-konto, en kodeeditor (som Visual Studio Code), og du skal åbne din terminal (eller: kommandoprompt).
Gå til [github.com](https://github.com/) og opret en konto, hvis du ikke allerede har en, eller log ind og udfyld din profil.
@ -45,18 +45,18 @@ Gå til [github.com](https://github.com/) og opret en konto, hvis du ikke allere
### Forberedelse
Du skal bruge både en mappe med et kodeprojekt på din lokale maskine (laptop eller PC) og et offentligt repository på GitHub, som vil fungere som et eksempel på, hvordan man bidrager til andres projekter.
Du skal bruge både en mappe med et kodeprojekt på din lokale maskine (laptop eller PC) og et offentligt repository på GitHub, som vil tjene som et eksempel på, hvordan man bidrager til andres projekter.
---
## Kodestyring
## Kodehåndtering
Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at spore din fremgang ved hjælp af git - versionskontrolsystemet. Nogle mennesker sammenligner brugen af git med at skrive et kærlighedsbrev til dit fremtidige jeg. Når du læser dine commit-beskeder dage, uger eller måneder senere, vil du kunne huske, hvorfor du tog en beslutning, eller "rulle tilbage" en ændring - det vil sige, hvis du skriver gode "commit-beskeder".
Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at spore din fremgang ved hjælp af git - versionskontrolsystemet. Nogle sammenligner brugen af git med at skrive et kærlighedsbrev til dit fremtidige jeg. Når du læser dine commit-beskeder dage, uger eller måneder senere, vil du kunne huske, hvorfor du tog en beslutning, eller "rulle tilbage" en ændring - det vil sige, når du skriver gode "commit-beskeder".
### Opgave: Opret et repository og commit kode
> Se video
>
> Se video
>
> [![Git og GitHub grundlæggende video](https://img.youtube.com/vi/9R31OUPpxU4/0.jpg)](https://www.youtube.com/watch?v=9R31OUPpxU4)
1. **Opret repository på GitHub**. På GitHub.com, under repositories-fanen eller fra navigationslinjen øverst til højre, find knappen **new repo**.
@ -93,7 +93,7 @@ Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at
modified: file2.txt
```
Typisk fortæller en `git status`-kommando dig ting som hvilke filer der er klar til at blive _gemt_ i repoet, eller som har ændringer, du måske vil gemme.
Typisk fortæller en `git status`-kommando dig ting som hvilke filer, der er klar til at blive _gemt_ i repoet, eller som har ændringer, du måske vil gemme.
1. **Tilføj alle filer til sporing**
Dette kaldes også at stage filer/tilføje filer til staging-området.
@ -102,7 +102,7 @@ Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at
git add .
```
`git add` plus `.` argumentet angiver, at alle dine filer og ændringer skal spores.
Argumentet `git add` plus `.` angiver, at alle dine filer og ændringer skal spores.
1. **Tilføj udvalgte filer til sporing**
@ -128,15 +128,15 @@ Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at
Denne kommando hjælper os med kun at fjerne en bestemt fil fra staging-området, som vi ikke ønsker at inkludere i den næste commit.
1. **Gem dit arbejde**. På dette tidspunkt har du tilføjet filerne til et såkaldt _staging-område_. Et sted, hvor Git sporer dine filer. For at gøre ændringen permanent skal du _committe_ filerne. For at gøre dette opretter du en _commit_ med kommandoen `git commit`. En _commit_ repræsenterer et gemmepunkt i historien for dit repo. Skriv følgende for at oprette en _commit_:
1. **Gem dit arbejde**. På dette tidspunkt har du tilføjet filerne til et såkaldt _staging-område_. Et sted, hvor Git sporer dine filer. For at gøre ændringen permanent skal du _commit_ filerne. For at gøre dette opretter du en _commit_ med kommandoen `git commit`. En _commit_ repræsenterer et gemmepunkt i historien for dit repo. Skriv følgende for at oprette en _commit_:
```bash
git commit -m "first commit"
```
Dette commit'er alle dine filer og tilføjer beskeden "first commit". For fremtidige commit-beskeder vil du gerne være mere beskrivende for at formidle, hvilken type ændring du har lavet.
Dette committer alle dine filer og tilføjer beskeden "first commit". For fremtidige commit-beskeder vil du gerne være mere beskrivende for at formidle, hvilken type ændring du har lavet.
1. **Forbind dit lokale Git-repo med GitHub**. Et Git-repo er godt på din maskine, men på et tidspunkt vil du gerne have en backup af dine filer et sted og også invitere andre til at arbejde med dig på dit repo. Et godt sted at gøre dette er GitHub. Husk, vi har allerede oprettet et repo på GitHub, så det eneste, vi skal gøre, er at forbinde vores lokale Git-repo med GitHub. Kommandoen `git remote add` gør netop dette. Skriv følgende kommando:
1. **Forbind dit lokale Git-repo med GitHub**. Et Git-repo er godt på din maskine, men på et tidspunkt vil du gerne have en backup af dine filer et sted og også invitere andre til at arbejde med dig på dit repo. Et godt sted at gøre dette er GitHub. Husk, at vi allerede har oprettet et repo på GitHub, så det eneste, vi skal gøre, er at forbinde vores lokale Git-repo med GitHub. Kommandoen `git remote add` gør netop dette. Skriv følgende kommando:
> Bemærk, før du skriver kommandoen, skal du gå til din GitHub-repo-side for at finde repository-URL'en. Du vil bruge den i nedenstående kommando. Erstat ```https://github.com/username/repository_name.git``` med din GitHub-URL.
@ -146,9 +146,9 @@ Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at
Dette opretter en _remote_, eller forbindelse, kaldet "origin", der peger på det GitHub-repository, du oprettede tidligere.
1. **Send lokale filer til GitHub**. Indtil videre har du oprettet en _forbindelse_ mellem det lokale repo og GitHub-repoet. Lad os sende disse filer til GitHub med følgende kommando `git push`, som vist nedenfor:
1. **Send lokale filer til GitHub**. Indtil videre har du oprettet en _forbindelse_ mellem det lokale repo og GitHub-repoet. Lad os sende disse filer til GitHub med følgende kommando `git push`, som følger:
> Bemærk, dit branch-navn kan være anderledes som standard end ```main```.
> Bemærk, dit branch-navn kan være forskelligt som standard fra ```main```.
```bash
git push -u origin main
@ -164,17 +164,17 @@ Lad os sige, at du har en mappe lokalt med et kodeprojekt, og du vil begynde at
git push
```
> Tip, du vil måske også adoptere en `.gitignore`-fil for at forhindre filer, du ikke ønsker at spore, i at dukke op på GitHub - som den notesfil, du gemmer i samme mappe, men som ikke har nogen plads i et offentligt repository. Du kan finde skabeloner til `.gitignore`-filer på [.gitignore templates](https://github.com/github/gitignore).
> Tip: Du vil måske også adoptere en `.gitignore`-fil for at forhindre filer, du ikke ønsker at spore, i at dukke op på GitHub - som den notesfil, du gemmer i samme mappe, men som ikke hører hjemme i et offentligt repository. Du kan finde skabeloner til `.gitignore`-filer på [.gitignore templates](https://github.com/github/gitignore).
#### Commit-beskeder
En god Git commit-emnelinje fuldender følgende sætning:
Hvis anvendt, vil denne commit <din emnelinje her>
For emnet skal du bruge den imperativ, nutidige form: "ændre" i stedet for "ændrede" eller "ændringer".
Som i emnet skal du også i kroppen (valgfrit) bruge den imperativ, nutidige form. Kroppen bør inkludere motivationen for ændringen og kontrastere dette med tidligere adfærd. Du forklarer `hvorfor`, ikke `hvordan`.
For emnet skal du bruge den bydeform, nutid: "ændrer" i stedet for "ændrede" eller "ændringer".
Som i emnet skal du også i brødteksten (valgfrit) bruge den bydeform, nutid. Brødteksten bør inkludere motivationen for ændringen og kontrastere dette med tidligere adfærd. Du forklarer `hvorfor`, ikke `hvordan`.
Tag et par minutter til at surfe rundt på GitHub. Kan du finde en virkelig god commit-besked? Kan du finde en virkelig minimal en? Hvilken information synes du er den vigtigste og mest nyttige at formidle i en commit-besked?
Brug et par minutter på at surfe rundt på GitHub. Kan du finde en virkelig god commit-besked? Kan du finde en meget minimal én? Hvilken information synes du er den vigtigste og mest nyttige at formidle i en commit-besked?
### Opgave: Samarbejd
@ -182,37 +182,37 @@ Hovedårsagen til at lægge ting på GitHub var at gøre det muligt at samarbejd
## Arbejde på projekter med andre
> Se video
>
> Se video
>
> [![Git og GitHub grundlæggende video](https://img.youtube.com/vi/bFCM-PC3cu8/0.jpg)](https://www.youtube.com/watch?v=bFCM-PC3cu8)
I dit repository skal du navigere til `Insights > Community` for at se, hvordan dit projekt sammenlignes med anbefalede fællesskabsstandarder.
Her er nogle ting, der kan forbedre dit GitHub-repo:
- **Beskrivelse**. Har du tilføjet en beskrivelse af dit projekt?
- **README**. Har du tilføjet en README? GitHub giver vejledning til at skrive en [README](https://docs.github.com/articles/about-readmes/?WT.mc_id=academic-77807-sagibbon).
- **Retningslinjer for bidrag**. Har dit projekt [retningslinjer for bidrag](https://docs.github.com/articles/setting-guidelines-for-repository-contributors/?WT.mc_id=academic-77807-sagibbon)?
- **Adfærdskodeks**. En [adfærdskodeks](https://docs.github.com/articles/adding-a-code-of-conduct-to-your-project/).
- **Licens**. Måske vigtigst af alt, en [licens](https://docs.github.com/articles/adding-a-license-to-a-repository/).
Her er nogle ting, der kan forbedre dit GitHub-repo:
- **Beskrivelse**. Har du tilføjet en beskrivelse af dit projekt?
- **README**. Har du tilføjet en README? GitHub giver vejledning til at skrive en [README](https://docs.github.com/articles/about-readmes/?WT.mc_id=academic-77807-sagibbon).
- **Retningslinjer for bidrag**. Har dit projekt [retningslinjer for bidrag](https://docs.github.com/articles/setting-guidelines-for-repository-contributors/?WT.mc_id=academic-77807-sagibbon)?
- **Adfærdskodeks**. Et [adfærdskodeks](https://docs.github.com/articles/adding-a-code-of-conduct-to-your-project/).
- **Licens**. Måske vigtigst af alt, en [licens](https://docs.github.com/articles/adding-a-license-to-a-repository/)?
Alle disse ressourcer vil gavne onboarding af nye teammedlemmer. Og det er typisk den slags ting, nye bidragydere kigger på, før de overhovedet ser på din kode, for at finde ud af, om dit projekt er det rigtige sted for dem at bruge deres tid.
Alle disse ressourcer vil gavne onboarding af nye teammedlemmer. Og det er typisk den slags ting, nye bidragydere kigger på, før de overhovedet ser på din kode, for at finde ud af, om dit projekt er det rette sted for dem at bruge deres tid.
✅ README-filer, selvom de tager tid at forberede, bliver ofte overset af travle vedligeholdere. Kan du finde et eksempel på en særlig beskrivende README? Bemærk: der findes nogle [værktøjer til at hjælpe med at lave gode READMEs](https://www.makeareadme.com/), som du måske vil prøve.
✅ README-filer, selvom de tager tid at forberede, bliver ofte forsømt af travle vedligeholdere. Kan du finde et eksempel på en særlig beskrivende én? Bemærk: Der findes nogle [værktøjer til at hjælpe med at lave gode READMEs](https://www.makeareadme.com/), som du måske vil prøve.
### Opgave: Flet noget kode
Bidragsdokumenter hjælper folk med at bidrage til projektet. De forklarer, hvilke typer bidrag du leder efter, og hvordan processen fungerer. Bidragydere skal gennem en række trin for at kunne bidrage til dit repo på GitHub:
Bidragsdokumenter hjælper folk med at bidrage til projektet. De forklarer, hvilke typer bidrag du leder efter, og hvordan processen fungerer. Bidragydere skal gennem en række trin for at kunne bidrage til dit repo på GitHub:
1. **Fork dit repo**. Du vil sandsynligvis have, at folk _forker_ dit projekt. Forking betyder at oprette en kopi af dit repository på deres GitHub-profil.
1. **Clone**. Derfra vil de clone projektet til deres lokale maskine.
1. **Fork dit repo**. Du vil sandsynligvis have, at folk _forker_ dit projekt. At forke betyder at oprette en kopi af dit repository på deres GitHub-profil.
1. **Klon**. Derefter vil de klone projektet til deres lokale maskine.
1. **Opret en branch**. Du vil bede dem om at oprette en _branch_ til deres arbejde.
1. **Fokuser deres ændring på ét område**. Bed bidragydere om at koncentrere deres bidrag om én ting ad gangen - på den måde er chancerne for, at du kan _flette_ deres arbejde, højere. Forestil dig, at de skriver en fejlrettelse, tilføjer en ny funktion og opdaterer flere tests - hvad hvis du vil, eller kun kan implementere 2 ud af 3, eller 1 ud af 3 ændringer?
1. **Fokuser deres ændring på ét område**. Bed bidragydere om at koncentrere deres bidrag om én ting ad gangen - på den måde er chancerne for, at du kan _flette_ deres arbejde, højere. Forestil dig, at de skriver en fejlrettelse, tilføjer en ny funktion og opdaterer flere tests - hvad nu hvis du kun vil eller kan implementere 2 ud af 3 eller 1 ud af 3 ændringer?
✅ Forestil dig en situation, hvor branches er særligt kritiske for at skrive og levere god kode. Hvilke brugsscenarier kan du komme i tanke om?
> Bemærk, vær den forandring, du ønsker at se i verden, og opret branches til dit eget arbejde også. Enhver commit, du laver, vil blive lavet på den branch, du aktuelt er "checked out" til. Brug `git status` for at se, hvilken branch det er.
> Bemærk, vær den forandring, du ønsker at se i verden, og opret branches til dit eget arbejde også. Enhver commit, du laver, vil blive lavet på den branch, du i øjeblikket er "checket ud" til. Brug `git status` for at se, hvilken branch det er.
Lad os gennemgå en bidragsworkflow. Antag, at bidragyderen allerede har _forket_ og _clonet_ repoet, så de har et Git-repo klar til at blive arbejdet på, på deres lokale maskine:
Lad os gennemgå en bidragyder-arbejdsgang. Antag, at bidragyderen allerede har _forket_ og _klonet_ repoet, så de har et Git-repo klar til at blive arbejdet på, på deres lokale maskine:
1. **Opret en branch**. Brug kommandoen `git branch` til at oprette en branch, der vil indeholde de ændringer, de ønsker at bidrage med:
@ -235,7 +235,7 @@ Lad os gennemgå en bidragsworkflow. Antag, at bidragyderen allerede har _forket
Sørg for at give din commit et godt navn, for din egen skyld såvel som for vedligeholderen af det repo, du hjælper med.
1. **Kombiner dit arbejde med `main`-branch**. På et tidspunkt er du færdig med at arbejde, og du vil kombinere dit arbejde med det i `main`-branch. `main`-branch kan have ændret sig i mellemtiden, så sørg for først at opdatere den til det nyeste med følgende kommandoer:
1. **Kombiner dit arbejde med `main`-branchen**. På et tidspunkt er du færdig med at arbejde, og du vil kombinere dit arbejde med det i `main`-branchen. `Main`-branchen kan have ændret sig i mellemtiden, så sørg for først at opdatere den til den nyeste version med følgende kommandoer:
```bash
git switch main
@ -257,30 +257,30 @@ Lad os gennemgå en bidragsworkflow. Antag, at bidragyderen allerede har _forket
git push --set-upstream origin [branch-name]
```
Ovenstående kommando opretter branchen på dit forkede repo.
Kommandoen ovenfor opretter branchen på dit forkede repo.
1. **Åbn en PR**. Dernæst vil du åbne en PR. Det gør du ved at navigere til det forkede repo på GitHub. Du vil se en indikation på GitHub, hvor det spørger, om du vil oprette en ny PR, du klikker på det, og du bliver taget til en grænseflade, hvor du kan ændre commit-beskedens titel, give den en mere passende beskrivelse. Nu vil vedligeholderen af det repo, du forkede, se denne PR, og _fingers crossed_ vil de værdsætte og _flette_ din PR. Du er nu en bidragyder, yay :)
1. **Åbn en PR**. Dernæst vil du åbne en PR. Det gør du ved at navigere til det forkede repo på GitHub. Du vil se en indikation på GitHub, hvor det spørger, om du vil oprette en ny PR. Klik på det, og du bliver ført til en grænseflade, hvor du kan ændre commit-beskedens titel og give den en mere passende beskrivelse. Nu vil vedligeholderen af det repo, du forkede, se denne PR, og _fingrene krydsede_, de vil sætte pris på og _flette_ din PR. Du er nu en bidragyder, yay :)
1. **Ryd op**. Det anses for god praksis at _rydde op_, efter du har succesfuldt flettet en PR. Du vil rydde op i både din lokale branch og den branch, du pushede til GitHub. Først lad os slette den lokalt med følgende kommando:
1. **Ryd op**. Det anses for god praksis at _rydde op_, efter du har fået succes med at flette en PR. Du vil rydde op i både din lokale branch og den branch, du pushede til GitHub. Først skal du slette den lokalt med følgende kommando:
```bash
git branch -d [branch-name]
```
Sørg for at gå til GitHub-siden for den forkede repo næste gang og fjern den fjernede branch, du lige har skubbet til.
`Pull request` kan virke som et fjollet udtryk, fordi du egentlig ønsker at skubbe dine ændringer til projektet. Men vedligeholderen (projektets ejer) eller kerneholdet skal overveje dine ændringer, før de flettes med projektets "main"-branch, så du anmoder faktisk om en beslutning om ændringer fra en vedligeholder.
Sørg for at gå til GitHub-siden for det forkede repo og fjerne den remote branch, du lige har pushet til.
`Pull request` virker som et fjollet udtryk, fordi du egentlig ønsker at skubbe dine ændringer til projektet. Men vedligeholderen (projektets ejer) eller kerneholdet skal overveje dine ændringer, før de bliver flettet med projektets "main"-gren, så du anmoder faktisk om en beslutning om ændringen fra en vedligeholder.
En pull request er stedet, hvor man kan sammenligne og diskutere forskellene, der er introduceret på en branch, med anmeldelser, kommentarer, integrerede tests og mere. En god pull request følger nogenlunde de samme regler som en commit-besked. Du kan tilføje en reference til et issue i issue trackeren, når dit arbejde for eksempel løser et problem. Dette gøres ved at bruge et `#` efterfulgt af nummeret på dit issue. For eksempel `#97`.
En pull request er stedet, hvor man sammenligner og diskuterer forskellene, der er introduceret på en gren, med anmeldelser, kommentarer, integrerede tests og mere. En god pull request følger nogenlunde de samme regler som en commit-besked. Du kan tilføje en reference til et issue i issue tracker, når dit arbejde for eksempel løser et problem. Dette gøres ved at bruge et `#` efterfulgt af nummeret på dit issue. For eksempel `#97`.
🤞Kryds fingre for, at alle tjek passerer, og at projektets ejer(e) fletter dine ændringer ind i projektet🤞
🤞Kryds fingre for, at alle checks går igennem, og projektets ejer(e) fletter dine ændringer ind i projektet🤞
Opdater din nuværende lokale arbejdsbranch med alle nye commits fra den tilsvarende fjernbranch på GitHub:
Opdater din nuværende lokale arbejdsgren med alle nye commits fra den tilsvarende fjern-gren på GitHub:
`git pull`
## Sådan bidrager du til open source
Lad os først finde et repository (eller **repo**) på GitHub, der interesserer dig, og som du gerne vil bidrage med en ændring til. Du vil kopiere dets indhold til din maskine.
Lad os først finde et repository (eller **repo**) på GitHub, som interesserer dig, og som du gerne vil bidrage med en ændring til. Du vil gerne kopiere dets indhold til din maskine.
✅ En god måde at finde 'begynder-venlige' repos er at [søge efter tagget 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
@ -291,16 +291,16 @@ Der er flere måder at kopiere kode på. En måde er at "klone" indholdet af rep
Åbn din terminal og klon repositoryet sådan her:
`git clone https://github.com/ProjectURL`
For at arbejde på projektet skal du skifte til den rigtige mappe:
For at arbejde på projektet, skift til den rigtige mappe:
`cd ProjectURL`
Du kan også åbne hele projektet ved hjælp af [Codespaces](https://github.com/features/codespaces), GitHubs indbyggede kodeeditor / cloud-udviklingsmiljø, eller [GitHub Desktop](https://desktop.github.com/).
Endelig kan du downloade koden i en zip-mappe.
Til sidst kan du downloade koden i en zippet mappe.
### Et par flere interessante ting om GitHub
Du kan stjerne, overvåge og/eller "forke" ethvert offentligt repository på GitHub. Du kan finde dine stjernemarkerede repositories i menuen øverst til højre. Det er som at bogmærke, men for kode.
Du kan stjerne, overvåge og/eller "forke" ethvert offentligt repository på GitHub. Du kan finde dine stjernemarkerede repositories i drop-down-menuen øverst til højre. Det er som bogmærker, men for kode.
Projekter har en issue tracker, som oftest findes på GitHub under fanen "Issues", medmindre andet er angivet, hvor folk diskuterer problemer relateret til projektet. Og fanen Pull Requests er, hvor folk diskuterer og gennemgår ændringer, der er undervejs.
@ -312,10 +312,10 @@ Projekter kan også have diskussioner i fora, mailinglister eller chatkanaler so
## 🚀 Udfordring
Samarbejd med en ven om at arbejde på hinandens kode. Opret et projekt i fællesskab, fork kode, opret branches og flet ændringer.
Samarbejd med en ven om hinandens kode. Opret et projekt sammen, fork kode, opret grene og flet ændringer.
## Quiz efter forelæsning
[Quiz efter forelæsning](https://ff-quizzes.netlify.app/web/quiz/4)
[Quiz efter forelæsning](https://ff-quizzes.netlify.app/web/en/)
## Gennemgang & Selvstudie
@ -336,4 +336,4 @@ Gennemfør [kurset Første uge på GitHub](https://skills.github.com/#first-week
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e4cd5b1faed4adab5acf720f82798003",
"translation_date": "2025-08-26T22:19:44+00:00",
"original_hash": "f0c88c3e2cefa8952d356f802b1e47ca",
"translation_date": "2025-08-29T08:23:36+00:00",
"source_file": "1-getting-started-lessons/3-accessibility/README.md",
"language_code": "da"
}
@ -13,13 +13,13 @@ CO_OP_TRANSLATOR_METADATA:
> Sketchnote af [Tomomi Imura](https://twitter.com/girlie_mac)
## Quiz før lektionen
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/5)
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/)
> Webben er stærk på grund af dens universelle karakter. Adgang for alle, uanset handicap, er en essentiel del.
> Internettets styrke ligger i dets universalitet. Adgang for alle, uanset handicap, er en essentiel del.
>
> \- Sir Timothy Berners-Lee, W3C-direktør og opfinder af World Wide Web
Dette citat understreger perfekt vigtigheden af at skabe tilgængelige websites. En applikation, der ikke kan tilgås af alle, er pr. definition ekskluderende. Som webudviklere bør vi altid have tilgængelighed i tankerne. Ved at fokusere på dette fra starten er du godt på vej til at sikre, at alle kan til de sider, du skaber. I denne lektion vil du lære om værktøjer, der kan hjælpe dig med at sikre, at dine webressourcer er tilgængelige, og hvordan du bygger med tilgængelighed i tankerne.
Dette citat fremhæver perfekt vigtigheden af at skabe tilgængelige hjemmesider. En applikation, der ikke kan tilgås af alle, er per definition ekskluderende. Som webudviklere bør vi altid have tilgængelighed i tankerne. Ved at fokusere på dette fra starten er du godt på vej til at sikre, at alle kan få adgang til de sider, du skaber. I denne lektion lærer du om værktøjer, der kan hjælpe dig med at sikre, at dine webressourcer er tilgængelige, og hvordan du bygger med tilgængelighed for øje.
> Du kan tage denne lektion på [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/accessibility/?WT.mc_id=academic-77807-sagibbon)!
@ -29,99 +29,99 @@ Dette citat understreger perfekt vigtigheden af at skabe tilgængelige websites.
Et af de mest kendte tilgængelighedsværktøjer er skærmlæsere.
[Skærmlæsere](https://en.wikipedia.org/wiki/Screen_reader) er almindeligt anvendte klienter af personer med synshandicap. Når vi bruger tid på at sikre, at en browser korrekt formidler den information, vi ønsker at dele, skal vi også sikre, at en skærmlæser gør det samme.
[Skærmlæsere](https://en.wikipedia.org/wiki/Screen_reader) bruges ofte af personer med synsnedsættelser. Når vi bruger tid på at sikre, at en browser korrekt formidler den information, vi ønsker at dele, skal vi også sikre, at en skærmlæser gør det samme.
En skærmlæser vil grundlæggende læse en side fra top til bund højt. Hvis din side kun består af tekst, vil læseren formidle informationen på en lignende måde som en browser. Websider er dog sjældent kun tekst; de indeholder links, grafik, farver og andre visuelle komponenter. Der skal udvises omhu for at sikre, at denne information læses korrekt af en skærmlæser.
En skærmlæser vil i sin enkleste form læse en side højt fra top til bund. Hvis din side kun består af tekst, vil læseren formidle informationen på en lignende måde som en browser. Men websteder er sjældent kun tekst; de indeholder links, grafik, farver og andre visuelle komponenter. Der skal tages hensyn til, at denne information læses korrekt af en skærmlæser.
Alle webudviklere bør sætte sig ind i, hvordan en skærmlæser fungerer. Som nævnt ovenfor er det den klient, dine brugere vil benytte. På samme måde som du er bekendt med, hvordan en browser fungerer, bør du lære, hvordan en skærmlæser fungerer. Heldigvis er skærmlæsere indbygget i de fleste operativsystemer.
Alle webudviklere bør sætte sig ind i, hvordan en skærmlæser fungerer. Som nævnt ovenfor er det det værktøj, dine brugere vil benytte. På samme måde som du kender til, hvordan en browser fungerer, bør du lære, hvordan en skærmlæser fungerer. Heldigvis er skærmlæsere indbygget i de fleste operativsystemer.
Nogle browsere har også indbyggede værktøjer og udvidelser, der kan læse tekst højt eller endda give nogle grundlæggende navigationsfunktioner, såsom [disse tilgængelighedsorienterede Edge-browserværktøjer](https://support.microsoft.com/help/4000734/microsoft-edge-accessibility-features). Disse er også vigtige tilgængelighedsværktøjer, men fungerer meget anderledes end skærmlæsere og bør ikke forveksles med testværktøjer til skærmlæsere.
Nogle browsere har også indbyggede værktøjer og udvidelser, der kan læse tekst højt eller give nogle grundlæggende navigationsfunktioner, som f.eks. [disse tilgængelighedsfokuserede Edge-browserværktøjer](https://support.microsoft.com/help/4000734/microsoft-edge-accessibility-features). Disse er også vigtige tilgængelighedsværktøjer, men fungerer meget anderledes end skærmlæsere og bør ikke forveksles med testværktøjer til skærmlæsere.
✅ Prøv en skærmlæser og browsertekstlæser. På Windows er [Narrator](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon) inkluderet som standard, og [JAWS](https://webaim.org/articles/jaws/) og [NVDA](https://www.nvaccess.org/about-nvda/) kan også installeres. På macOS og iOS er [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10) installeret som standard.
✅ Prøv en skærmlæser og en browsertekstlæser. På Windows er [Narrator](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon) inkluderet som standard, og [JAWS](https://webaim.org/articles/jaws/) og [NVDA](https://www.nvaccess.org/about-nvda/) kan også installeres. På macOS og iOS er [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10) installeret som standard.
### Zoom
Et andet værktøj, der ofte bruges af personer med synshandicap, er zoom. Den mest grundlæggende type zoom er statisk zoom, som styres via `Control + plus-tegn (+)` eller ved at reducere skærmopløsningen. Denne type zoom får hele siden til at ændre størrelse, så det er vigtigt at bruge [responsivt design](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Responsive_Design) for at give en god brugeroplevelse ved øgede zoomniveauer.
Et andet værktøj, der ofte bruges af personer med synsnedsættelser, er zoom. Den mest grundlæggende form for zoom er statisk zoom, som styres med `Control + plus-tegn (+)` eller ved at reducere skærmopløsningen. Denne type zoom får hele siden til at ændre størrelse, så det er vigtigt at bruge [responsivt design](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Responsive_Design) for at give en god brugeroplevelse ved øgede zoomniveauer.
En anden type zoom bruger specialiseret software til at forstørre et område af skærmen og panorere, meget ligesom at bruge et rigtigt forstørrelsesglas. På Windows er [Magnifier](https://support.microsoft.com/windows/use-magnifier-to-make-things-on-the-screen-easier-to-see-414948ba-8b1c-d3bd-8615-0e5e32204198) indbygget, og [ZoomText](https://www.freedomscientific.com/training/zoomtext/getting-started/) er en tredjeparts forstørrelsessoftware med flere funktioner og en større brugerbase. Både macOS og iOS har en indbygget forstørrelsessoftware kaldet [Zoom](https://www.apple.com/accessibility/mac/vision/).
En anden type zoom bruger specialiseret software til at forstørre et område af skærmen og panorere, ligesom man bruger et forstørrelsesglas. På Windows er [Forstørrelsesglas](https://support.microsoft.com/windows/use-magnifier-to-make-things-on-the-screen-easier-to-see-414948ba-8b1c-d3bd-8615-0e5e32204198) indbygget, og [ZoomText](https://www.freedomscientific.com/training/zoomtext/getting-started/) er en tredjeparts forstørrelsessoftware med flere funktioner og en større brugerbase. Både macOS og iOS har en indbygget forstørrelsessoftware kaldet [Zoom](https://www.apple.com/accessibility/mac/vision/).
### Kontrastkontroller
### Kontrasttestere
Farver på websites skal vælges omhyggeligt for at imødekomme behovene hos farveblinde brugere eller personer, der har svært ved at se farver med lav kontrast.
Farver på websteder skal vælges omhyggeligt for at imødekomme behovene hos farveblinde brugere eller personer, der har svært ved at se farver med lav kontrast.
✅ Test et website, du godt kan lide, for farvebrug med en browserudvidelse som [WCAG's farvekontrol](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US&WT.mc_id=academic-77807-sagibbon). Hvad lærer du?
✅ Test et websted, du godt kan lide, for farvebrug med en browserudvidelse som [WCAG's farvetester](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US&WT.mc_id=academic-77807-sagibbon). Hvad lærer du?
### Lighthouse
I udviklerværktøjsområdet i din browser finder du Lighthouse-værktøjet. Dette værktøj er vigtigt for at få et første indblik i tilgængeligheden (samt andre analyser) af et website. Selvom det er vigtigt ikke udelukkende at stole på Lighthouse, er en score på 100 % meget nyttig som baseline.
I udviklerværktøjsområdet i din browser finder du Lighthouse-værktøjet. Dette værktøj er vigtigt for at få et første indtryk af tilgængeligheden (samt andre analyser) af et websted. Selvom det er vigtigt ikke at stole udelukkende på Lighthouse, er en score på 100 % meget nyttig som udgangspunkt.
✅ Find Lighthouse i din browsers udviklerværktøjspanel og kør en analyse på et vilkårligt site. Hvad opdager du?
✅ Find Lighthouse i din browsers udviklerværktøjspanel, og kør en analyse på et vilkårligt websted. Hvad opdager du?
## Design med tilgængelighed i tankerne
## Design med tilgængelighed for øje
Tilgængelighed er et relativt stort emne. For at hjælpe dig er der mange ressourcer tilgængelige.
- [Accessible U - University of Minnesota](https://accessibility.umn.edu/your-role/web-developers)
Selvom vi ikke vil kunne dække alle aspekter af at skabe tilgængelige sites, er nedenfor nogle af de grundlæggende principper, du vil implementere. At designe en tilgængelig side fra starten er **altid** lettere end at gå tilbage til en eksisterende side for at gøre den tilgængelig.
Selvom vi ikke kan dække alle aspekter af at skabe tilgængelige sider, er nedenfor nogle af de grundlæggende principper, du bør implementere. At designe en tilgængelig side fra starten er **altid** lettere end at gå tilbage til en eksisterende side for at gøre den tilgængelig.
## Gode visuelle principper
### Farvesikre paletter
Folk ser verden på forskellige måder, og dette inkluderer farver. Når du vælger et farveskema til dit site, bør du sikre, at det er tilgængeligt for alle. Et fantastisk [værktøj til at generere farvepaletter er Color Safe](http://colorsafe.co/).
Folk ser verden på forskellige måder, og det inkluderer farver. Når du vælger et farveskema til dit websted, bør du sikre, at det er tilgængeligt for alle. Et fantastisk [værktøj til at generere farvepaletter er Color Safe](http://colorsafe.co/).
✅ Identificer et website, der er meget problematisk i sin brug af farver. Hvorfor?
✅ Identificer et websted, der er meget problematisk i dets brug af farver. Hvorfor?
### Brug korrekt HTML
Med CSS og JavaScript er det muligt at få ethvert element til at ligne enhver type kontrol. `<span>` kunne bruges til at skabe en `<button>`, og `<b>` kunne blive til et hyperlink. Selvom dette måske anses for lettere at style, formidler det intet til en skærmlæser. Brug den passende HTML, når du opretter kontroller på en side. Hvis du vil have et hyperlink, skal du bruge `<a>`. At bruge den rigtige HTML til den rigtige kontrol kaldes at gøre brug af Semantisk HTML.
✅ Gå til et vilkårligt website og se, om designerne og udviklerne bruger HTML korrekt. Kan du finde en knap, der burde være et link? Tip: højreklik og vælg 'Vis sidekilde' i din browser for at se den underliggende kode.
✅ Gå til et vilkårligt websted og se, om designerne og udviklerne bruger HTML korrekt. Kan du finde en knap, der burde være et link? Tip: højreklik og vælg 'Vis sidekilde' i din browser for at se den underliggende kode.
### Opret en beskrivende overskrifthierarki
### Skab en beskrivende overskrifthierarki
Brugere af skærmlæsere [afhænger meget af overskrifter](https://webaim.org/projects/screenreadersurvey8/#finding) for at finde information og navigere gennem en side. At skrive beskrivende overskriftsindhold og bruge semantiske overskriftstags er vigtigt for at skabe et let navigerbart site for brugere af skærmlæsere.
Brugere af skærmlæsere [afhænger meget af overskrifter](https://webaim.org/projects/screenreadersurvey8/#finding) for at finde information og navigere gennem en side. At skrive beskrivende overskriftsindhold og bruge semantiske overskriftstags er vigtigt for at skabe et let navigerbart websted for brugere af skærmlæsere.
### Brug gode visuelle ledetråde
CSS giver fuld kontrol over udseendet af ethvert element på en side. Du kan oprette tekstbokse uden en ramme eller hyperlinks uden en understregning. Desværre kan fjernelse af disse ledetråde gøre det mere udfordrende for nogen, der er afhængige af dem, at genkende typen af kontrol.
CSS giver fuld kontrol over udseendet af ethvert element på en side. Du kan skabe tekstbokse uden en ramme eller hyperlinks uden en understregning. Desværre kan fjernelse af disse ledetråde gøre det mere udfordrende for nogen, der er afhængige af dem, at genkende typen af kontrol.
## Vigtigheden af linktekst
Hyperlinks er centrale for at navigere på nettet. Derfor er det vigtigt at sikre, at en skærmlæser korrekt kan læse links, så alle brugere kan navigere på dit site.
Hyperlinks er kernen i at navigere på nettet. Derfor er det vigtigt at sikre, at en skærmlæser korrekt kan læse links, så alle brugere kan navigere på dit websted.
### Skærmlæsere og links
Som forventet læser skærmlæsere linktekst på samme måde, som de ville læse enhver anden tekst på siden. Med dette i tankerne kan teksten nedenfor virke helt acceptabel.
> Den lille pingvin, også kendt som fe-pingvinen, er den mindste pingvin i verden. [Klik her](https://en.wikipedia.org/wiki/Little_penguin) for mere information.
> Den lille pingvin, nogle gange kendt som eventyrpingvinen, er verdens mindste pingvin. [Klik her](https://en.wikipedia.org/wiki/Little_penguin) for mere information.
> Den lille pingvin, også kendt som fe-pingvinen, er den mindste pingvin i verden. Besøg https://en.wikipedia.org/wiki/Little_penguin for mere information.
> Den lille pingvin, nogle gange kendt som eventyrpingvinen, er verdens mindste pingvin. Besøg https://en.wikipedia.org/wiki/Little_penguin for mere information.
> **NOTE** Som du snart vil læse, bør du **aldrig** oprette links, der ser ud som ovenstående.
Husk, skærmlæsere er en anden grænseflade end browsere med et andet sæt funktioner.
Husk, at skærmlæsere er en anden grænseflade end browsere med et andet sæt funktioner.
### Problemet med at bruge URL'en
Skærmlæsere læser teksten. Hvis en URL vises i teksten, vil skærmlæseren læse URL'en. Generelt formidler URL'en ikke meningsfuld information og kan lyde irriterende. Du har måske oplevet dette, hvis din telefon nogensinde har læst en tekstbesked med en URL højt.
Skærmlæsere læser teksten. Hvis en URL vises i teksten, vil skærmlæseren læse URL'en. Generelt set formidler URL'en ikke meningsfuld information og kan lyde irriterende. Du har måske oplevet dette, hvis din telefon nogensinde har læst en tekstbesked med en URL højt.
### Problemet med "klik her"
Skærmlæsere har også evnen til kun at læse hyperlinks på en side, meget ligesom en seende person ville scanne en side for links. Hvis linkteksten altid er "klik her", vil brugeren kun høre "klik her, klik her, klik her, klik her, klik her, ..." Alle links er nu uadskillelige fra hinanden.
Skærmlæsere har også evnen til kun at læse hyperlinks på en side, på samme måde som en seende person ville scanne en side for links. Hvis linkteksten altid er "klik her", vil brugeren kun høre "klik her, klik her, klik her, klik her, klik her, ..." Alle links bliver nu uadskillelige fra hinanden.
### God linktekst
God linktekst beskriver kort, hvad der er på den anden side af linket. I det ovenstående eksempel, der handler om små pingviner, er linket til Wikipedia-siden om arten. Udtrykket *små pingviner* ville være perfekt som linktekst, da det gør det klart, hvad man vil lære om, hvis man klikker på linket - små pingviner.
God linktekst beskriver kort, hvad der er på den anden side af linket. I det ovenstående eksempel om små pingviner linker teksten til Wikipedia-siden om arten. Udtrykket *små pingviner* ville være perfekt som linktekst, da det gør det klart, hvad nogen vil lære om, hvis de klikker på linket - små pingviner.
> Den [lille pingvin](https://en.wikipedia.org/wiki/Little_penguin), også kendt som fe-pingvinen, er den mindste pingvin i verden.
> Den [lille pingvin](https://en.wikipedia.org/wiki/Little_penguin), nogle gange kendt som eventyrpingvinen, er verdens mindste pingvin.
✅ Surf på nettet i et par minutter for at finde sider, der bruger uklare linkstrategier. Sammenlign dem med andre, bedre linkede sites. Hvad lærer du?
✅ Surf på nettet i et par minutter for at finde sider, der bruger uklare linkstrategier. Sammenlign dem med andre, bedre linkede sider. Hvad lærer du?
#### Noter om søgemaskiner
Som en ekstra bonus ved at sikre, at dit site er tilgængeligt for alle, hjælper du søgemaskiner med at navigere på dit site. Søgemaskiner bruger linktekst til at lære emnerne på sider. Så ved at bruge god linktekst hjælper du alle!
Som en ekstra bonus ved at sikre, at dit websted er tilgængeligt for alle, hjælper du også søgemaskiner med at navigere på dit websted. Søgemaskiner bruger linktekst til at lære emnerne på sider. Så ved at bruge god linktekst hjælper du alle!
### ARIA
@ -132,11 +132,11 @@ Forestil dig følgende side:
| Widget | [Beskrivelse](../../../../1-getting-started-lessons/3-accessibility/') | [Bestil](../../../../1-getting-started-lessons/3-accessibility/') |
| Super widget | [Beskrivelse](../../../../1-getting-started-lessons/3-accessibility/') | [Bestil](../../../../1-getting-started-lessons/3-accessibility/') |
I dette eksempel giver det mening for en browserbruger at gentage teksten beskrivelse og bestil. Men en skærmlæserbruger ville kun høre ordene *beskrivelse* og *bestil* gentaget uden kontekst.
I dette eksempel giver det mening for en browserbruger at gentage teksten "beskrivelse" og "bestil". Men for en skærmlæserbruger vil ordene *beskrivelse* og *bestil* kun blive gentaget uden kontekst.
For at understøtte disse typer scenarier understøtter HTML et sæt attributter kendt som [Accessible Rich Internet Applications (ARIA)](https://developer.mozilla.org/docs/Web/Accessibility/ARIA). Disse attributter giver dig mulighed for at give yderligere information til skærmlæsere.
> **NOTE**: Som med mange aspekter af HTML kan browser- og skærmlæserstøtte variere. Men de fleste mainstream-klienter understøtter ARIA-attributter.
> **NOTE**: Som med mange aspekter af HTML kan browser- og skærmlæserstøtte variere. Dog understøtter de fleste mainstream-klienter ARIA-attributter.
Du kan bruge `aria-label` til at beskrive linket, når sidens format ikke tillader det. Beskrivelsen for widget kunne sættes som
@ -144,7 +144,7 @@ Du kan bruge `aria-label` til at beskrive linket, når sidens format ikke tillad
<a href="#" aria-label="Widget description">description</a>
```
✅ Generelt overgår brugen af Semantisk markup som beskrevet ovenfor brugen af ARIA, men nogle gange er der ingen semantisk ækvivalent for forskellige HTML-widgets. Et godt eksempel er et træ. Der er ingen HTML-ækvivalent for et træ, så du identificerer den generiske `<div>` for dette element med en korrekt rolle og ARIA-værdier. [MDN-dokumentationen om ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) indeholder mere nyttig information.
✅ Generelt overgår brugen af semantisk markup som beskrevet ovenfor brugen af ARIA, men nogle gange findes der ikke en semantisk ækvivalent for forskellige HTML-widgets. Et godt eksempel er et træ. Der findes ingen HTML-ækvivalent for et træ, så du identificerer den generiske `<div>` for dette element med en passende rolle og ARIA-værdier. [MDN-dokumentationen om ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) indeholder mere nyttig information.
```html
<h2 id="tree-label">File Viewer</h2>
@ -155,20 +155,20 @@ Du kan bruge `aria-label` til at beskrive linket, når sidens format ikke tillad
## Billeder
Det siger sig selv, at skærmlæsere ikke automatisk kan læse, hvad der er i et billede. At sikre, at billeder er tilgængelige, kræver ikke meget arbejde - det er det, `alt`-attributten handler om. Alle meningsfulde billeder bør have en `alt`-attribut, der beskriver, hvad de er.
Det siger sig selv, at skærmlæsere ikke automatisk kan læse, hvad der er i et billede. At sikre, at billeder er tilgængelige, kræver ikke meget arbejde - det er, hvad `alt`-attributten handler om. Alle meningsfulde billeder bør have en `alt`-beskrivelse, der forklarer, hvad de er.
Billeder, der kun er dekorative, bør have deres `alt`-attribut sat til en tom streng: `alt=""`. Dette forhindrer skærmlæsere i unødvendigt at annoncere det dekorative billede.
✅ Som du måske forventer, kan søgemaskiner heller ikke forstå, hvad der er i et billede. De bruger også alt-tekst. Så igen giver det ekstra fordele at sikre, at din side er tilgængelig!
✅ Som du måske forventer, kan søgemaskiner heller ikke forstå, hvad der er i et billede. De bruger også alt-tekst. Så endnu en gang giver det at sikre, at din side er tilgængelig, ekstra fordele!
## Tastaturet
Nogle brugere er ude af stand til at bruge en mus eller trackpad og er i stedet afhængige af tastaturinteraktioner for at tabbe fra et element til det næste. Det er vigtigt, at dit website præsenterer dit indhold i en logisk rækkefølge, så en tastaturbruger kan til hvert interaktivt element, mens de bevæger sig ned gennem dokumentet. Hvis du bygger dine websider med semantisk markup og bruger CSS til at style deres visuelle layout, bør dit site være tastaturnavigerbart, men det er vigtigt at teste dette aspekt manuelt. Læs mere om [strategier for tastaturnavigation](https://webaim.org/techniques/keyboard/).
Nogle brugere er ude af stand til at bruge en mus eller en touchpad og er i stedet afhængige af tastaturinteraktioner for at navigere fra et element til det næste. Det er vigtigt, at dit websted præsenterer dit indhold i en logisk rækkefølge, så en tastaturbruger kan få adgang til hvert interaktivt element, mens de bevæger sig ned gennem dokumentet. Hvis du bygger dine websider med semantisk markup og bruger CSS til at style deres visuelle layout, bør dit websted være tastaturnavigerbart, men det er vigtigt at teste dette aspekt manuelt. Læs mere om [tastaturnavigationsstrategier](https://webaim.org/techniques/keyboard/).
✅ Gå til et vilkårligt website og prøv at navigere gennem det ved kun at bruge dit tastatur. Hvad fungerer, hvad fungerer ikke? Hvorfor?
✅ Gå til et vilkårligt websted og prøv at navigere gennem det kun ved hjælp af dit tastatur. Hvad fungerer, og hvad fungerer ikke? Hvorfor?
## Opsummering
En web, der kun er tilgængelig for nogle, er ikke en ægte 'world-wide web'. Den bedste måde at sikre, at de sites, du skaber, er tilgængelige, er at inkorporere tilgængelighedsbedste praksis fra starten. Selvom der er ekstra trin involveret, vil det at integrere disse færdigheder i din arbejdsgang nu betyde, at alle sider, du skaber, vil være tilgængelige.
Et web, der kun er tilgængeligt for nogle, er ikke et ægte 'world-wide web'. Den bedste måde at sikre, at de sider, du skaber, er tilgængelige, er at inkorporere tilgængelighedsprincipper fra starten. Selvom der er ekstra trin involveret, vil det at integrere disse færdigheder i din arbejdsgang nu betyde, at alle sider, du skaber, vil være tilgængelige.
---
@ -220,25 +220,25 @@ Tag denne HTML og omskriv den, så den er så tilgængelig som muligt, givet de
<p class="nav-item nav-item-bull"><a href="../semantic">Semantic Example</a></p>
</div>
</div>
<p class="footer-copyright">&copy; 2016 Instrument</span>
<p class="footer-copyright">&copy; 2016 Instrument</p>
</div>
</body>
</html>
```
## Quiz efter lektionen
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/6)
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/en/)
## Gennemgang & Selvstudie
Mange regeringer har love om krav til tilgængelighed. Undersøg tilgængelighedslovgivningen i dit hjemland. Hvad er dækket, og hvad er ikke? Et eksempel er [denne regeringswebside](https://accessibility.blog.gov.uk/).
Mange regeringer har love om tilgængelighedskrav. Undersøg dit hjemlands love om tilgængelighed. Hvad er dækket, og hvad er ikke? Et eksempel er [denne regeringswebside](https://accessibility.blog.gov.uk/).
## Opgave
[Analyser en ikke-tilgængelig webside](assignment.md)
Credits: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) af Instrument
Kreditering: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) af Instrument
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,19 +1,19 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "fc6aef8ecfdd5b0ad2afa6e6ba52bfde",
"translation_date": "2025-08-26T21:49:25+00:00",
"original_hash": "b95fdd8310ef467305015ece1b0f9411",
"translation_date": "2025-08-29T08:17:07+00:00",
"source_file": "2-js-basics/1-data-types/README.md",
"language_code": "da"
}
-->
# JavaScript Grundlæggende: Datatyper
![JavaScript Grundlæggende - Datatyper](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.da.png)
![JavaScript Basics - Datatyper](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.da.png)
> Sketchnote af [Tomomi Imura](https://twitter.com/girlie_mac)
## Quiz før lektionen
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/7)
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/)
Denne lektion dækker det grundlæggende i JavaScript, sproget der giver interaktivitet på nettet.
@ -26,15 +26,16 @@ Denne lektion dækker det grundlæggende i JavaScript, sproget der giver interak
> 🎥 Klik på billederne ovenfor for videoer om variabler og datatyper
Lad os starte med variabler og de datatyper, der fylder dem!
## Variabler
Variabler gemmer værdier, der kan bruges og ændres gennem din kode.
Variabler gemmer værdier, som kan bruges og ændres i din kode.
At oprette og **deklarere** en variabel har følgende syntaks **[nøgleord] [navn]**. Det består af to dele:
- **Nøgleord**. Nøgleord kan være `let` eller `var`.
✅ Nøgleordet `let` blev introduceret i ES6 og giver din variabel en såkaldt _blokscope_. Det anbefales, at du bruger `let` frem for `var`. Vi vil dække blokscopes mere detaljeret i fremtidige dele.
✅ Nøgleordet `let` blev introduceret i ES6 og giver din variabel en såkaldt _blokscope_. Det anbefales, at du bruger `let` frem for `var`. Vi vil dække blokscope mere detaljeret i fremtidige dele.
- **Variabelnavnet**, dette er et navn, du selv vælger.
### Opgave - arbejde med variabler
@ -53,7 +54,7 @@ At oprette og **deklarere** en variabel har følgende syntaks **[nøgleord] [nav
myVariable = 123;
```
> Bemærk: brugen af `=` i denne lektion betyder, at vi bruger en "tildelingsoperator", der bruges til at sætte en værdi til en variabel. Det angiver ikke lighed.
> Bemærk: brugen af `=` i denne lektion betyder, at vi bruger en "tildelingsoperator", som bruges til at sætte en værdi til en variabel. Det angiver ikke lighed.
`myVariable` er nu blevet *initialiseret* med værdien 123.
@ -73,11 +74,11 @@ At oprette og **deklarere** en variabel har følgende syntaks **[nøgleord] [nav
Når en variabel er deklareret, kan du ændre dens værdi på ethvert tidspunkt i din kode med operatoren `=` og den nye værdi.
✅ Prøv det! Du kan skrive JavaScript direkte i din browser. Åbn et browservindue og navigér til Developer Tools. I konsollen finder du en prompt; skriv `let myVariable = 123`, tryk retur, og skriv derefter `myVariable`. Hvad sker der? Bemærk, du vil lære mere om disse begreber i efterfølgende lektioner.
✅ Prøv det! Du kan skrive JavaScript direkte i din browser. Åbn et browservindue og navigér til Developer Tools. I konsollen finder du en prompt; skriv `let myVariable = 123`, tryk return, og skriv derefter `myVariable`. Hvad sker der? Bemærk, du vil lære mere om disse begreber i efterfølgende lektioner.
## Konstanter
Deklaration og initialisering af en konstant følger de samme koncepter som en variabel, med undtagelse af nøgleordet `const`. Konstanter deklareres typisk med store bogstaver.
Deklaration og initialisering af en konstant følger de samme principper som en variabel, med undtagelse af nøgleordet `const`. Konstanter deklareres typisk med store bogstaver.
```javascript
const MY_VARIABLE = 123;
@ -114,9 +115,9 @@ Konstanter ligner variabler, med to undtagelser:
## Datatyper
Variabler kan gemme mange forskellige typer værdier, som tal og tekst. Disse forskellige typer værdier er kendt som **datatyper**. Datatyper er en vigtig del af softwareudvikling, fordi de hjælper udviklere med at træffe beslutninger om, hvordan koden skal skrives, og hvordan softwaren skal re. Desuden har nogle datatyper unikke funktioner, der hjælper med at transformere eller udtrække yderligere information fra en værdi.
Variabler kan gemme mange forskellige typer værdier, som tal og tekst. Disse forskellige typer værdier kaldes **datatyper**. Datatyper er en vigtig del af softwareudvikling, fordi de hjælper udviklere med at træffe beslutninger om, hvordan koden skal skrives, og hvordan softwaren skal fungere. Desuden har nogle datatyper unikke funktioner, der hjælper med at transformere eller udtrække yderligere information fra en værdi.
✅ Datatyper kaldes også JavaScript dataprimitiver, da de er de laveste niveau datatyper, der leveres af sproget. Der er 7 primitive datatyper: string, number, bigint, boolean, undefined, null og symbol. Tag et øjeblik til at visualisere, hvad hver af disse primitiver kan repræsentere. Hvad er en `zebra`? Hvad med `0`? `true`?
✅ Datatyper kaldes også JavaScript-dataprimitiver, da de er de mest grundlæggende datatyper, som sproget tilbyder. Der er 7 primitive datatyper: string, number, bigint, boolean, undefined, null og symbol. Tag et øjeblik til at visualisere, hvad hver af disse primitiver kan repræsentere. Hvad er en `zebra`? Hvad med `0`? `true`?
### Tal
@ -126,7 +127,7 @@ I det foregående afsnit var værdien af `myVariable` en tal-datatype.
Variabler kan gemme alle typer tal, inklusive decimaler eller negative tal. Tal kan også bruges med aritmetiske operatorer, som dækkes i [næste afsnit](../../../../2-js-basics/1-data-types).
### Aritmetiske Operatorer
### Aritmetiske operatorer
Der er flere typer operatorer, der kan bruges til at udføre aritmetiske funktioner, og nogle er listet her:
@ -150,11 +151,11 @@ Strings er sæt af tegn, der er placeret mellem enkelt- eller dobbeltanførselst
Husk at bruge anførselstegn, når du skriver en string, ellers vil JavaScript antage, at det er et variabelnavn.
### Formatering af Strings
### Formatering af strings
Strings er tekstuelle og vil kræve formatering fra tid til anden.
For at **konkatenere** to eller flere strings, eller sætte dem sammen, brug operatoren `+`.
For at **konkatenere** to eller flere strings, eller sætte dem sammen, bruges operatoren `+`.
```javascript
let myString1 = "Hello";
@ -168,7 +169,7 @@ myString1 + ", " + myString2 + "!"; //Hello, World!
✅ Hvorfor er `1 + 1 = 2` i JavaScript, men `'1' + '1' = 11?` Tænk over det. Hvad med `'1' + 1`?
**Template literals** er en anden måde at formatere strings på, undtagen i stedet for anførselstegn bruges backtick. Alt, der ikke er almindelig tekst, skal placeres inde i pladsholdere `${ }`. Dette inkluderer eventuelle variabler, der kan være strings.
**Template literals** er en anden måde at formatere strings på, bortset fra at der bruges backticks i stedet for anførselstegn. Alt, der ikke er almindelig tekst, skal placeres i placeholders `${ }`. Dette inkluderer eventuelle variabler, der kan være strings.
```javascript
let myString1 = "Hello";
@ -189,16 +190,16 @@ Booleans kan kun have to værdier: `true` eller `false`. Booleans kan hjælpe me
- `let myTrueBool = true`
- `let myFalseBool = false`
✅ En variabel kan betragtes som 'truthy', hvis den evalueres til en boolean `true`. Interessant nok er [alle værdier truthy, medmindre de er defineret som falsy](https://developer.mozilla.org/docs/Glossary/Truthy) i JavaScript.
✅ En variabel kan betragtes som 'truthy', hvis den evalueres til en boolean `true`. Interessant nok er [alle værdier i JavaScript truthy, medmindre de er defineret som falsy](https://developer.mozilla.org/docs/Glossary/Truthy).
---
## 🚀 Udfordring
JavaScript er berygtet for sine overraskende måder at håndtere datatyper på fra tid til anden. Undersøg lidt om disse 'gotchas'. For eksempel: case sensitivity kan drille! Prøv dette i din konsol: `let age = 1; let Age = 2; age == Age` (resulterer i `false` -- hvorfor?). Hvilke andre gotchas kan du finde?
JavaScript er berygtet for sine overraskende måder at håndtere datatyper på. Undersøg lidt om disse 'gotchas'. For eksempel: case sensitivity kan drille! Prøv dette i din konsol: `let age = 1; let Age = 2; age == Age` (resulterer i `false` -- hvorfor?). Hvilke andre gotchas kan du finde?
## Quiz efter lektionen
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/8)
[Quiz efter lektionen](https://ff-quizzes.netlify.app)
## Gennemgang & Selvstudie
@ -211,4 +212,4 @@ Tag et kig på [denne liste over JavaScript-øvelser](https://css-tricks.com/sni
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "b4612bbb9ace984f374fcc80e3e035ad",
"translation_date": "2025-08-26T21:44:12+00:00",
"original_hash": "92e136090efc4341b1d51c37924c1802",
"translation_date": "2025-08-29T08:15:38+00:00",
"source_file": "2-js-basics/2-functions-methods/README.md",
"language_code": "da"
}
@ -12,12 +12,12 @@ CO_OP_TRANSLATOR_METADATA:
![JavaScript Basics - Functions](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b7605c36330ac42eeb5cd8ed02bcdd60fdac778174d6cb865.da.png)
> Sketchnote af [Tomomi Imura](https://twitter.com/girlie_mac)
## Quiz før lektionen
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/9)
## Quiz før forelæsning
[Quiz før forelæsning](https://ff-quizzes.netlify.app)
Når vi tænker på at skrive kode, vil vi altid sikre, at vores kode er læsbar. Selvom det kan lyde kontraintuitivt, bliver kode læst mange flere gange, end den bliver skrevet. Et af de vigtigste værktøjer i en udviklers værktøjskasse for at sikre vedligeholdelig kode er **funktionen**.
Når vi tænker på at skrive kode, vil vi altid sikre os, at vores kode er læsbar. Selvom det kan lyde kontraintuitivt, bliver kode læst mange flere gange, end den bliver skrevet. Et af de vigtigste værktøjer i en udviklers værktøjskasse for at sikre vedligeholdelig kode er **funktionen**.
[![Metoder og Funktioner](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Metoder og Funktioner")
[![Methods and Functions](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Methods and Functions")
> 🎥 Klik på billedet ovenfor for en video om metoder og funktioner.
@ -25,9 +25,9 @@ Når vi tænker på at skrive kode, vil vi altid sikre, at vores kode er læsbar
## Funktioner
Grundlæggende er en funktion en blok af kode, som vi kan udføre efter behov. Dette er perfekt til scenarier, hvor vi skal udføre den samme opgave flere gange; i stedet for at duplikere logikken flere steder (hvilket ville gøre det svært at opdatere senere), kan vi centralisere den ét sted og kalde den, når vi har brug for operationen udført - du kan endda kalde funktioner fra andre funktioner!
I sin kerne er en funktion en blok af kode, som vi kan udføre efter behov. Dette er perfekt til scenarier, hvor vi skal udføre den samme opgave flere gange; i stedet for at duplikere logikken flere steder (hvilket ville gøre det svært at opdatere senere), kan vi centralisere den ét sted og kalde den, når vi har brug for operationen udført - du kan endda kalde funktioner fra andre funktioner!
Lige så vigtigt er evnen til at navngive en funktion. Selvom det kan virke trivielt, giver navnet en hurtig måde at dokumentere en sektion af kode. Du kan tænke på det som en etiket på en knap. Hvis jeg klikker på en knap, der sr "Annuller timer", ved jeg, at den vil stoppe uret.
Lige så vigtigt er evnen til at navngive en funktion. Selvom det måske virker trivielt, giver navnet en hurtig måde at dokumentere en sektion af kode. Du kan tænke på det som en etiket på en knap. Hvis jeg klikker på en knap, der siger "Annuller timer", ved jeg, at den vil stoppe uret.
## Oprettelse og kald af en funktion
@ -66,7 +66,7 @@ Der er nogle få bedste praksis at huske på, når du opretter funktioner:
## Overførsel af information til en funktion
For at gøre en funktion mere genanvendelig vil du ofte gerne overføre information til den. Hvis vi ser på vores `displayGreeting`-eksempel ovenfor, vil den kun vise **Hello, world!**. Ikke den mest nyttige funktion, man kunne oprette. Hvis vi vil gøre den lidt mere fleksibel, som at give nogen mulighed for at angive navnet på den person, der skal hilses, kan vi tilføje en **parameter**. En parameter (nogle gange også kaldet et **argument**) er yderligere information, der sendes til en funktion.
For at gøre en funktion mere genanvendelig vil du ofte gerne overføre information til den. Hvis vi ser på vores `displayGreeting`-eksempel ovenfor, vil det kun vise **Hello, world!**. Ikke den mest nyttige funktion, man kunne oprette. Hvis vi vil gøre den lidt mere fleksibel, som at give nogen mulighed for at angive navnet på den person, der skal hilses, kan vi tilføje en **parameter**. En parameter (nogle gange også kaldet et **argument**) er yderligere information, der sendes til en funktion.
Parametre er angivet i definitionsdelen inden for parenteser og er kommaseparerede som følger:
@ -94,7 +94,7 @@ displayGreeting('Christopher');
## Standardværdier
Vi kan gøre vores funktion endnu mere fleksibel ved at tilføje flere parametre. Men hvad hvis vi ikke vil kræve, at hver værdi angives? Hvis vi holder os til vores hilsenseksempel, kunne vi lade navnet være obligatorisk (vi skal vide, hvem vi hilser på), men vi vil give mulighed for, at selve hilsenen kan tilpasses efter ønske. Hvis nogen ikke ønsker at tilpasse den, giver vi en standardværdi i stedet. For at give en parameter en standardværdi sætter vi den på samme måde, som vi sætter en værdi for en variabel - `parameterName = 'defaultValue'`. For at se et fuldt eksempel:
Vi kan gøre vores funktion endnu mere fleksibel ved at tilføje flere parametre. Men hvad hvis vi ikke vil kræve, at hver værdi angives? Hvis vi holder os til vores hilsningseksempel, kunne vi lade navnet være obligatorisk (vi skal vide, hvem vi hilser på), men vi vil give mulighed for, at selve hilsningen kan tilpasses efter ønske. Hvis nogen ikke ønsker at tilpasse det, giver vi en standardværdi i stedet. For at give en standardværdi til en parameter, angiver vi den på samme måde, som vi angiver en værdi for en variabel - `parameterName = 'defaultValue'`. For at se et fuldt eksempel:
```javascript
function displayGreeting(name, salutation='Hello') {
@ -114,17 +114,17 @@ displayGreeting('Christopher', 'Hi');
## Returneringsværdier
Indtil nu vil den funktion, vi har bygget, altid outputte til [console](https://developer.mozilla.org/docs/Web/API/console). Nogle gange kan dette være præcis, hvad vi leder efter, især når vi opretter funktioner, der vil kalde andre tjenester. Men hvad hvis jeg vil oprette en hjælpefunktion til at udføre en beregning og give værdien tilbage, så jeg kan bruge den andre steder?
Indtil nu vil den funktion, vi har bygget, altid outputte til [konsollen](https://developer.mozilla.org/docs/Web/API/console). Nogle gange kan dette være præcis, hvad vi leder efter, især når vi opretter funktioner, der vil kalde andre tjenester. Men hvad hvis jeg vil oprette en hjælpefunktion til at udføre en beregning og give værdien tilbage, så jeg kan bruge den andre steder?
Vi kan gøre dette ved at bruge en **returneringsværdi**. En returneringsværdi returneres af funktionen og kan gemmes i en variabel på samme måde, som vi kunne gemme en bogstavelig værdi som en streng eller et tal.
Hvis en funktion returnerer noget, bruges nøgleordet `return`. Nøgleordet `return` forventer en værdi eller reference af det, der returneres, som følger:
Hvis en funktion returnerer noget, bruges nøgleordet `return`. Nøgleordet `return` forventer en værdi eller reference af, hvad der returneres, som følger:
```javascript
return myVariable;
```
Vi kunne oprette en funktion til at oprette en hilsenbesked og returnere værdien tilbage til den, der kalder den.
Vi kunne oprette en funktion til at oprette en hilsningsbesked og returnere værdien tilbage til den, der kalder den.
```javascript
function createGreetingMessage(name) {
@ -159,7 +159,7 @@ setTimeout(displayDone, 3000);
Lad os tage et nyt kig på, hvad vi har bygget. Vi opretter en funktion med et navn, som kun vil blive brugt én gang. Efterhånden som vores applikation bliver mere kompleks, kan vi se os selv oprette mange funktioner, som kun vil blive kaldt én gang. Dette er ikke ideelt. Som det viser sig, behøver vi ikke altid at give et navn!
Når vi sender en funktion som en parameter, kan vi undgå at oprette en på forhånd og i stedet bygge en som en del af parameteren. Vi bruger det samme nøgleord `function`, men i stedet bygger vi det som en parameter.
Når vi overfører en funktion som en parameter, kan vi undgå at oprette en på forhånd og i stedet bygge en som en del af parameteren. Vi bruger det samme nøgleord `function`, men i stedet bygger vi det som en parameter.
Lad os omskrive koden ovenfor til at bruge en anonym funktion:
@ -185,7 +185,7 @@ setTimeout(() => {
### Hvornår skal man bruge hver strategi
Du har nu set, at vi har tre måder at sende en funktion som en parameter og undrer dig måske over, hvornår du skal bruge hver. Hvis du ved, at du vil bruge funktionen mere end én gang, skal du oprette den som normalt. Hvis du kun vil bruge den til én placering, er det generelt bedst at bruge en anonym funktion. Om du bruger en fat arrow-funktion eller den mere traditionelle `function`-syntaks er op til dig, men du vil bemærke, at de fleste moderne udviklere foretrækker `=>`.
Du har nu set, at vi har tre måder at overføre en funktion som en parameter og undrer dig måske over, hvornår man skal bruge hver. Hvis du ved, at du vil bruge funktionen mere end én gang, skal du oprette den som normalt. Hvis du kun vil bruge den til én placering, er det generelt bedst at bruge en anonym funktion. Om du bruger en fat arrow-funktion eller den mere traditionelle `function`-syntaks, er op til dig, men du vil bemærke, at de fleste moderne udviklere foretrækker `=>`.
---
@ -193,8 +193,8 @@ Du har nu set, at vi har tre måder at sende en funktion som en parameter og und
Kan du formulere forskellen mellem funktioner og metoder i én sætning? Giv det et forsøg!
## Quiz efter lektionen
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/10)
## Quiz efter forelæsning
[Quiz efter forelæsning](https://ff-quizzes.netlify.app)
## Gennemgang & Selvstudie
@ -207,4 +207,4 @@ Det er værd at [læse lidt mere om arrow-funktioner](https://developer.mozilla.
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "888609c48329c280ca2477d2df40f2e5",
"translation_date": "2025-08-26T21:41:08+00:00",
"original_hash": "f7009631b73556168ca435120a231c98",
"translation_date": "2025-08-29T08:16:35+00:00",
"source_file": "2-js-basics/3-making-decisions/README.md",
"language_code": "da"
}
@ -17,7 +17,7 @@ CO_OP_TRANSLATOR_METADATA:
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/11)
At træffe beslutninger og kontrollere rækkefølgen, hvori din kode kører, gør din kode genanvendelig og robust. Dette afsnit dækker syntaksen for at kontrollere dataflow i JavaScript og dens betydning, når den bruges med Booleske datatyper.
At træffe beslutninger og kontrollere rækkefølgen, hvori din kode kører, gør din kode genanvendelig og robust. Denne sektion dækker syntaksen for at kontrollere dataflow i JavaScript og dens betydning, når den bruges med Booleske datatyper.
[![At Træffe Beslutninger](https://img.youtube.com/vi/SxTp8j-fMMY/0.jpg)](https://youtube.com/watch?v=SxTp8j-fMMY "At Træffe Beslutninger")
@ -27,9 +27,9 @@ At træffe beslutninger og kontrollere rækkefølgen, hvori din kode kører, gø
## En Kort Genopfriskning af Booleans
Booleans kan kun have to værdier: `true` eller `false`. Booleans hjælper med at træffe beslutninger om, hvilke linjer kode der skal køres, når bestemte betingelser er opfyldt.
Booleans kan kun have to værdier: `true` eller `false`. Booleans hjælper med at træffe beslutninger om, hvilke linjer kode der skal køres, når visse betingelser er opfyldt.
Sæt din boolean til at være sand eller falsk som dette:
Sæt din boolean til at være true eller false sådan her:
`let myTrueBool = true`
`let myFalseBool = false`
@ -38,22 +38,22 @@ Sæt din boolean til at være sand eller falsk som dette:
## Sammenligningsoperatorer og Booleans
Operatorer bruges til at evaluere betingelser ved at lave sammenligninger, der skaber en Boolesk værdi. Følgende er en liste over ofte anvendte operatorer.
Operatorer bruges til at evaluere betingelser ved at lave sammenligninger, der skaber en Boolean-værdi. Følgende er en liste over ofte anvendte operatorer.
| Symbol | Beskrivelse | Eksempel |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `<` | **Mindre end**: Sammenligner to værdier og returnerer den Booleske datatype `true`, hvis værdien på venstre side er mindre end højre | `5 < 6 // true` |
| `<=` | **Mindre end eller lig med**: Sammenligner to værdier og returnerer den Booleske datatype `true`, hvis værdien på venstre side er mindre end eller lig med højre | `5 <= 6 // true` |
| `>` | **Større end**: Sammenligner to værdier og returnerer den Booleske datatype `true`, hvis værdien på venstre side er større end højre | `5 > 6 // false` |
| `>=` | **Større end eller lig med**: Sammenligner to værdier og returnerer den Booleske datatype `true`, hvis værdien på venstre side er større end eller lig med højre | `5 >= 6 // false` |
| `===` | **Streng lighed**: Sammenligner to værdier og returnerer den Booleske datatype `true`, hvis værdierne på højre og venstre er ens OG har samme datatype. | `5 === 6 // false` |
| `!==` | **Ulighed**: Sammenligner to værdier og returnerer den modsatte Booleske værdi af, hvad en streng lighedsoperator ville returnere | `5 !== 6 // true` |
| `<` | **Mindre end**: Sammenligner to værdier og returnerer `true` Boolean-datatype, hvis værdien på venstre side er mindre end højre | `5 < 6 // true` |
| `<=` | **Mindre end eller lig med**: Sammenligner to værdier og returnerer `true` Boolean-datatype, hvis værdien på venstre side er mindre end eller lig med højre | `5 <= 6 // true` |
| `>` | **Større end**: Sammenligner to værdier og returnerer `true` Boolean-datatype, hvis værdien på venstre side er større end højre | `5 > 6 // false` |
| `>=` | **Større end eller lig med**: Sammenligner to værdier og returnerer `true` Boolean-datatype, hvis værdien på venstre side er større end eller lig med højre | `5 >= 6 // false` |
| `===` | **Streng lighed**: Sammenligner to værdier og returnerer `true` Boolean-datatype, hvis værdierne på højre og venstre er ens OG har samme datatype. | `5 === 6 // false` |
| `!==` | **Ulighed**: Sammenligner to værdier og returnerer den modsatte Boolean-værdi af, hvad en streng lighedsoperator ville returnere | `5 !== 6 // true` |
✅ Test din viden ved at skrive nogle sammenligninger i din browsers konsol. Overrasker nogen af de returnerede data dig?
✅ Test din viden ved at skrive nogle sammenligninger i din browsers konsol. Er der noget af det returnerede data, der overrasker dig?
## If-sætning
## If-Sætning
If-sætningen kører koden mellem dens blokke, hvis betingelsen er sand.
If-sætningen vil køre kode mellem sine blokke, hvis betingelsen er sand.
```javascript
if (condition) {
@ -73,9 +73,9 @@ if (currentMoney >= laptopPrice) {
}
```
## If..Else-sætning
## If..Else-Sætning
`else`-sætningen kører koden mellem dens blokke, når betingelsen er falsk. Den er valgfri med en `if`-sætning.
`else`-sætningen vil køre koden mellem sine blokke, når betingelsen er falsk. Den er valgfri med en `if`-sætning.
```javascript
let currentMoney;
@ -90,9 +90,9 @@ if (currentMoney >= laptopPrice) {
}
```
✅ Test din forståelse af denne kode og den følgende kode ved at køre den i en browserkonsol. Ændr værdierne af variablerne `currentMoney` og `laptopPrice` for at ændre den returnerede `console.log()`.
✅ Test din forståelse af denne kode og den følgende kode ved at køre den i en browserkonsol. Ændr værdierne af variablerne currentMoney og laptopPrice for at ændre den returnerede `console.log()`.
## Switch-sætning
## Switch-Sætning
`switch`-sætningen bruges til at udføre forskellige handlinger baseret på forskellige betingelser. Brug `switch`-sætningen til at vælge en af mange kodeblokke, der skal udføres.
@ -127,17 +127,17 @@ switch (a) {
console.log(`The value is ${a}`);
```
✅ Test din forståelse af denne kode og den følgende kode ved at køre den i en browserkonsol. Ændr værdierne af variablen `a` for at ændre den returnerede `console.log()`.
✅ Test din forståelse af denne kode og den følgende kode ved at køre den i en browserkonsol. Ændr værdierne af variablen a for at ændre den returnerede `console.log()`.
## Logiske Operatorer og Booleans
Beslutninger kan kræve mere end én sammenligning og kan kædes sammen med logiske operatorer for at producere en Boolesk værdi.
Beslutninger kan kræve mere end én sammenligning og kan kædes sammen med logiske operatorer for at producere en Boolean-værdi.
| Symbol | Beskrivelse | Eksempel |
| ------ | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `&&` | **Logisk OG**: Sammenligner to Booleske udtryk. Returnerer true **kun**, hvis begge sider er sande | `(5 > 6) && (5 < 6 ) //Den ene side er falsk, den anden er sand. Returnerer false` |
| `\|\|` | **Logisk ELLER**: Sammenligner to Booleske udtryk. Returnerer true, hvis mindst én side er sand | `(5 > 6) \|\| (5 < 6) //Den ene side er falsk, den anden er sand. Returnerer true` |
| `!` | **Logisk IKKE**: Returnerer den modsatte værdi af et Boolesk udtryk | `!(5 > 6) // 5 er ikke større end 6, men "!" vil returnere true` |
| `&&` | **Logisk OG**: Sammenligner to Boolean-udtryk. Returnerer true **kun** hvis begge sider er true | `(5 > 6) && (5 < 6 ) //En side er falsk, den anden er sand. Returnerer false` |
| `\|\|` | **Logisk ELLER**: Sammenligner to Boolean-udtryk. Returnerer true, hvis mindst én side er true | `(5 > 6) \|\| (5 < 6) //En side er falsk, den anden er sand. Returnerer true` |
| `!` | **Logisk IKKE**: Returnerer den modsatte værdi af et Boolean-udtryk | `!(5 > 6) // 5 er ikke større end 6, men "!" vil returnere true` |
## Betingelser og Beslutninger med Logiske Operatorer
@ -159,7 +159,7 @@ if (currentMoney >= laptopPrice || currentMoney >= laptopDiscountPrice) {
### Negationsoperator
Du har indtil videre set, hvordan du kan bruge en `if...else`-sætning til at skabe betinget logik. Alt, der går ind i en `if`, skal evaluere til sandt/falsk. Ved at bruge `!`-operatoren kan du _negere_ udtrykket. Det vil se sådan ud:
Du har indtil videre set, hvordan du kan bruge en `if...else`-sætning til at skabe betinget logik. Alt, der går ind i en `if`, skal evaluere til true/false. Ved at bruge `!`-operatoren kan du _negere_ udtrykket. Det ville se sådan ud:
```javascript
if (!condition) {
@ -169,7 +169,7 @@ if (!condition) {
}
```
### Ternære udtryk
### Ternære Udtryk
`if...else` er ikke den eneste måde at udtrykke beslutningslogik på. Du kan også bruge noget, der kaldes en ternær operator. Syntaksen for den ser sådan ud:
@ -193,7 +193,7 @@ Ovenstående siger, at
- så tildel `firstNumber` til `biggestNumber`
- ellers tildel `secondNumber`.
Den ternære udtryksform er blot en kompakt måde at skrive koden nedenfor på:
Det ternære udtryk er blot en kompakt måde at skrive koden nedenfor på:
```javascript
let biggestNumber;
@ -220,7 +220,7 @@ Lav et program, der først er skrevet med logiske operatorer, og omskriv det der
Læs mere om de mange operatorer, der er tilgængelige for brugeren [på MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Gå igennem Josh Comeaus fantastiske [operatoropslag](https://joshwcomeau.com/operator-lookup/)!
Gå igennem Josh Comeaus fantastiske [operator-opslag](https://joshwcomeau.com/operator-lookup/)!
## Opgave
@ -229,4 +229,4 @@ Gå igennem Josh Comeaus fantastiske [operatoropslag](https://joshwcomeau.com/op
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at opnå nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "3f7f87871312cf6cc12662da7d973182",
"translation_date": "2025-08-26T21:46:42+00:00",
"original_hash": "9029f96b0e034839c1799f4595e4bb66",
"translation_date": "2025-08-29T08:18:05+00:00",
"source_file": "2-js-basics/4-arrays-loops/README.md",
"language_code": "da"
}
@ -19,7 +19,7 @@ Denne lektion dækker det grundlæggende i JavaScript, sproget der giver interak
[![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 "Loops")
[![Løkker](https://img.youtube.com/vi/Eeh7pxtTZ3k/0.jpg)](https://www.youtube.com/watch?v=Eeh7pxtTZ3k "Løkker")
> 🎥 Klik på billederne ovenfor for videoer om arrays og løkker.
@ -27,25 +27,25 @@ Denne lektion dækker det grundlæggende i JavaScript, sproget der giver interak
## Arrays
At arbejde med data er en almindelig opgave i ethvert programmeringssprog, og det er en meget lettere opgave, når data er organiseret i en strukturel form, såsom arrays. Med arrays gemmes data i en struktur, der ligner en liste. En stor fordel ved arrays er, at du kan gemme forskellige typer data i ét array.
At arbejde med data er en almindelig opgave i ethvert programmeringssprog, og det bliver meget nemmere, når data er organiseret i en struktureret form som arrays. Med arrays gemmes data i en struktur, der minder om en liste. En stor fordel ved arrays er, at du kan gemme forskellige typer data i ét array.
✅ Arrays er overalt omkring os! Kan du komme i tanke om et eksempel fra det virkelige liv på et array, såsom en solcellepanel-array?
✅ Arrays findes overalt omkring os! Kan du komme i tanke om et eksempel fra det virkelige liv, som et solcellepanel-array?
Syntaksen for et array er et par firkantede parenteser.
Syntaksen for et array er et par kantede parenteser.
```javascript
let myArray = [];
```
Dette er et tomt array, men arrays kan deklareres allerede fyldt med data. Flere værdier i et array adskilles med et komma.
Dette er et tomt array, men arrays kan også deklareres med data allerede indsat. Flere værdier i et array adskilles med et komma.
```javascript
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
```
Array-værdierne tildeles en unik værdi kaldet **indeks**, et heltal, der tildeles baseret på dets afstand fra begyndelsen af arrayet. I eksemplet ovenfor har strengværdien "Chocolate" et indeks på 0, og indekset for "Rocky Road" er 4. Brug indekset med firkantede parenteser til at hente, ændre eller indsætte array-værdier.
Array-værdier tildeles en unik værdi kaldet **indeks**, et heltal, der tildeles baseret på afstanden fra begyndelsen af arrayet. I eksemplet ovenfor har strengværdien "Chocolate" et indeks på 0, og "Rocky Road" har et indeks på 4. Brug indekset med kantede parenteser til at hente, ændre eller indsætte værdier i arrayet.
✅ Er det overraskende for dig, at arrays starter ved indeks nul? I nogle programmeringssprog starter indekser ved 1. Der er en interessant historie omkring dette, som du kan [læse på Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
✅ Er det overraskende for dig, at arrays starter ved indeks nul? I nogle programmeringssprog starter indekser ved 1. Der er en interessant historie bag dette, som du kan [læse om på Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
```javascript
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
@ -64,26 +64,26 @@ Og du kan indsætte en ny værdi på et givet indeks som dette:
iceCreamFlavors[5] = "Cookie Dough"; //Added "Cookie Dough"
```
✅ En mere almindelig måde at tilføje værdier til et array er ved at bruge array-operatører såsom array.push()
✅ En mere almindelig måde at tilføje værdier til et array er ved at bruge array-metoder som array.push().
For at finde ud af, hvor mange elementer der er i et array, skal du bruge `length`-egenskaben.
For at finde ud af, hvor mange elementer der er i et array, kan du bruge `length`-egenskaben.
```javascript
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
iceCreamFlavors.length; //5
```
✅ Prøv det selv! Brug din browsers konsol til at oprette og manipulere et array, du selv har lavet.
✅ Prøv det selv! Brug din browsers konsol til at oprette og manipulere et array, du selv finder på.
## Løkker
Løkker giver os mulighed for at udføre gentagne eller **iterative** opgaver og kan spare meget tid og kode. Hver iteration kan variere i deres variabler, værdier og betingelser. Der er forskellige typer løkker i JavaScript, og de har alle små forskelle, men gør i bund og grund det samme: løkker over data.
Løkker giver os mulighed for at udføre gentagne eller **iterative** opgaver og kan spare meget tid og kode. Hver iteration kan variere i deres variabler, værdier og betingelser. Der findes forskellige typer løkker i JavaScript, og de har små forskelle, men gør i bund og grund det samme: gennemløber data.
### For-løkke
`for`-løkker kræver 3 dele for at iterere:
- `counter` En variabel, der typisk initialiseres med et tal, der tæller antallet af iterationer
- `condition` Udtryk, der bruger sammenligningsoperatorer til at få løkken til at stoppe, når den er `false`
- `condition` Et udtryk, der bruger sammenligningsoperatorer til at stoppe løkken, når det bliver `false`
- `iteration-expression` Kører i slutningen af hver iteration, typisk brugt til at ændre counter-værdien
```javascript
@ -97,7 +97,7 @@ for (let i = 0; i < 10; i++) {
### While-løkke
I modsætning til syntaksen for `for`-løkker kræver `while`-løkker kun en betingelse, der stopper løkken, når betingelsen bliver `false`. Betingelser i løkker afhænger normalt af andre værdier som counters og skal administreres under løkken. Startværdier for counters skal oprettes uden for løkken, og alle udtryk for at opfylde en betingelse, inklusive ændring af counter, skal vedligeholdes inde i løkken.
I modsætning til syntaksen for `for`-løkker kræver `while`-løkker kun en betingelse, der stopper løkken, når betingelsen bliver `false`. Betingelser i løkker afhænger normalt af andre værdier som counters og skal håndteres under løkken. Startværdier for counters skal oprettes uden for løkken, og alle udtryk for at opfylde en betingelse, inklusive ændring af counter, skal vedligeholdes inden i løkken.
```javascript
//Counting up to 10
@ -108,11 +108,11 @@ while (i < 10) {
}
```
✅ Hvorfor ville du vælge en for-løkke frem for en while-løkke? 17K brugere havde det samme spørgsmål på StackOverflow, og nogle af meningerne [kan være interessante for dig](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
✅ Hvorfor ville du vælge en for-løkke frem for en while-løkke? 17.000 brugere havde det samme spørgsmål på StackOverflow, og nogle af deres meninger [kan være interessante for dig](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
## Løkker og Arrays
Arrays bruges ofte med løkker, fordi de fleste betingelser kræver længden af arrayet for at stoppe løkken, og indekset kan også være counter-værdien.
Arrays bruges ofte sammen med løkker, fordi de fleste betingelser kræver længden af arrayet for at stoppe løkken, og indekset kan også være counter-værdien.
```javascript
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
@ -122,20 +122,20 @@ for (let i = 0; i < iceCreamFlavors.length; i++) {
} //Ends when all flavors are printed
```
✅ Eksperimentér med at løkke over et array, du selv har lavet, i din browsers konsol.
✅ Eksperimentér med at gennemløbe et array, du selv finder på, i din browsers konsol.
---
## 🚀 Udfordring
Der er andre måder at løkke over arrays end for- og while-løkker. Der er [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) og [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Skriv din array-løkke om ved hjælp af en af disse teknikker.
Der findes andre måder at gennemløbe arrays på end for- og while-løkker. Der er [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) og [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Omskriv din array-løkke ved hjælp af en af disse teknikker.
## Quiz efter lektionen
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/14)
## Gennemgang & Selvstudie
Arrays i JavaScript har mange metoder knyttet til dem, som er ekstremt nyttige til datamanipulation. [Læs om disse metoder](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) og prøv nogle af dem (som push, pop, slice og splice) på et array, du selv har lavet.
Arrays i JavaScript har mange metoder knyttet til sig, som er ekstremt nyttige til datamanipulation. [Læs om disse metoder](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) og prøv nogle af dem (som push, pop, slice og splice) på et array, du selv opretter.
## Opgave
@ -144,4 +144,4 @@ Arrays i JavaScript har mange metoder knyttet til dem, som er ekstremt nyttige t
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "46a0639e719b9cf1dfd062aa24cad639",
"translation_date": "2025-08-26T21:30:22+00:00",
"original_hash": "89f7f9f800ce7c9f149e98baaae8491a",
"translation_date": "2025-08-29T08:18:35+00:00",
"source_file": "3-terrarium/1-intro-to-html/README.md",
"language_code": "da"
}
@ -20,13 +20,13 @@ CO_OP_TRANSLATOR_METADATA:
> Se videoen
>
> [![Video om Git og GitHub grundlæggende](https://img.youtube.com/vi/1TvxJKBzhyQ/0.jpg)](https://www.youtube.com/watch?v=1TvxJKBzhyQ)
> [![Git og GitHub grundlæggende video](https://img.youtube.com/vi/1TvxJKBzhyQ/0.jpg)](https://www.youtube.com/watch?v=1TvxJKBzhyQ)
### Introduktion
HTML, eller HyperText Markup Language, er 'skelettet' på nettet. Hvis CSS 'klæder' din HTML på, og JavaScript giver det liv, så er HTML kroppen i din webapplikation. HTML's syntaks afspejler endda denne idé, da den inkluderer "head", "body" og "footer" tags.
I denne lektion skal vi bruge HTML til at opbygge 'skelettet' af vores virtuelle terrariums interface. Det vil have en titel og tre kolonner: en højre og en venstre kolonne, hvor de trækbare planter befinder sig, og et midterområde, som vil være det egentlige glaslignende terrarium. Når vi er færdige med denne lektion, vil du kunne se planterne i kolonnerne, men interfacet vil se lidt mærkeligt ud; bare rolig, i næste sektion tilføjer vi CSS-stilarter til interfacet for at få det til at se bedre ud.
I denne lektion skal vi bruge HTML til at opbygge 'skelettet' af vores virtuelle terrariums interface. Det vil have en titel og tre kolonner: en højre og en venstre kolonne, hvor de trækbare planter befinder sig, og et midterområde, som vil være det glaslignende terrarium. Ved slutningen af denne lektion vil du kunne se planterne i kolonnerne, men interfacet vil se lidt mærkeligt ud; bare rolig, i næste sektion vil du tilføje CSS-stilarter til interfacet for at få det til at se bedre ud.
### Opgave
@ -42,7 +42,7 @@ Brug disse kommandoer i din git bash:
* `touch index.html`
* `code index.html` eller `nano index.html`
> index.html-filer angiver for en browser, at det er standardfilen i en mappe; URL'er som `https://anysite.com/test` kan være bygget ved hjælp af en mappestruktur, der inkluderer en mappe kaldet `test` med `index.html` indeni; `index.html` behøver ikke at vises i en URL.
> index.html-filer angiver til en browser, at det er standardfilen i en mappe; URL'er som `https://anysite.com/test` kan være bygget ved hjælp af en mappestruktur, der inkluderer en mappe kaldet `test` med `index.html` indeni; `index.html` behøver ikke at vises i en URL.
---
@ -52,7 +52,7 @@ Den første linje i en HTML-fil er dens doctype. Det er lidt overraskende, at du
> Tip: I VS Code kan du holde musen over et tag og få information om dets brug fra MDN Reference guides.
Den anden linje skal være `<html>`-taggets åbningstag, efterfulgt af dets lukketag `</html>`. Disse tags er roden af dit interface.
Den anden linje skal være `<html>`-taggets åbningstag, efterfulgt af dets lukningstag `</html>`. Disse tags er roden af dit interface.
### Opgave
@ -63,7 +63,7 @@ Tilføj disse linjer øverst i din `index.html`-fil:
<html></html>
```
✅ Der er nogle forskellige tilstande, der kan bestemmes ved at sætte DocType med en forespørgselsstreng: [Quirks Mode og Standards Mode](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode). Disse tilstande blev brugt til at understøtte virkelig gamle browsere, som normalt ikke bruges i dag (Netscape Navigator 4 og Internet Explorer 5). Du kan holde dig til standard doctype-deklarationen.
✅ Der er et par forskellige tilstande, der kan bestemmes ved at sætte DocType med en forespørgselsstreng: [Quirks Mode og Standards Mode](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode). Disse tilstande blev brugt til at understøtte virkelig gamle browsere, som normalt ikke bruges i dag (Netscape Navigator 4 og Internet Explorer 5). Du kan holde dig til standard doctype-deklarationen.
---
@ -72,10 +72,10 @@ Tilføj disse linjer øverst i din `index.html`-fil:
'Head'-området i HTML-dokumentet inkluderer vigtig information om din webside, også kendt som [metadata](https://developer.mozilla.org/docs/Web/HTML/Element/meta). I vores tilfælde fortæller vi webserveren, som denne side vil blive sendt til for at blive gengivet, disse fire ting:
- sidens titel
- metadata om siden, herunder:
- sidens metadata, herunder:
- 'character set', som fortæller, hvilken tegnkodning der bruges på siden
- browserinformation, herunder `x-ua-compatible`, som angiver, at IE=edge-browseren understøttes
- information om, hvordan viewporten skal opføre sig, når den indlæses. Ved at sætte viewporten til at have en initial scale på 1 kontrolleres zoomniveauet, når siden først indlæses.
- information om, hvordan viewporten skal opføre sig, når den indlæses. At sætte viewporten til at have en initial scale på 1 kontrollerer zoomniveauet, når siden først indlæses.
### Opgave
@ -98,7 +98,7 @@ Tilføj et 'head'-blok til dit dokument mellem åbning og lukning af `<html>`-ta
### HTML-tags
I HTML tilføjer du tags til din .html-fil for at oprette elementer på en webside. Hvert tag har normalt et åbningstag og et lukketag, som dette: `<p>hello</p>` for at angive et afsnit. Opret kroppens interface ved at tilføje et sæt `<body>`-tags inden for `<html>`-tagparret; din markup ser nu sådan ud:
I HTML tilføjer du tags til din .html-fil for at oprette elementer på en webside. Hvert tag har normalt et åbningstag og et lukningstag, som dette: `<p>hej</p>` for at angive et afsnit. Opret kroppens interface ved at tilføje et sæt `<body>`-tags inde i `<html>`-tagparret; din markup ser nu sådan ud:
### Opgave
@ -119,7 +119,7 @@ Nu kan du begynde at opbygge din side. Normalt bruger du `<div>`-tags til at opr
### Billeder
Et HTML-tag, der ikke behøver et lukketag, er `<img>`-tagget, fordi det har et `src`-element, der indeholder al den information, siden har brug for til at gengive elementet.
Et HTML-tag, der ikke behøver et lukningstag, er `<img>`-tagget, fordi det har et `src`-element, der indeholder al den information, siden har brug for til at gengive elementet.
Opret en mappe i din app kaldet `images`, og tilføj alle billederne fra [source code folder](../../../../3-terrarium/solution/images); (der er 14 billeder af planter).
@ -198,7 +198,7 @@ Tilføj følgende linje lige under dit åbningstag `<body>`:
<h1>My Terrarium</h1>
```
At bruge semantisk markup, som at have overskrifter som `<h1>` og uordnede lister som `<ul>`, hjælper skærmlæsere med at navigere gennem en side. Generelt bør knapper skrives som `<button>`, og lister bør være `<li>`. Selvom det _er muligt_ at bruge specielt stylet `<span>`-elementer med klik-håndterere til at efterligne knapper, er det bedre for handicappede brugere at bruge teknologier til at bestemme, hvor på en side en knap befinder sig, og interagere med den, hvis elementet vises som en knap. Af denne grund bør du forsøge at bruge semantisk markup så meget som muligt.
At bruge semantisk markup, som at have overskrifter som `<h1>` og uordnede lister som `<ul>`, hjælper skærmlæsere med at navigere gennem en side. Generelt bør knapper skrives som `<button>`, og lister bør være `<li>`. Selvom det _er muligt_ at bruge specielt stylet `<span>`-elementer med klikfunktioner til at efterligne knapper, er det bedre for handicappede brugere at bruge teknologier til at bestemme, hvor på en side en knap findes, og interagere med den, hvis elementet vises som en knap. Af denne grund bør du forsøge at bruge semantisk markup så meget som muligt.
✅ Tag et kig på en skærmlæser og [hvordan den interagerer med en webside](https://www.youtube.com/watch?v=OUDV1gqs9GA). Kan du se, hvorfor ikke-semantisk markup kan frustrere brugeren?
@ -222,7 +222,7 @@ Tilføj denne markup over det sidste `</div>`-tag:
</div>
```
✅ Selvom du har tilføjet denne markup til skærmen, ser du absolut intet blive gengivet. Hvorfor?
✅ Selvom du tilføjede denne markup til skærmen, ser du absolut intet blive gengivet. Hvorfor?
---
@ -240,7 +240,6 @@ HTML er det 'prøvede og sande' byggesystem, der har hjulpet med at opbygge nett
Lær mere om at bygge sider til nettet og mobile enheder på [Microsoft Learn](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon).
## Opgave
[Øv dig i HTML: Byg en blogmockup](assignment.md)
@ -248,4 +247,4 @@ Lær mere om at bygge sider til nettet og mobile enheder på [Microsoft Learn](h
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at opnå nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvaret for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e375c2aeb94e2407f2667633d39580bd",
"translation_date": "2025-08-26T21:37:16+00:00",
"original_hash": "acb5ae00cde004304296bb97da8ff4c3",
"translation_date": "2025-08-29T08:19:07+00:00",
"source_file": "3-terrarium/2-intro-to-css/README.md",
"language_code": "da"
}
@ -18,7 +18,7 @@ CO_OP_TRANSLATOR_METADATA:
### Introduktion
CSS, eller Cascading Style Sheets, løser et vigtigt problem inden for webudvikling: hvordan man får sin hjemmeside til at se flot ud. Styling af dine apps gør dem mere brugervenlige og visuelt tiltalende; du kan også bruge CSS til at skabe Responsive Web Design (RWD) - så dine apps ser godt ud, uanset hvilken skærmstørrelse de vises på. CSS handler ikke kun om at få din app til at se flot ud; specifikationen inkluderer også animationer og transformationer, der kan muliggøre avancerede interaktioner for dine apps. CSS Working Group hjælper med at vedligeholde de aktuelle CSS-specifikationer; du kan følge deres arbejde på [World Wide Web Consortiums hjemmeside](https://www.w3.org/Style/CSS/members).
CSS, eller Cascading Style Sheets, løser et vigtigt problem inden for webudvikling: hvordan man får din hjemmeside til at se flot ud. Styling af dine apps gør dem mere brugervenlige og visuelt tiltalende; du kan også bruge CSS til at skabe Responsive Web Design (RWD) - så dine apps ser godt ud uanset skærmstørrelse. CSS handler ikke kun om at få din app til at se flot ud; specifikationen inkluderer også animationer og transformationer, der kan muliggøre avancerede interaktioner for dine apps. CSS Working Group hjælper med at vedligeholde de aktuelle CSS-specifikationer; du kan følge deres arbejde på [World Wide Web Consortiums hjemmeside](https://www.w3.org/Style/CSS/members).
> Bemærk, CSS er et sprog, der udvikler sig, ligesom alt andet på nettet, og ikke alle browsere understøtter de nyeste dele af specifikationen. Tjek altid dine implementeringer ved at konsultere [CanIUse.com](https://caniuse.com).
@ -35,7 +35,7 @@ Du bør have HTML'en til dit terrarium klar og klar til at blive stylet.
### Opgave
I din terrarium-mappe skal du oprette en ny fil kaldet `style.css`. Importer den fil i `<head>`-sektionen:
I din terrarium-mappe skal du oprette en ny fil kaldet `style.css`. Importér den fil i `<head>`-sektionen:
```html
<link rel="stylesheet" href="./style.css" />
@ -55,7 +55,7 @@ Tilføj den inline style "color: red" til din `<h1>`-tag:
<h1 style="color: red">My Terrarium</h1>
```
Tilføj derefter følgende kode til din `style.css`-fil:
Derefter skal du tilføje følgende kode til din `style.css`-fil:
```CSS
h1 {
@ -69,11 +69,11 @@ h1 {
## Arv
Styles arves fra en forfader til en efterkommer, sådan at indlejrede elementer arver deres forældres styles.
Styles arves fra en forfaderstil til en efterkommer, sådan at indlejrede elementer arver deres forældres styles.
### Opgave
Sæt kroppens font til en given font, og tjek for at se en indlejret elements font:
Sæt kroppens skrifttype til en given skrifttype, og tjek for at se en indlejret elements skrifttype:
```CSS
body {
@ -81,9 +81,9 @@ body {
}
```
Åbn din browsers konsol til 'Elements'-fanen og observer H1's font. Den arver sin font fra kroppen, som angivet inden for browseren:
Åbn din browsers konsol til fanen 'Elements' og observer H1's skrifttype. Den arver sin skrifttype fra kroppen, som angivet inden for browseren:
![arvet font](../../../../translated_images/1.cc07a5cbe114ad1d4728c35134584ac1b87db688eff83cf75985cf31fe0ed95c.da.png)
![arvet skrifttype](../../../../translated_images/1.cc07a5cbe114ad1d4728c35134584ac1b87db688eff83cf75985cf31fe0ed95c.da.png)
✅ Kan du få en indlejret style til at arve en anden egenskab?
@ -106,7 +106,7 @@ h1 {
}
```
Denne måde at style et tag på giver dig kontrol over unikke elementer, men du har brug for at kontrollere styles for mange planter i dit terrarium. For at gøre dette skal du bruge CSS-selektorer.
Denne måde at style et tag på giver dig kontrol over unikke elementer, men du har brug for at kontrollere styles for mange planter i dit terrarium. For at gøre dette skal du udnytte CSS-selektorer.
### Id'er
@ -134,7 +134,7 @@ Tilføj noget style for at layoutet venstre og højre containere. Da der kun er
}
```
Her har du placeret disse containere med absolut positionering yderst til venstre og højre på skærmen og brugt procenter for deres bredde, så de kan skalere til små mobilskærme.
Her har du placeret disse containere med absolut positionering helt til venstre og højre på skærmen og brugt procenter for deres bredde, så de kan skalere til små mobilskærme.
✅ Denne kode er ret gentaget, og derfor ikke "DRY" (Don't Repeat Yourself); kan du finde en bedre måde at style disse id'er på, måske med et id og en klasse? Du ville skulle ændre markupen og refaktorere CSS'en:
@ -177,7 +177,7 @@ Du sætter højden på planteholderen til 13%, et godt tal for at sikre, at alle
Du sætter planteholderen til at flytte til venstre for at gøre planterne mere centrerede inden for deres container. Billederne har en stor mængde gennemsigtig baggrund for at gøre dem mere dragbare, så de skal skubbes til venstre for at passe bedre på skærmen.
Derefter får selve planten en max-bredde på 150%. Dette gør det muligt for den at skalere ned, når browseren skaleres ned. Prøv at ændre størrelsen på din browser; planterne forbliver i deres containere, men skaleres ned for at passe.
Derefter får selve planten en max-bredde på 150%. Dette gør det muligt for den at skalere ned, når browseren skaleres ned. Prøv at ændre størrelsen på din browser; planterne forbliver i deres containere, men skalerer ned for at passe.
Også bemærkelsesværdigt er brugen af z-index, som styrer den relative højde af et element (så planterne sidder oven på containeren og ser ud til at sidde inde i terrariet).
@ -187,21 +187,21 @@ Også bemærkelsesværdigt er brugen af z-index, som styrer den relative højde
At blande positioneringsegenskaber (der er statiske, relative, faste, absolutte og klæbrige positioner) kan være lidt tricky, men når det gøres korrekt, giver det dig god kontrol over elementerne på dine sider.
Absolut positionerede elementer er positioneret relativt til deres nærmeste positionerede forfædre, og hvis der ikke er nogen, positioneres de i forhold til dokumentets krop.
Absolut positionerede elementer er positioneret i forhold til deres nærmeste positionerede forfædre, og hvis der ikke er nogen, positioneres de i forhold til dokumentets krop.
Relativt positionerede elementer er positioneret baseret på CSS'ens instruktioner om at justere deres placering væk fra deres oprindelige position.
Relativt positionerede elementer er positioneret baseret på CSS'ens instruktioner til at justere deres placering væk fra deres oprindelige position.
I vores eksempel er `plant-holder` et relativt positioneret element, der er positioneret inden for en absolut positioneret container. Den resulterende adfærd er, at sidebjælkecontainerne er fastgjort til venstre og højre, og planteholderen er indlejret, justerer sig selv inden for sidebjælkerne og giver plads til, at planterne kan placeres i en vertikal række.
I vores eksempel er `plant-holder` et relativt positioneret element, der er positioneret inden for en absolut positioneret container. Den resulterende adfærd er, at sidebjælkecontainere er fastgjort til venstre og højre, og planteholderen er indlejret, justerer sig selv inden for sidebjælkerne og giver plads til, at planterne kan placeres i en vertikal række.
> Selve `plant` har også absolut positionering, hvilket er nødvendigt for at gøre det dragbart, som du vil opdage i næste lektion.
✅ Eksperimenter med at skifte typerne af positionering af sidecontainerne og planteholderen. Hvad sker der?
✅ Eksperimentér med at skifte typerne af positionering af sidecontainere og planteholderen. Hvad sker der?
## CSS-layouts
Nu vil du bruge det, du har lært, til at bygge selve terrariet, alt sammen ved hjælp af CSS!
Først skal du style `.terrarium` div-børnene som en afrundet rektangel ved hjælp af CSS:
Først skal du style `.terrarium` div-børnene som et afrundet rektangel ved hjælp af CSS:
```CSS
.jar-walls {
@ -250,9 +250,9 @@ Først skal du style `.terrarium` div-børnene som en afrundet rektangel ved hj
}
```
Bemærk brugen af procenter her. Hvis du skalerer din browser ned, kan du se, hvordan glasset også skaleres. Bemærk også bredderne og højderne i procenter for glaselementerne og hvordan hvert element er absolut positioneret i midten, fastgjort til bunden af visningsområdet.
Bemærk brugen af procenter her. Hvis du skalerer din browser ned, kan du se, hvordan glasset også skaleres. Bemærk også bredderne og højderne i procenter for glaselementerne, og hvordan hvert element er absolut positioneret i midten, fastgjort til bunden af visningsområdet.
Vi bruger også `rem` til border-radius, en font-relativ længde. Læs mere om denne type relative målinger i [CSS-specifikationen](https://www.w3.org/TR/css-values-3/#font-relative-lengths).
Vi bruger også `rem` til border-radius, en skrifttype-relativ længde. Læs mere om denne type relative målinger i [CSS-specifikationen](https://www.w3.org/TR/css-values-3/#font-relative-lengths).
✅ Prøv at ændre glassets farver og opacitet i forhold til jordens. Hvad sker der? Hvorfor?
@ -272,7 +272,7 @@ For at fuldføre quizzen efter lektionen, gå igennem dette Learn-modul: [Style
## Gennemgang & Selvstudie
CSS virker tilsyneladende ligetil, men der er mange udfordringer, når man forsøger at style en app perfekt til alle browsere og alle skærmstørrelser. CSS-Grid og Flexbox er værktøjer, der er udviklet for at gøre arbejdet lidt mere struktureret og mere pålideligt. Lær om disse værktøjer ved at spille [Flexbox Froggy](https://flexboxfroggy.com/) og [Grid Garden](https://codepip.com/games/grid-garden/).
CSS virker tilsyneladende ligetil, men der er mange udfordringer, når man forsøger at style en app perfekt til alle browsere og skærmstørrelser. CSS-Grid og Flexbox er værktøjer, der er udviklet for at gøre arbejdet lidt mere struktureret og mere pålideligt. Lær om disse værktøjer ved at spille [Flexbox Froggy](https://flexboxfroggy.com/) og [Grid Garden](https://codepip.com/games/grid-garden/).
## Opgave
@ -281,4 +281,4 @@ CSS virker tilsyneladende ligetil, men der er mange udfordringer, når man fors
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at opnå nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "30f8903a1f290e3d438dc2c70fe60259",
"translation_date": "2025-08-26T21:34:00+00:00",
"original_hash": "61c14b27044861e5e69db35dd52c4403",
"translation_date": "2025-08-29T08:19:50+00:00",
"source_file": "3-terrarium/3-intro-to-DOM-and-closures/README.md",
"language_code": "da"
}
@ -18,7 +18,7 @@ CO_OP_TRANSLATOR_METADATA:
### Introduktion
Manipulation af DOM, eller "Document Object Model", er en central del af webudvikling. Ifølge [MDN](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) er "The Document Object Model (DOM) den datarepræsentation af objekterne, der udgør strukturen og indholdet af et dokument på nettet." Udfordringerne ved DOM-manipulation på nettet har ofte været årsagen til, at man bruger JavaScript-frameworks i stedet for ren JavaScript til at håndtere DOM, men vi klarer os selv!
Manipulation af DOM, eller "Document Object Model", er en central del af webudvikling. Ifølge [MDN](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) er "Document Object Model (DOM) den datarepræsentation af objekterne, der udgør strukturen og indholdet af et dokument på nettet." Udfordringerne ved DOM-manipulation på nettet har ofte været årsagen til, at man bruger JavaScript-frameworks i stedet for ren JavaScript til at håndtere DOM, men vi klarer os selv!
Derudover vil denne lektion introducere ideen om en [JavaScript closure](https://developer.mozilla.org/docs/Web/JavaScript/Closures), som du kan tænke på som en funktion, der er indkapslet af en anden funktion, så den indre funktion har adgang til den ydre funktions scope.
@ -46,7 +46,7 @@ I din terrarium-mappe skal du oprette en ny fil kaldet `script.js`. Importér de
<script src="./script.js" defer></script>
```
> Bemærk: Brug `defer`, når du importerer en ekstern JavaScript-fil i HTML-filen, så JavaScript kun udføres, efter HTML-filen er fuldt indlæst. Du kunne også bruge attributten `async`, som tillader scriptet at udføres, mens HTML-filen parses, men i vores tilfælde er det vigtigt, at HTML-elementerne er fuldt tilgængelige til at trække, før vi tillader drag-scriptet at blive udført.
> Bemærk: Brug `defer`, når du importerer en ekstern JavaScript-fil i HTML-filen, så JavaScript kun eksekveres, efter HTML-filen er fuldt indlæst. Du kunne også bruge attributten `async`, som tillader scriptet at eksekvere, mens HTML-filen parses, men i vores tilfælde er det vigtigt, at HTML-elementerne er fuldt tilgængelige til at trække, før vi tillader drag-scriptet at blive eksekveret.
---
## DOM-elementerne
@ -72,7 +72,7 @@ dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));
```
Hvad sker der her? Du refererer til dokumentet og søger gennem dets DOM for at finde et element med et bestemt Id. Husk fra den første lektion om HTML, at du gav individuelle Id'er til hvert plantebillede (`id="plant1"`)? Nu vil du gøre brug af den indsats. Efter at have identificeret hvert element, sender du det til en funktion kaldet `dragElement`, som du vil bygge om lidt. Således er elementet i HTML nu drag-aktiveret, eller vil snart være det.
Hvad sker der her? Du refererer til dokumentet og søger gennem dets DOM for at finde et element med et bestemt Id. Husk fra den første lektion om HTML, at du gav individuelle Id'er til hvert plantebillede (`id="plant1"`)? Nu vil du gøre brug af den indsats. Efter at have identificeret hvert element, sender du det til en funktion kaldet `dragElement`, som du vil bygge om lidt. Dermed bliver elementet i HTML nu drag-aktiveret, eller vil snart blive det.
✅ Hvorfor refererer vi til elementer via Id? Hvorfor ikke via deres CSS-klasse? Du kan henvise til den tidligere lektion om CSS for at besvare dette spørgsmål.
@ -96,9 +96,9 @@ displayCandy();
console.log(candy)
```
I dette eksempel omgiver `displayCandy`-funktionen en funktion, der tilføjer en ny type slik til en array, der allerede eksisterer i funktionen. Hvis du kører denne kode, vil `candy`-arrayet være undefined, da det er en lokal variabel (lokal for closure).
I dette eksempel omgiver funktionen `displayCandy` en funktion, der tilføjer en ny type slik til en array, der allerede eksisterer i funktionen. Hvis du kører denne kode, vil arrayet `candy` være undefined, da det er en lokal variabel (lokal for closure).
✅ Hvordan kan du gøre `candy`-arrayet tilgængeligt? Prøv at flytte det uden for closure. På denne måde bliver arrayet globalt i stedet for kun at være tilgængeligt i closures lokale scope.
✅ Hvordan kan du gøre arrayet `candy` tilgængeligt? Prøv at flytte det uden for closure. På denne måde bliver arrayet globalt i stedet for kun at være tilgængeligt i closure's lokale scope.
### Opgave
@ -117,15 +117,15 @@ function dragElement(terrariumElement) {
`dragElement` får sit `terrariumElement`-objekt fra deklarationerne øverst i scriptet. Derefter sætter du nogle lokale positioner til `0` for det objekt, der sendes ind i funktionen. Disse er de lokale variabler, der vil blive manipuleret for hvert element, når du tilføjer drag-and-drop-funktionalitet inden for closure til hvert element. Terrariet vil blive fyldt med disse trukne elementer, så applikationen skal holde styr på, hvor de placeres.
Derudover tildeles det `terrariumElement`, der sendes til denne funktion, en `pointerdown`-hændelse, som er en del af [web-API'er](https://developer.mozilla.org/docs/Web/API) designet til at hjælpe med DOM-styring. `onpointerdown` udløses, når en knap trykkes, eller i vores tilfælde, når et trækbart element berøres. Denne event handler fungerer på både [web- og mobilbrowsere](https://caniuse.com/?search=onpointerdown), med få undtagelser.
Derudover tildeles det `terrariumElement`, der sendes til denne funktion, en `pointerdown`-event, som er en del af [web-API'er](https://developer.mozilla.org/docs/Web/API) designet til at hjælpe med DOM-håndtering. `onpointerdown` udløses, når en knap trykkes, eller i vores tilfælde, når et dragbart element berøres. Denne event handler fungerer på både [web- og mobilbrowsere](https://caniuse.com/?search=onpointerdown), med få undtagelser.
✅ [Event handleren `onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) har meget mere understøttelse på tværs af browsere; hvorfor ville du ikke bruge den her? Tænk over den præcise type skærminteraktion, du prøver at skabe her.
✅ [Event handleren `onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) har meget mere støtte på tværs af browsere; hvorfor ville du ikke bruge den her? Tænk over den præcise type skærminteraktion, du prøver at skabe her.
---
## Pointerdrag-funktionen
`terrariumElement` er klar til at blive trukket rundt; når `onpointerdown`-hændelsen udløses, kaldes funktionen `pointerDrag`. Tilføj den funktion lige under denne linje: `terrariumElement.onpointerdown = pointerDrag;`:
`terrariumElement` er klar til at blive trukket rundt; når `onpointerdown`-eventen udløses, kaldes funktionen `pointerDrag`. Tilføj den funktion lige under denne linje: `terrariumElement.onpointerdown = pointerDrag;`:
### Opgave
@ -138,27 +138,27 @@ function pointerDrag(e) {
}
```
Flere ting sker. Først forhindrer du de standardhændelser, der normalt sker ved pointerdown, i at finde sted ved at bruge `e.preventDefault();`. På denne måde har du mere kontrol over grænsefladens adfærd.
Flere ting sker. Først forhindrer du de standardevents, der normalt sker ved pointerdown, i at finde sted ved at bruge `e.preventDefault();`. På denne måde har du mere kontrol over grænsefladens opførsel.
> Vend tilbage til denne linje, når du har bygget scriptfilen helt, og prøv det uden `e.preventDefault()` - hvad sker der?
For det andet skal du åbne `index.html` i et browservindue og inspicere grænsefladen. Når du klikker på en plante, kan du se, hvordan 'e'-hændelsen fanges. Undersøg hændelsen for at se, hvor meget information der indsamles ved én pointerdown-hændelse!
For det andet skal du åbne `index.html` i et browservindue og inspicere grænsefladen. Når du klikker på en plante, kan du se, hvordan 'e'-eventen fanges. Undersøg eventen for at se, hvor meget information der indsamles ved én pointerdown-event!
Dernæst skal du bemærke, hvordan de lokale variabler `pos3` og `pos4` sættes til e.clientX. Du kan finde `e`-værdierne i inspektionspanelet. Disse værdier fanger plantens x- og y-koordinater i det øjeblik, du klikker på den eller rører ved den. Du vil have fin kontrol over planternes adfærd, når du klikker og trækker dem, så du holder styr på deres koordinater.
Dernæst bemærk, hvordan de lokale variabler `pos3` og `pos4` sættes til e.clientX. Du kan finde `e`-værdierne i inspektionspanelet. Disse værdier fanger plantens x- og y-koordinater i det øjeblik, du klikker på eller berører den. Du vil have fin kontrol over planternes opførsel, når du klikker og trækker dem, så du holder styr på deres koordinater.
✅ Bliver det mere klart, hvorfor hele denne app er bygget med én stor closure? Hvis den ikke var det, hvordan ville du opretholde scope for hver af de 14 trækbare planter?
✅ Bliver det mere klart, hvorfor hele denne app er bygget med én stor closure? Hvis den ikke var det, hvordan ville du opretholde scope for hver af de 14 dragbare planter?
Fuldfør den indledende funktion ved at tilføje to flere pointer-hændelsesmanipulationer under `pos4 = e.clientY`:
Fuldfør den indledende funktion ved at tilføje to mere pointer-event-manipulationer under `pos4 = e.clientY`:
```html
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
```
Nu angiver du, at du vil have planten til at blive trukket med pointeren, mens du flytter den, og at trækgesten skal stoppe, når du fravælger planten. `onpointermove` og `onpointerup` er alle dele af den samme API som `onpointerdown`. Grænsefladen vil nu kaste fejl, da du endnu ikke har defineret funktionerne `elementDrag` og `stopElementDrag`, så byg dem ud næste gang.
Nu angiver du, at du vil have planten til at blive trukket med pointeren, mens du bevæger den, og at trækbevægelserne skal stoppe, når du fravælger planten. `onpointermove` og `onpointerup` er alle dele af den samme API som `onpointerdown`. Grænsefladen vil nu kaste fejl, da du endnu ikke har defineret funktionerne `elementDrag` og `stopElementDrag`, så byg dem ud næste gang.
## Funktionerne elementDrag og stopElementDrag
Du vil fuldføre din closure ved at tilføje to flere interne funktioner, der håndterer, hvad der sker, når du trækker en plante og stopper med at trække den. Den adfærd, du ønsker, er, at du kan trække enhver plante til enhver tid og placere den hvor som helst på skærmen. Denne grænseflade er ret uformel (der er f.eks. ingen drop zone) for at give dig mulighed for at designe dit terrarium præcis, som du vil, ved at tilføje, fjerne og omplacere planter.
Du vil fuldføre din closure ved at tilføje to flere interne funktioner, der vil håndtere, hvad der sker, når du trækker en plante og stopper med at trække den. Den opførsel, du ønsker, er, at du kan trække enhver plante til enhver tid og placere den hvor som helst på skærmen. Denne grænseflade er ret uopinioneret (der er f.eks. ingen dropzone) for at give dig mulighed for at designe dit terrarium præcis, som du vil, ved at tilføje, fjerne og omplacere planter.
### Opgave
@ -177,11 +177,11 @@ function elementDrag(e) {
```
I denne funktion redigerer du en masse af de oprindelige positioner 1-4, som du satte som lokale variabler i den ydre funktion. Hvad sker der her?
Mens du trækker, tildeler du `pos1` ved at gøre det lig med `pos3` (som du tidligere satte som `e.clientX`) minus den aktuelle `e.clientX`-værdi. Du udfører en lignende operation på `pos2`. Derefter nulstiller du `pos3` og `pos4` til de nye X- og Y-koordinater for elementet. Du kan se disse ændringer i konsollen, mens du trækker. Derefter manipulerer du plantens CSS-stil for at sætte dens nye position baseret på de nye positioner af `pos1` og `pos2`, og beregner plantens top- og venstre X- og Y-koordinater baseret på sammenligningen af dens offset med disse nye positioner.
Mens du trækker, tildeler du `pos1` ved at gøre det lig med `pos3` (som du tidligere satte som `e.clientX`) minus den aktuelle `e.clientX`-værdi. Du udfører en lignende operation på `pos2`. Derefter nulstiller du `pos3` og `pos4` til de nye X- og Y-koordinater for elementet. Du kan se disse ændringer i konsollen, mens du trækker. Derefter manipulerer du plantens CSS-stil for at sætte dens nye position baseret på de nye positioner af `pos1` og `pos2`, og beregner plantens top- og venstre X- og Y-koordinater baseret på sammenligning af dens offset med disse nye positioner.
> `offsetTop` og `offsetLeft` er CSS-egenskaber, der sætter et elements position baseret på dets forælder; dets forælder kan være ethvert element, der ikke er positioneret som `static`.
Al denne genberegning af positioner giver dig mulighed for at finjustere terrariets og planternes adfærd.
Alle disse genberegninger af positioner giver dig mulighed for at finjustere terrariets og planternes opførsel.
### Opgave
@ -194,9 +194,9 @@ function stopElementDrag() {
}
```
Denne lille funktion nulstiller `onpointerup`- og `onpointermove`-hændelserne, så du enten kan genstarte plantens fremgang ved at begynde at trække den igen, eller begynde at trække en ny plante.
Denne lille funktion nulstiller `onpointerup`- og `onpointermove`-events, så du enten kan genstarte plantens fremgang ved at begynde at trække den igen, eller begynde at trække en ny plante.
✅ Hvad sker der, hvis du ikke sætter disse hændelser til null?
✅ Hvad sker der, hvis du ikke sætter disse events til null?
Nu har du fuldført dit projekt!
@ -206,7 +206,7 @@ Nu har du fuldført dit projekt!
## 🚀Udfordring
Tilføj en ny event handler til din closure for at gøre noget mere med planterne; for eksempel dobbeltklik på en plante for at bringe den foran. Bliv kreativ!
Tilføj en ny event handler til din closure for at gøre noget mere med planterne; for eksempel dobbeltklik på en plante for at bringe den foran. Vær kreativ!
## Quiz efter lektionen
@ -216,7 +216,7 @@ Tilføj en ny event handler til din closure for at gøre noget mere med plantern
Selvom det virker trivielt at trække elementer rundt på skærmen, er der mange måder at gøre dette på og mange faldgruber, afhængigt af den effekt, du søger. Faktisk er der en hel [drag and drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API), som du kan prøve. Vi brugte den ikke i dette modul, fordi den effekt, vi ønskede, var lidt anderledes, men prøv denne API på dit eget projekt og se, hvad du kan opnå.
Find mere information om pointer-hændelser på [W3C-dokumentation](https://www.w3.org/TR/pointerevents1/) og på [MDN web docs](https://developer.mozilla.org/docs/Web/API/Pointer_events).
Find mere information om pointer-events på [W3C-dokumentation](https://www.w3.org/TR/pointerevents1/) og på [MDN web docs](https://developer.mozilla.org/docs/Web/API/Pointer_events).
Tjek altid browserkapabiliteter ved hjælp af [CanIUse.com](https://caniuse.com/).
@ -227,4 +227,4 @@ Tjek altid browserkapabiliteter ved hjælp af [CanIUse.com](https://caniuse.com/
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,13 +1,13 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e982871b8388c59c22a41b73b5fca70f",
"translation_date": "2025-08-26T23:17:45+00:00",
"original_hash": "1b0aeccb600f83c603cd70cb42df594d",
"translation_date": "2025-08-29T08:21:53+00:00",
"source_file": "4-typing-game/typing-game/README.md",
"language_code": "da"
}
-->
# Opret et spil ved hjælp af events
# Oprettelse af et spil ved hjælp af events
## Quiz før forelæsning
@ -15,40 +15,40 @@ CO_OP_TRANSLATOR_METADATA:
## Event-drevet programmering
Når vi opretter en browserbaseret applikation, giver vi en grafisk brugergrænseflade (GUI) til brugeren, som de kan bruge til at interagere med det, vi har bygget. Den mest almindelige måde at interagere med browseren på er ved at klikke og skrive i forskellige elementer. Udfordringen, vi står over for som udviklere, er, at vi ikke ved, hvornår de vil udføre disse handlinger!
Når vi skaber en browserbaseret applikation, leverer vi en grafisk brugergrænseflade (GUI), som brugeren kan bruge til at interagere med det, vi har bygget. Den mest almindelige måde at interagere med browseren på er ved at klikke og skrive i forskellige elementer. Udfordringen som udvikler er, at vi ikke ved, hvornår de vil udføre disse handlinger!
[Event-drevet programmering](https://en.wikipedia.org/wiki/Event-driven_programming) er navnet på den type programmering, vi skal bruge for at oprette vores GUI. Hvis vi bryder denne sætning lidt ned, ser vi, at det centrale ord her er **event**. [Event](https://www.merriam-webster.com/dictionary/event), ifølge Merriam-Webster, er defineret som "noget, der sker". Dette beskriver vores situation perfekt. Vi ved, at noget vil ske, som vi ønsker at udføre kode som svar på, men vi ved ikke, hvornår det vil finde sted.
[Event-drevet programmering](https://en.wikipedia.org/wiki/Event-driven_programming) er navnet på den type programmering, vi skal bruge for at skabe vores GUI. Hvis vi bryder denne sætning lidt ned, ser vi, at kerneordet her er **event**. [Event](https://www.merriam-webster.com/dictionary/event), ifølge Merriam-Webster, defineres som "noget, der sker". Dette beskriver vores situation perfekt. Vi ved, at noget vil ske, som vi ønsker at udføre kode som svar på, men vi ved ikke, hvornår det vil finde sted.
Måden, vi markerer en sektion af kode, vi ønsker at udføre, er ved at oprette en funktion. Når vi tænker på [procedureprogrammering](https://en.wikipedia.org/wiki/Procedural_programming), kaldes funktioner i en specifik rækkefølge. Det samme gælder for event-drevet programmering. Forskellen er **hvordan** funktionerne kaldes.
For at håndtere events (knapklik, indtastning osv.) registrerer vi **event listeners**. En event listener er en funktion, der lytter efter, at en event opstår, og udfører noget som svar. Event listeners kan opdatere UI, foretage kald til serveren eller hvad der ellers skal gøres som svar på brugerens handling. Vi tilføjer en event listener ved at bruge [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) og angive en funktion, der skal udføres.
> **NOTE:** Det er værd at fremhæve, at der er mange måder at oprette event listeners på. Du kan bruge anonyme funktioner eller oprette navngivne. Du kan bruge forskellige genveje, som at indstille `click`-egenskaben eller bruge `addEventListener`. I vores øvelse vil vi fokusere på `addEventListener` og anonyme funktioner, da det sandsynligvis er den mest almindelige teknik, webudviklere bruger. Det er også den mest fleksible, da `addEventListener` fungerer for alle events, og event-navnet kan angives som en parameter.
> **NOTE:** Det er værd at fremhæve, at der er mange måder at oprette event listeners på. Du kan bruge anonyme funktioner eller oprette navngivne funktioner. Du kan bruge forskellige genveje, som at sætte `click`-egenskaben eller bruge `addEventListener`. I vores øvelse vil vi fokusere på `addEventListener` og anonyme funktioner, da det sandsynligvis er den mest almindelige teknik, webudviklere bruger. Det er også den mest fleksible, da `addEventListener` fungerer for alle events, og event-navnet kan angives som en parameter.
### Almindelige events
Der er [masser af events](https://developer.mozilla.org/docs/Web/Events), du kan lytte til, når du opretter en applikation. Grundlæggende hæver alt, hvad en bruger gør på en side, en event, hvilket giver dig stor magt til at sikre, at de får den oplevelse, du ønsker. Heldigvis vil du normalt kun have brug for en lille håndfuld events. Her er nogle almindelige (inklusive de to, vi vil bruge, når vi opretter vores spil):
Der er [mange events](https://developer.mozilla.org/docs/Web/Events) tilgængelige, som du kan lytte til, når du opretter en applikation. Grundlæggende udløser alt, hvad en bruger gør på en side, en event, hvilket giver dig stor magt til at sikre, at de får den oplevelse, du ønsker. Heldigvis har du normalt kun brug for en lille håndfuld events. Her er nogle almindelige (inklusive de to, vi vil bruge, når vi opretter vores spil):
- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event): Brugeren klikkede på noget, typisk en knap eller hyperlink
- [contextmenu](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event): Brugeren klikkede med højre museknap
- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event): Brugeren klikkede på noget, typisk en knap eller et hyperlink
- [contextmenu](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event): Brugeren klikkede højre museknap
- [select](https://developer.mozilla.org/docs/Web/API/Element/select_event): Brugeren markerede noget tekst
- [input](https://developer.mozilla.org/docs/Web/API/Element/input_event): Brugeren indtastede noget tekst
## Opret spillet
## Oprettelse af spillet
Vi skal oprette et spil for at udforske, hvordan events fungerer i JavaScript. Vores spil vil teste en spillers skrivefærdigheder, som er en af de mest undervurderede færdigheder, alle udviklere bør have. Vi bør alle øve os på at skrive! Den generelle flow af spillet vil se sådan ud:
Vi skal oprette et spil for at udforske, hvordan events fungerer i JavaScript. Vores spil vil teste en spillers skrivefærdigheder, som er en af de mest undervurderede færdigheder, alle udviklere bør have. Vi bør alle øve os i at skrive! Den generelle spilflow vil se sådan ud:
- Spilleren klikker på startknappen og præsenteres for et citat, de skal skrive
- Spilleren skriver citatet så hurtigt som muligt i en tekstboks
- Når hvert ord er færdigt, fremhæves det næste
- Hvis spilleren laver en tastefejl, opdateres tekstboksen til rød
- Når hvert ord er færdiggjort, fremhæves det næste
- Hvis spilleren laver en tastefejl, bliver tekstboksen rød
- Når spilleren fuldfører citatet, vises en succesmeddelelse med den forløbne tid
Lad os bygge vores spil og lære om events!
### Filstruktur
Vi skal bruge i alt tre filer: **index.html**, **script.js** og **style.css**. Lad os starte med at opsætte dem for at gøre livet lidt lettere for os.
Vi skal bruge i alt tre filer: **index.html**, **script.js** og **style.css**. Lad os starte med at sætte dem op for at gøre livet lidt lettere for os.
- Opret en ny mappe til dit arbejde ved at åbne en konsol eller terminal og udføre følgende kommando:
@ -73,14 +73,14 @@ code .
## Opret brugergrænsefladen
Hvis vi undersøger kravene, ved vi, at vi skal bruge en håndfuld elementer på vores HTML-side. Dette er lidt som en opskrift, hvor vi har brug for nogle ingredienser:
Hvis vi ser kravene, ved vi, at vi skal bruge en håndfuld elementer på vores HTML-side. Dette er lidt som en opskrift, hvor vi har brug for nogle ingredienser:
- Et sted at vise citatet, som brugeren skal skrive
- Et sted at vise meddelelser, som en succesmeddelelse
- En tekstboks til indtastning
- En startknap
Hvert af disse vil have brug for IDs, så vi kan arbejde med dem i vores JavaScript. Vi vil også tilføje referencer til de CSS- og JavaScript-filer, vi skal oprette.
Hvert af disse elementer skal have ID'er, så vi kan arbejde med dem i vores JavaScript. Vi tilføjer også referencer til de CSS- og JavaScript-filer, vi skal oprette.
Opret en ny fil med navnet **index.html**. Tilføj følgende HTML:
@ -107,16 +107,16 @@ Opret en ny fil med navnet **index.html**. Tilføj følgende HTML:
### Start applikationen
Det er altid bedst at udvikle iterativt for at se, hvordan tingene ser ud. Lad os starte vores applikation. Der er en fantastisk udvidelse til Visual Studio Code kaldet [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), som både vil hoste din applikation lokalt og opdatere browseren hver gang du gemmer.
Det er altid bedst at udvikle iterativt for at se, hvordan tingene ser ud. Lad os starte vores applikation. Der er en fantastisk udvidelse til Visual Studio Code kaldet [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), som både hoster din applikation lokalt og opdaterer browseren, hver gang du gemmer.
- Installer [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) ved at følge linket og klikke på **Install**
- Du vil blive bedt om at åbne Visual Studio Code via browseren og derefter af Visual Studio Code om at udføre installationen
- Du vil blive bedt om at åbne Visual Studio Code via browseren og derefter udføre installationen i Visual Studio Code
- Genstart Visual Studio Code, hvis det bliver bedt om det
- Når det er installeret, klik Ctrl-Shift-P (eller Cmd-Shift-P) i Visual Studio Code for at åbne kommandopaletten
- Når det er installeret, skal du i Visual Studio Code trykke på Ctrl-Shift-P (eller Cmd-Shift-P) for at åbne kommandopaletten
- Skriv **Live Server: Open with Live Server**
- Live Server vil begynde at hoste din applikation
- Åbn en browser og naviger til **https://localhost:5500**
- Du bør nu se den side, du har oprettet!
- Du skulle nu kunne se den side, du har oprettet!
Lad os tilføje noget funktionalitet.
@ -138,7 +138,7 @@ Opret en ny fil med navnet **style.css**, og tilføj følgende syntaks.
}
```
✅ Når det kommer til CSS, kan du layout din side, som du vil. Brug lidt tid på at gøre siden mere tiltalende:
✅ Når det kommer til CSS, kan du designe din side, som du vil. Brug lidt tid på at gøre siden mere tiltalende:
- Vælg en anden skrifttype
- Farvelæg overskrifterne
@ -146,24 +146,24 @@ Opret en ny fil med navnet **style.css**, og tilføj følgende syntaks.
## JavaScript
Med vores UI oprettet er det tid til at fokusere på JavaScript, som vil give logikken. Vi vil opdele dette i en håndfuld trin:
Med vores UI oprettet er det tid til at fokusere på JavaScript, som vil levere logikken. Vi vil opdele dette i en håndfuld trin:
- [Opret konstanterne](../../../../4-typing-game/typing-game)
- [Event listener til at starte spillet](../../../../4-typing-game/typing-game)
- [Event listener til indtastning](../../../../4-typing-game/typing-game)
Men først, opret en ny fil med navnet **script.js**.
Men først skal du oprette en ny fil med navnet **script.js**.
### Tilføj konstanterne
Vi skal bruge nogle elementer for at gøre vores programmering lidt lettere. Igen, ligesom en opskrift, her er hvad vi skal bruge:
Vi skal bruge nogle elementer for at gøre vores programmering lettere. Igen, ligesom en opskrift, her er hvad vi skal bruge:
- Array med listen over alle citater
- Tomt array til at gemme alle ordene for det aktuelle citat
- Plads til at gemme indekset for det ord, spilleren aktuelt skriver
- Tiden, spilleren klikkede på start
- En array med listen over alle citater
- En tom array til at gemme alle ordene for det aktuelle citat
- Et sted til at gemme indekset for det ord, spilleren aktuelt skriver
- Tiden, hvor spilleren klikkede på start
Vi vil også have referencer til UI-elementerne:
Vi skal også have referencer til UI-elementerne:
- Tekstboksen (**typed-value**)
- Citatvisningen (**quote**)
@ -194,9 +194,9 @@ const typedValueElement = document.getElementById('typed-value');
✅ Tilføj flere citater til dit spil
> **NOTE:** Vi kan hente elementerne, når vi vil i koden, ved at bruge `document.getElementById`. Fordi vi regelmæssigt vil referere til disse elementer, undgår vi tastefejl med strenglitteraler ved at bruge konstanter. Frameworks som [Vue.js](https://vuejs.org/) eller [React](https://reactjs.org/) kan hjælpe dig med bedre at centralisere din kode.
> **NOTE:** Vi kan hente elementerne, når som helst vi vil i koden, ved at bruge `document.getElementById`. Fordi vi ofte vil referere til disse elementer, undgår vi tastefejl med strenglitteraler ved at bruge konstanter. Frameworks som [Vue.js](https://vuejs.org/) eller [React](https://reactjs.org/) kan hjælpe dig med bedre at centralisere din kode.
Tag et øjeblik til at se en video om brugen af `const`, `let` og `var`
Tag et øjeblik til at se en video om brugen af `const`, `let` og `var`.
[![Typer af variabler](https://img.youtube.com/vi/JNIXfGiDWM8/0.jpg)](https://youtube.com/watch?v=JNIXfGiDWM8 "Typer af variabler")
@ -204,9 +204,9 @@ Tag et øjeblik til at se en video om brugen af `const`, `let` og `var`
### Tilføj startlogik
For at starte spillet vil spilleren klikke på start. Selvfølgelig ved vi ikke, hvornår de vil klikke på start. Dette er, hvor en [event listener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) kommer i spil. En event listener giver os mulighed for at lytte efter, at noget sker (en event) og udføre kode som svar. I vores tilfælde ønsker vi at udføre kode, når brugeren klikker på start.
For at starte spillet vil spilleren klikke på start. Selvfølgelig ved vi ikke, hvornår de vil klikke på start. Dette er, hvor en [event listener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) kommer i spil. En event listener giver os mulighed for at lytte efter, at noget sker (en event), og udføre kode som svar. I vores tilfælde ønsker vi at udføre kode, når brugeren klikker på start.
Når brugeren klikker på **start**, skal vi vælge et citat, opsætte brugergrænsefladen og opsætte sporing for det aktuelle ord og timing. Nedenfor er den JavaScript, du skal tilføje; vi diskuterer det lige efter scriptblokken.
Når brugeren klikker på **start**, skal vi vælge et citat, opsætte brugergrænsefladen og opsætte sporing for det aktuelle ord og tidtagning. Nedenfor er den JavaScript, du skal tilføje; vi diskuterer det lige efter scriptblokken.
```javascript
// at the end of script.js
@ -245,23 +245,23 @@ Lad os bryde koden ned!
- Opsætning af ordsporing
- Brug af [Math.floor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) og [Math.random](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random) giver os mulighed for tilfældigt at vælge et citat fra `quotes`-arrayet
- Vi konverterer `quote` til et array af `words`, så vi kan spore det ord, spilleren aktuelt skriver
- Vi konverterer `quote` til en array af `words`, så vi kan spore det ord, spilleren aktuelt skriver
- `wordIndex` sættes til 0, da spilleren starter med det første ord
- Opsætning af UI
- Opret et array af `spanWords`, som indeholder hvert ord inde i et `span`-element
- Dette giver os mulighed for at fremhæve ordet på displayet
- `join` arrayet for at oprette en streng, som vi kan bruge til at opdatere `innerHTML``quoteElement`
- Opret en array af `spanWords`, som indeholder hvert ord inde i et `span`-element
- Dette giver os mulighed for at fremhæve ordet på skærmen
- `join` arrayet for at skabe en streng, som vi kan bruge til at opdatere `innerHTML``quoteElement`
- Dette vil vise citatet til spilleren
- Indstil `className` for det første `span`-element til `highlight` for at fremhæve det som gult
- Rens `messageElement` ved at indstille `innerText` til `''`
- Sæt `className` for det første `span`-element til `highlight` for at fremhæve det som gult
- Rens `messageElement` ved at sætte `innerText` til `''`
- Opsætning af tekstboksen
- Ryd den aktuelle `value``typedValueElement`
- Indstil `focus` til `typedValueElement`
- Sæt `focus` til `typedValueElement`
- Start timeren ved at kalde `getTime`
### Tilføj indtastningslogik
Når spilleren skriver, vil en `input`-event blive rejst. Denne event listener vil kontrollere, om spilleren skriver ordet korrekt, og håndtere spillets aktuelle status. Vend tilbage til **script.js**, og tilføj følgende kode til slutningen. Vi vil bryde det ned bagefter.
Når spilleren skriver, vil en `input`-event blive udløst. Denne event listener vil kontrollere, om spilleren skriver ordet korrekt, og håndtere spillets aktuelle status. Tilføj følgende kode til slutningen af **script.js**. Vi vil bryde det ned bagefter.
```javascript
// at the end of script.js
@ -300,27 +300,27 @@ typedValueElement.addEventListener('input', () => {
});
```
Lad os bryde koden ned! Vi starter med at hente det aktuelle ord og den værdi, spilleren har skrevet indtil videre. Derefter har vi en vandfaldslogik, hvor vi kontrollerer, om citatet er fuldført, ordet er fuldført, ordet er korrekt, eller (endelig), om der er en fejl.
Lad os bryde koden ned! Vi starter med at hente det aktuelle ord og den værdi, spilleren har skrevet indtil videre. Derefter har vi en kaskadelogik, hvor vi tjekker, om citatet er fuldført, ordet er fuldført, ordet er korrekt, eller (endelig), om der er en fejl.
- Citatet er fuldført, angivet ved at `typedValue` er lig med `currentWord`, og `wordIndex` er lig med en mindre end `length` af `words`
- Citatet er fuldført, angivet ved, at `typedValue` er lig med `currentWord`, og `wordIndex` er lig med en mindre end længden af `words`
- Beregn `elapsedTime` ved at trække `startTime` fra den aktuelle tid
- Divider `elapsedTime` med 1.000 for at konvertere fra millisekunder til sekunder
- Vis en succesmeddelelse
- Ordet er fuldført, angivet ved at `typedValue` slutter med et mellemrum (slutningen af et ord) og `typedValue` er lig med `currentWord`
- Indstil `value``typedElement` til `''` for at tillade, at det næste ord kan skrives
- Ordet er fuldført, angivet ved, at `typedValue` slutter med et mellemrum (slutningen af et ord), og `typedValue` er lig med `currentWord`
- Sæt `value``typedElement` til `''` for at tillade, at det næste ord kan skrives
- Inkrementer `wordIndex` for at gå videre til det næste ord
- Loop gennem alle `childNodes` af `quoteElement` for at indstille `className` til `''` for at vende tilbage til standardvisning
- Indstil `className` for det aktuelle ord til `highlight` for at markere det som det næste ord, der skal skrives
- Ordet er aktuelt skrevet korrekt (men ikke fuldført), angivet ved at `currentWord` starter med `typedValue`
- Gennemgå alle `childNodes` af `quoteElement` for at sætte `className` til `''` for at vende tilbage til standardvisning
- Sæt `className` for det aktuelle ord til `highlight` for at markere det som det næste ord, der skal skrives
- Ordet er aktuelt skrevet korrekt (men ikke fuldført), angivet ved, at `currentWord` starter med `typedValue`
- Sørg for, at `typedValueElement` vises som standard ved at rydde `className`
- Hvis vi er nået hertil, har vi en fejl
- Indstil `className``typedValueElement` til `error`
- Sæt `className``typedValueElement` til `error`
## Test din applikation
Du er nået til slutningen! Det sidste trin er at sikre, at vores applikation fungerer. Prøv det! Vær ikke bekymret, hvis der er fejl; **alle udviklere** har fejl. Undersøg meddelelserne og debug efter behov.
Du er nået til slutningen! Det sidste trin er at sikre, at vores applikation fungerer. Prøv det! Vær ikke bekymret, hvis der er fejl; **alle udviklere** oplever fejl. Undersøg meddelelserne og fejlret efter behov.
Klik på **start**, og begynd at skrive! Det skulle se lidt ud som animationen, vi så før.
Klik på **start**, og begynd at skrive! Det skulle se lidt ud som animationen, vi så tidligere.
![Animation af spillet i aktion](../../../../4-typing-game/images/demo.gif)
@ -333,21 +333,20 @@ Tilføj mere funktionalitet
- Deaktiver `input`-event listeneren ved fuldførelse, og aktiver den igen, når knappen klikkes
- Deaktiver tekstboksen, når spilleren fuldfører citatet
- Vis en modal dialogboks med succesmeddelelsen
- Gem høje scorer ved hjælp af [localStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage)
- Gem high scores ved hjælp af [localStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage)
## Quiz efter forelæsning
[Quiz efter forelæsning](https://ff-quizzes.netlify.app/web/quiz/22)
## Gennemgang & Selvstudie
Læs om [alle de tilgængelige begivenheder](https://developer.mozilla.org/docs/Web/Events) for udviklere via webbrowseren, og overvej de scenarier, hvor du ville bruge hver enkelt.
Læs om [alle de tilgængelige hændelser](https://developer.mozilla.org/docs/Web/Events) for udviklere via webbrowseren, og overvej de scenarier, hvor du ville bruge hver enkelt.
## Opgave
[Opret et nyt tastaturspil](assignment.md)
[Skab et nyt tastaturspil](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "0bb55e0b98600afab801eea115228873",
"translation_date": "2025-08-26T22:39:25+00:00",
"original_hash": "2326d04e194a10aa760b51f5e5a1f61d",
"translation_date": "2025-08-29T08:09:51+00:00",
"source_file": "5-browser-extension/1-about-browsers/README.md",
"language_code": "da"
}
@ -24,7 +24,7 @@ Browserudvidelser tilføjer ekstra funktionalitet til en browser. Men før du by
I denne lektionsserie lærer du, hvordan du bygger en browserudvidelse, der fungerer på Chrome, Firefox og Edge. I denne del vil du opdage, hvordan browsere fungerer, og hvordan du opbygger elementerne i en browserudvidelse.
Men hvad er en browser egentlig? Det er en softwareapplikation, der giver en slutbruger mulighed for at få adgang til indhold fra en server og vise det på websider.
Men hvad er en browser egentlig? Det er en softwareapplikation, der gør det muligt for en slutbruger at få adgang til indhold fra en server og vise det på websider.
✅ Lidt historie: Den første browser hed 'WorldWideWeb' og blev skabt af Sir Timothy Berners-Lee i 1990.
@ -37,11 +37,11 @@ På dette tidspunkt viser browserens rendering-motor siden på brugerens enhed,
Browsere har også evnen til at cache indhold, så det ikke behøver at blive hentet fra serveren hver gang. De kan registrere en brugers browserhistorik, gemme 'cookies', som er små datastykker, der indeholder information om brugerens aktivitet, og meget mere.
En vigtig ting at huske om browsere er, at de ikke alle er ens! Hver browser har sine styrker og svagheder, og en professionel webudvikler skal forstå, hvordan man får websider til at fungere godt på tværs af browsere. Dette inkluderer at håndtere små skærmstørrelser som en mobiltelefons samt en bruger, der er offline.
En vigtig ting at huske om browsere er, at de ikke alle er ens! Hver browser har sine styrker og svagheder, og en professionel webudvikler skal forstå, hvordan man får websider til at fungere godt på tværs af browsere. Dette inkluderer at håndtere små skærmstørrelser som en mobiltelefons samt brugere, der er offline.
En virkelig nyttig hjemmeside, som du sandsynligvis bør bogmærke i den browser, du foretrækker at bruge, er [caniuse.com](https://www.caniuse.com). Når du bygger websider, er det meget nyttigt at bruge caniuse's lister over understøttede teknologier, så du bedst kan støtte dine brugere.
En virkelig nyttig hjemmeside, som du sandsynligvis bør bogmærke i den browser, du foretrækker at bruge, er [caniuse.com](https://www.caniuse.com). Når du bygger websider, er det meget hjælpsomt at bruge caniuse's lister over understøttede teknologier, så du bedst kan støtte dine brugere.
✅ Hvordan kan du finde ud af, hvilke browsere der er mest populære blandt brugerne af din hjemmeside? Tjek din analyse - du kan installere forskellige analyseværktøjer som en del af din webudviklingsproces, og de vil fortælle dig, hvilke browsere der bruges mest af de forskellige populære browsere.
✅ Hvordan kan du finde ud af, hvilke browsere der er mest populære blandt brugerne af din hjemmeside? Tjek din analytics - du kan installere forskellige analyseværktøjer som en del af din webudviklingsproces, og de vil fortælle dig, hvilke browsere der bruges mest af de forskellige populære browsere.
## Browserudvidelser
@ -70,18 +70,18 @@ I det væsentlige vil processen være:
### Kom i gang
Du skal bygge en browserudvidelse, der viser dit områdes CO2-aftryk, herunder energiforbrug og energikilde. Udvidelsen vil have en formular, der indsamler en API-nøgle, så du kan få adgang til CO2 Signal's API.
Du skal bygge en browserudvidelse, der viser din regions CO2-aftryk, herunder energiforbrug og energikilde. Udvidelsen vil have en formular, der indsamler en API-nøgle, så du kan få adgang til CO2 Signal's API.
**Du skal bruge:**
- [en API-nøgle](https://www.co2signal.com/); indtast din e-mail i boksen på denne side, og en nøgle vil blive sendt til dig
- koden for dit område fra [Electricity Map](http://api.electricitymap.org/v3/zones) (for eksempel bruger jeg 'US-NEISO' i Boston)
- koden for din region fra [Electricity Map](http://api.electricitymap.org/v3/zones) (for eksempel bruger jeg 'US-NEISO' i Boston)
- [startkoden](../../../../5-browser-extension/start). Download `start`-mappen; du skal færdiggøre koden i denne mappe.
- [NPM](https://www.npmjs.com) - NPM er et værktøj til pakkehåndtering; installer det lokalt, og pakkerne, der er angivet i din `package.json`-fil, vil blive installeret til brug i dine webaktiver
- [NPM](https://www.npmjs.com) - NPM er et værktøj til pakkehåndtering; installer det lokalt, og de pakker, der er angivet i din `package.json`-fil, vil blive installeret til brug i dit webprojekt
✅ Lær mere om pakkehåndtering i dette [fremragende Learn-modul](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
Tag et øjeblik til at gennemgå kodebasen:
Tag et øjeblik til at kigge på kodebasen:
dist
-|manifest.json (standardindstillinger her)
@ -91,17 +91,17 @@ dist
src
-|index.js (din JS-kode går her)
✅ Når du har din API-nøgle og områdekode klar, skal du gemme dem et sted som en note til fremtidig brug.
✅ Når du har din API-nøgle og regionskode klar, skal du gemme dem et sted som en note til senere brug.
### Byg HTML til udvidelsen
Denne udvidelse har to visninger. En til at indsamle API-nøglen og områdekoden:
Denne udvidelse har to visninger. En til at indsamle API-nøglen og regionskoden:
![skærmbillede af den færdige udvidelse åbnet i en browser, der viser en formular med inputfelter til områdenavn og API-nøgle.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.da.png)
![skærmbillede af den færdige udvidelse åbnet i en browser, der viser en formular med inputfelter til regionsnavn og API-nøgle.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.da.png)
Og den anden til at vise områdets CO2-forbrug:
Og den anden til at vise regionens CO2-forbrug:
![skærmbillede af den færdige udvidelse, der viser værdier for CO2-forbrug og procentdelen af fossile brændstoffer for US-NEISO-området.](../../../../translated_images/2.1dae52ff0804224692cd648afbf2342955d7afe3b0101b617268130dfb427f55.da.png)
![skærmbillede af den færdige udvidelse, der viser værdier for CO2-forbrug og procentdelen af fossile brændstoffer for regionen US-NEISO.](../../../../translated_images/2.1dae52ff0804224692cd648afbf2342955d7afe3b0101b617268130dfb427f55.da.png)
Lad os starte med at bygge HTML til formularen og style den med CSS.
@ -125,7 +125,7 @@ I `/dist`-mappen skal du bygge en formular og et resultatområde. I `index.html`
```
Dette er formularen, hvor dine gemte oplysninger vil blive indtastet og gemt i lokal lagring.
Opret derefter resultatområdet; under den sidste form-tag skal du tilføje nogle divs:
Dernæst skal du oprette resultatområdet; under den sidste form-tag skal du tilføje nogle divs:
```HTML
<div class="result">
@ -140,13 +140,13 @@ Opret derefter resultatområdet; under den sidste form-tag skal du tilføje nogl
<button class="clear-btn">Change region</button>
</div>
```
På dette tidspunkt kan du prøve at bygge. Sørg for at installere udvidelsens pakkeafhængigheder:
På dette tidspunkt kan du prøve at bygge. Sørg for at installere pakkeafhængighederne for denne udvidelse:
```
npm install
```
Denne kommando vil bruge npm, Node Package Manager, til at installere webpack til din udvidelses byggeproces. Du kan se outputtet af denne proces ved at kigge i `/dist/main.js` - du vil se, at koden er blevet bundlet.
Denne kommando vil bruge npm, Node Package Manager, til at installere webpack til din udvidelses byggeproces. Webpack er en bundler, der håndterer kompilering af kode. Du kan se outputtet af denne proces ved at kigge i `/dist/main.js` - du vil se, at koden er blevet bundlet.
For nu bør udvidelsen bygge, og hvis du implementerer den i Edge som en udvidelse, vil du se en pænt vist formular.
@ -164,7 +164,7 @@ Tag et kig på en browserudvidelsesbutik, og installer en udvidelse i din browse
## Gennemgang & Selvstudie
I denne lektion lærte du lidt om webbrowserens historie; benyt lejligheden til at lære om, hvordan opfinderne af World Wide Web forestillede sig dens brug, ved at læse mere om dens historie. Nogle nyttige sider inkluderer:
I denne lektion lærte du lidt om webbrowserens historie; brug denne mulighed til at lære om, hvordan opfinderne af World Wide Web forestillede sig dens brug ved at læse mere om dens historie. Nogle nyttige sider inkluderer:
[Historien om webbrowsere](https://www.mozilla.org/firefox/browsers/browser-history/)
@ -179,4 +179,4 @@ I denne lektion lærte du lidt om webbrowserens historie; benyt lejligheden til
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,13 +1,13 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e10f168beac4e7b05e30e0eb5c92bf11",
"translation_date": "2025-08-26T22:35:07+00:00",
"original_hash": "a7587943d38d095de8613e1b508609f5",
"translation_date": "2025-08-29T08:12:02+00:00",
"source_file": "5-browser-extension/2-forms-browsers-local-storage/README.md",
"language_code": "da"
}
-->
# Browserudvidelsesprojekt del 2: Kald en API, brug lokal lagring
# Browserudvidelsesprojekt Del 2: Kald en API, brug lokal lagring
## Quiz før lektionen
@ -21,7 +21,7 @@ I denne lektion vil du kalde en API ved at indsende din browserudvidelses formul
### Opsæt elementerne til manipulation i udvidelsen:
På dette tidspunkt har du oprettet HTML til formularen og resultaternes `<div>` for din browserudvidelse. Fra nu af skal du arbejde i filen `/src/index.js` og bygge din udvidelse lidt efter lidt. Henvis til [den forrige lektion](../1-about-browsers/README.md) for at få din projektopsætning og byggeprocessen på plads.
På dette tidspunkt har du opbygget HTML'en til formularen og resultaternes `<div>` for din browserudvidelse. Fra nu af skal du arbejde i filen `/src/index.js` og bygge din udvidelse lidt efter lidt. Henvis til [den forrige lektion](../1-about-browsers/README.md) for at få din projektopsætning og byggeprocessen på plads.
Arbejd i din `index.js`-fil, og start med at oprette nogle `const`-variabler til at holde værdierne forbundet med forskellige felter:
@ -41,11 +41,11 @@ const myregion = document.querySelector('.my-region');
const clearBtn = document.querySelector('.clear-btn');
```
Alle disse felter refereres til via deres CSS-klasse, som du opsatte i HTML i den forrige lektion.
Alle disse felter refereres til via deres CSS-klasse, som du opsatte i HTML'en i den forrige lektion.
### Tilføj lyttere
Tilføj derefter event listeners til formularen og knappen, der nulstiller formularen, så der sker noget, hvis en bruger indsender formularen eller klikker på nulstillingsknappen. Tilføj også kaldet til at initialisere appen nederst i filen:
Tilføj derefter event listeners til formularen og nulstillingsknappen, der nulstiller formularen, så hvis en bruger indsender formularen eller klikker på nulstillingsknappen, sker der noget, og tilføj kaldet til at initialisere appen nederst i filen:
```JavaScript
form.addEventListener('submit', (e) => handleSubmit(e));
@ -53,7 +53,7 @@ clearBtn.addEventListener('click', (e) => reset(e));
init();
```
✅ Bemærk den forkortede metode, der bruges til at lytte efter en submit- eller klikbegivenhed, og hvordan begivenheden sendes til handleSubmit- eller reset-funktionerne. Kan du skrive den tilsvarende lange version af denne forkortelse? Hvilken foretrækker du?
✅ Bemærk den forkortede metode, der bruges til at lytte efter en submit- eller klikbegivenhed, og hvordan begivenheden sendes til handleSubmit- eller reset-funktionerne. Kan du skrive den længere version af denne forkortelse? Hvilken foretrækker du?
### Byg init()-funktionen og reset()-funktionen:
@ -92,10 +92,9 @@ function reset(e) {
}
```
I denne funktion er der noget interessant logik. Når du læser igennem den, kan du se, hvad der sker?
- To `const` oprettes for at tjekke, om brugeren har gemt en APIKey og regionskode i lokal lagring.
- To `const` oprettes for at kontrollere, om brugeren har gemt en APIKey og regionskode i lokal lagring.
- Hvis en af dem er null, vis formularen ved at ændre dens stil til at blive vist som 'block'.
- Skjul resultaterne, loading og clearBtn, og sæt eventuel fejltekst til en tom streng.
- Hvis der findes en nøgle og region, start en rutine for at:
@ -104,19 +103,19 @@ I denne funktion er der noget interessant logik. Når du læser igennem den, kan
- Skjule formularen.
- Vise nulstillingsknappen.
Før du går videre, er det nyttigt at lære om et meget vigtigt koncept, der er tilgængeligt i browsere: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage). LocalStorage er en nyttig måde at gemme strenge i browseren som et `key-value`-par. Denne type webopbevaring kan manipuleres af JavaScript til at administrere data i browseren. LocalStorage udløber ikke, mens SessionStorage, en anden slags webopbevaring, ryddes, når browseren lukkes. De forskellige typer lagring har fordele og ulemper ved deres brug.
Før du går videre, er det nyttigt at lære om et meget vigtigt koncept, der er tilgængeligt i browsere: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage). LocalStorage er en nyttig måde at gemme strenge i browseren som et `key-value`-par. Denne type webopbevaring kan manipuleres af JavaScript til at administrere data i browseren. LocalStorage udløber ikke, mens SessionStorage, en anden slags webopbevaring, ryddes, når browseren lukkes. De forskellige typer opbevaring har fordele og ulemper ved deres brug.
> Bemærk - din browserudvidelse har sin egen lokale lagring; hovedbrowser-vinduet er en anden instans og opfører sig separat.
Du sætter din APIKey til at have en strengværdi, for eksempel, og du kan se, at den er sat i Edge ved at "inspicere" en webside (du kan højreklikke på en browser for at inspicere) og gå til fanen Applications for at se lagringen.
Du sætter din APIKey til at have en strengværdi, for eksempel, og du kan se, at den er sat i Edge ved at "inspicere" en webside (du kan højreklikke på en browser for at inspicere) og gå til fanen Applications for at se opbevaringen.
![Lokallagringspanel](../../../../translated_images/localstorage.472f8147b6a3f8d141d9551c95a2da610ac9a3c6a73d4a1c224081c98bae09d9.da.png)
✅ Tænk over situationer, hvor du IKKE ville ønske at gemme nogle data i LocalStorage. Generelt er det en dårlig idé at placere API-nøgler i LocalStorage! Kan du se hvorfor? I vores tilfælde, da vores app udelukkende er til læring og ikke vil blive udgivet i en app-butik, vil vi bruge denne metode.
✅ Tænk over situationer, hvor du IKKE ville ønske at gemme nogle data i LocalStorage. Generelt er det en dårlig idé at placere APIKeys i LocalStorage! Kan du se hvorfor? I vores tilfælde, da vores app udelukkende er til læring og ikke vil blive udgivet i en app-butik, vil vi bruge denne metode.
Bemærk, at du bruger Web API til at manipulere LocalStorage, enten ved at bruge `getItem()`, `setItem()` eller `removeItem()`. Det er bredt understøttet på tværs af browsere.
Bemærk, at du bruger Web API'en til at manipulere LocalStorage, enten ved at bruge `getItem()`, `setItem()` eller `removeItem()`. Det er bredt understøttet på tværs af browsere.
Før du bygger `displayCarbonUsage()`-funktionen, der kaldes i `init()`, lad os bygge funktionaliteten til at håndtere den indledende formularindsendelse.
Før du bygger funktionen `displayCarbonUsage()`, der kaldes i `init()`, lad os bygge funktionaliteten til at håndtere den indledende formularindsendelse.
### Håndter formularindsendelsen
@ -128,12 +127,11 @@ function handleSubmit(e) {
setUpUser(apiKey.value, region.value);
}
```
✅ Frisk din hukommelse op - HTML'en, du opsatte i den sidste lektion, har to inputfelter, hvis `values` fanges via de `const`, du opsatte øverst i filen, og de er begge `required`, så browseren forhindrer brugere i at indtaste null-værdier.
✅ Frisk din hukommelse op - HTML'en, du opsatte i den sidste lektion, har to inputfelter, hvis `values` fanges via de `const`, du opsatte øverst i filen, og de er begge `required`, så browseren stopper brugere fra at indtaste null-værdier.
### Opsæt brugeren
Videre til `setUpUser`-funktionen, her sætter du værdier for lokal lagring for apiKey og regionName. Tilføj en ny funktion:
Videre til funktionen `setUpUser`, her sætter du værdier for lokal lagring for apiKey og regionName. Tilføj en ny funktion:
```JavaScript
function setUpUser(apiKey, regionName) {
@ -146,20 +144,19 @@ function setUpUser(apiKey, regionName) {
displayCarbonUsage(apiKey, regionName);
}
```
Denne funktion viser en loading-besked, mens API'en kaldes. På dette tidspunkt er du nået til at oprette den vigtigste funktion i denne browserudvidelse!
### Vis kulstofbrug
Endelig er det tid til at forespørge API'en!
Før vi går videre, bør vi diskutere API'er. API'er, eller [Application Programming Interfaces](https://www.webopedia.com/TERM/A/API.html), er et kritisk element i en webudviklers værktøjskasse. De giver standardmåder for programmer til at interagere og grænseflade med hinanden. For eksempel, hvis du bygger en hjemmeside, der skal forespørge en database, kan nogen have oprettet en API, du kan bruge. Mens der findes mange typer API'er, er en af de mest populære en [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
Før vi går videre, bør vi diskutere API'er. API'er, eller [Application Programming Interfaces](https://www.webopedia.com/TERM/A/API.html), er et kritisk element i en webudviklers værktøjskasse. De giver standardmåder for programmer at interagere og grænseflade med hinanden. For eksempel, hvis du bygger en hjemmeside, der skal forespørge en database, kan nogen have oprettet en API, du kan bruge. Mens der findes mange typer API'er, er en af de mest populære en [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
✅ Udtrykket 'REST' står for 'Representational State Transfer' og indebærer brug af forskelligt konfigurerede URL'er til at hente data. Lav lidt research om de forskellige typer API'er, der er tilgængelige for udviklere. Hvilket format tiltaler dig?
✅ Udtrykket 'REST' står for 'Representational State Transfer' og indebærer brugen af forskellige konfigurerede URL'er til at hente data. Lav lidt research om de forskellige typer API'er, der er tilgængelige for udviklere. Hvilket format tiltaler dig?
Der er vigtige ting at bemærke om denne funktion. Først, bemærk [`async`-nøgleordet](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). At skrive dine funktioner, så de kører asynkront, betyder, at de venter på, at en handling, såsom data, der returneres, bliver fuldført, før de fortsætter.
Der er vigtige ting at bemærke om denne funktion. Først, bemærk nøgleordet [`async`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). At skrive dine funktioner, så de kører asynkront, betyder, at de venter på en handling, såsom at data returneres, før de fortsætter.
Her er en hurtig video om `async`:
Her er en kort video om `async`:
[![Async og Await til håndtering af promises](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async og Await til håndtering af promises")
@ -207,8 +204,8 @@ async function displayCarbonUsage(apiKey, region) {
Dette er en stor funktion. Hvad sker der her?
- Efter bedste praksis bruger du et `async`-nøgleord for at få denne funktion til at opføre sig asynkront. Funktionen indeholder et `try/catch`-blok, da den vil returnere et løfte, når API'en returnerer data. Fordi du ikke har kontrol over hastigheden, som API'en vil svare med (den kan muligvis slet ikke svare!), skal du håndtere denne usikkerhed ved at kalde den asynkront.
- Du forespørger co2signal API'en for at få data om din region ved hjælp af din APIKey. For at bruge den nøgle skal du bruge en type autentificering i dine header-parametre.
- I overensstemmelse med bedste praksis bruger du nøgleordet `async` for at få denne funktion til at opføre sig asynkront. Funktionen indeholder et `try/catch`-blok, da den vil returnere et løfte, når API'en returnerer data. Fordi du ikke har kontrol over hastigheden, som API'en vil svare med (den kan muligvis slet ikke svare!), skal du håndtere denne usikkerhed ved at kalde den asynkront.
- Du forespørger co2signal API'en for at få data om din regions kulstofbrug ved hjælp af din APIKey. For at bruge den nøgle skal du bruge en type autentificering i dine header-parametre.
- Når API'en svarer, tildeler du forskellige elementer af dens responsdata til de dele af din skærm, du opsatte til at vise disse data.
- Hvis der opstår en fejl, eller hvis der ikke er noget resultat, viser du en fejlmeddelelse.
@ -220,7 +217,7 @@ Tillykke! Hvis du bygger din udvidelse (`npm run build`) og opdaterer den i din
## 🚀 Udfordring
Vi har diskuteret flere typer API'er indtil videre i disse lektioner. Vælg en web-API og undersøg i dybden, hvad den tilbyder. For eksempel, kig på API'er, der er tilgængelige i browsere, såsom [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API). Hvad gør en API fremragende efter din mening?
Vi har diskuteret flere typer API'er indtil videre i disse lektioner. Vælg en web-API og undersøg i dybden, hvad den tilbyder. For eksempel, tag et kig på API'er, der er tilgængelige i browsere, såsom [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API). Hvad gør en API fantastisk efter din mening?
## Quiz efter lektionen
@ -232,9 +229,9 @@ Du lærte om LocalStorage og API'er i denne lektion, begge meget nyttige for den
## Opgave
[Adoptér en API](assignment.md)
[Adopt an API](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,43 +1,43 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "f198c6b817b4b2a99749f4662e7cae98",
"translation_date": "2025-08-26T22:44:12+00:00",
"original_hash": "49b58721a71cfda824e2f3e1f46908c6",
"translation_date": "2025-08-29T08:11:30+00:00",
"source_file": "5-browser-extension/3-background-tasks-and-performance/README.md",
"language_code": "da"
}
-->
# Browserudvidelsesprojekt Del 3: Lær om baggrundsopgaver og ydeevne
# Browserudvidelsesprojekt Del 3: Lær om Baggrundsopgaver og Ydeevne
## Quiz før lektionen
## Quiz før forelæsning
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/27)
[Quiz før forelæsning](https://ff-quizzes.netlify.app/web/quiz/27)
### Introduktion
I de sidste to lektioner i dette modul lærte du, hvordan man bygger en formular og et visningsområde til data hentet fra en API. Det er en meget standard måde at skabe en webtilstedeværelse på nettet. Du lærte endda, hvordan man håndterer asynkron datahentning. Din browserudvidelse er næsten færdig.
I de sidste to lektioner af dette modul lærte du, hvordan man bygger en formular og et visningsområde til data hentet fra en API. Det er en meget standard måde at skabe en webtilstedeværelse på nettet. Du lærte endda, hvordan man håndterer asynkron datahentning. Din browserudvidelse er næsten færdig.
Det, der mangler, er at håndtere nogle baggrundsopgaver, herunder opdatering af farven på udvidelsens ikon. Derfor er det et godt tidspunkt at tale om, hvordan browseren håndterer denne type opgaver. Lad os tænke på disse browseropgaver i konteksten af ydeevnen for dine webressourcer, mens du bygger dem.
Det, der mangler, er at håndtere nogle baggrundsopgaver, herunder at opdatere farven på udvidelsens ikon. Dette er derfor et godt tidspunkt at tale om, hvordan browseren håndterer denne type opgaver. Lad os tænke på disse browseropgaver i sammenhæng med ydeevnen af dine webressourcer, mens du bygger dem.
## Grundlæggende om webydeevne
> "Webstedets ydeevne handler om to ting: hvor hurtigt siden indlæses, og hvor hurtigt koden på den kører." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
Emnet om, hvordan man gør sine websites lynhurtige på alle slags enheder, for alle slags brugere, i alle slags situationer, er ikke overraskende omfattende. Her er nogle punkter at huske på, når du bygger enten et standard webprojekt eller en browserudvidelse.
Emnet om, hvordan man gør dine websteder lynhurtige på alle slags enheder, for alle slags brugere, i alle slags situationer, er ikke overraskende omfattende. Her er nogle punkter at huske på, mens du bygger enten et standard webprojekt eller en browserudvidelse.
Det første, du skal gøre for at sikre, at dit websted kører effektivt, er at indsamle data om dets ydeevne. Det første sted at gøre dette er i udviklerværktøjerne i din webbrowser. I Edge kan du vælge knappen "Indstillinger og mere" (ikonet med de tre prikker øverst til højre i browseren), derefter navigere til Flere værktøjer > Udviklerværktøjer og åbne fanen Ydeevne. Du kan også bruge tastaturgenvejene `Ctrl` + `Shift` + `I` på Windows eller `Option` + `Command` + `I` på Mac for at åbne udviklerværktøjerne.
Fanen Ydeevne indeholder et profileringsværktøj. Åbn et websted (prøv for eksempel [https://www.microsoft.com](https://www.microsoft.com/?WT.mc_id=academic-77807-sagibbon)) og klik på 'Optag'-knappen, og opdater derefter webstedet. Stop optagelsen når som helst, og du vil kunne se de rutiner, der genereres for at 'script', 'render' og 'male' webstedet:
Fanen Ydeevne indeholder et profileringsværktøj. Åbn et websted (prøv for eksempel [https://www.microsoft.com](https://www.microsoft.com/?WT.mc_id=academic-77807-sagibbon)) og klik på 'Optag'-knappen, og opdater derefter siden. Stop optagelsen når som helst, og du vil kunne se de rutiner, der genereres for at 'script', 'render' og 'male' siden:
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01cfec9aab74173dba13f91d2c968e1a1ae434c26165792df15.da.png)
✅ Besøg [Microsoft Dokumentation](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) om ydeevnepanelet i Edge
✅ Besøg [Microsoft Dokumentation](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) om Ydeevne-panelet i Edge
> Tip: For at få en nøjagtig aflæsning af dit websteds opstartstid, skal du rydde din browsers cache.
> Tip: For at få en præcis måling af dit websteds opstartstid, ryd din browsers cache
Vælg elementer i profilens tidslinje for at zoome ind på begivenheder, der sker, mens din side indlæses.
Få et snapshot af din sides ydeevne ved at vælge en del af profilens tidslinje og se på oversigtspanelet:
Få et øjebliksbillede af din sides ydeevne ved at vælge en del af profilens tidslinje og kigge på oversigtspanelet:
![Edge profiler snapshot](../../../../translated_images/snapshot.97750180ebcad73794a3594b36925eb5c8dbaac9e03fec7f9b974188c9ac63c7.da.png)
@ -45,29 +45,29 @@ Tjek begivenhedslogpanelet for at se, om nogen begivenhed tog længere end 15 ms
![Edge event log](../../../../translated_images/log.804026979f3707e00eebcfa028b2b5a88cec6292f858767bb6703afba65a7d9c.da.png)
✅ Lær din profiler at kende! Åbn udviklerværktøjerne på dette websted og se, om der er nogen flaskehalse. Hvilken ressource indlæses langsomst? Hurtigst?
✅ Lær din profiler at kende! Åbn udviklerværktøjerne på dette websted og se, om der er nogen flaskehalse. Hvad er den langsomst indlæsende ressource? Den hurtigste?
## Profileringstjek
Generelt er der nogle "problemområder", som enhver webudvikler bør holde øje med, når de bygger et websted, for at undgå ubehagelige overraskelser, når det er tid til at implementere i produktion.
**Ressourcestørrelser**: Internettet er blevet 'tungere' og dermed langsommere i løbet af de seneste år. Noget af denne vægt skyldes brugen af billeder.
**Ressourcestørrelser**: Internettet er blevet 'tungere' og dermed langsommere i løbet af de sidste par år. Noget af denne vægt skyldes brugen af billeder.
Gennemse [Internetarkivet](https://httparchive.org/reports/page-weight) for et historisk overblik over sidens vægt og mere.
Kig gennem [Internetarkivet](https://httparchive.org/reports/page-weight) for et historisk overblik over sidens vægt og mere.
En god praksis er at sikre, at dine billeder er optimerede og leveres i den rigtige størrelse og opløsning til dine brugere.
En god praksis er at sikre, at dine billeder er optimeret og leveret i den rigtige størrelse og opløsning til dine brugere.
**DOM-gennemløb**: Browseren skal opbygge sin Document Object Model baseret på den kode, du skriver, så det er i interesse for god sideydeevne at holde dine tags minimale og kun bruge og style det, siden har brug for. I denne forbindelse kunne overskydende CSS, der er knyttet til en side, optimeres; stilarter, der kun skal bruges på én side, behøver for eksempel ikke at være inkluderet i hovedstilarket.
**DOM-gennemløb**: Browseren skal bygge sin Document Object Model baseret på den kode, du skriver, så det er i god sidens ydeevnes interesse at holde dine tags minimale og kun bruge og style det, som siden har brug for. For eksempel kan overskydende CSS, der er knyttet til en side, optimeres; stilarter, der kun skal bruges på én side, behøver ikke at være inkluderet i hoved-stilarket.
**JavaScript**: Enhver JavaScript-udvikler bør holde øje med 'render-blokerende' scripts, der skal indlæses, før resten af DOM'en kan gennemløbes og males til browseren. Overvej at bruge `defer` med dine inline scripts (som det gøres i Terrarium-modulet).
✅ Prøv nogle websteder på en [Site Speed Test-webside](https://www.webpagetest.org/) for at lære mere om de almindelige tjek, der udføres for at bestemme webstedets ydeevne.
Nu hvor du har en idé om, hvordan browseren gengiver de ressourcer, du sender til den, lad os se på de sidste par ting, du skal gøre for at fuldføre din udvidelse:
Nu hvor du har en idé om, hvordan browseren gengiver de ressourcer, du sender til den, lad os se på de sidste par ting, du skal gøre for at færdiggøre din udvidelse:
### Opret en funktion til at beregne farve
Arbejd i `/src/index.js`, og tilføj en funktion kaldet `calculateColor()` efter rækken af `const`-variabler, du har oprettet for at få adgang til DOM'en:
Arbejd i `/src/index.js`, og tilføj en funktion kaldet `calculateColor()` efter rækken af `const`-variabler, du satte for at få adgang til DOM'en:
```JavaScript
function calculateColor(value) {
@ -88,17 +88,17 @@ function calculateColor(value) {
}
```
Hvad sker der her? Du sender en værdi (kulstofintensiteten) fra API-kaldet, du fuldførte i sidste lektion, og derefter beregner du, hvor tæt dens værdi er på indekset præsenteret i farvearrayet. Derefter sender du den nærmeste farveværdi videre til chrome runtime.
Hvad sker der her? Du sender en værdi (kulstofintensiteten) fra API-kaldet, du færdiggjorde i den sidste lektion, og derefter beregner du, hvor tæt dens værdi er på indekset præsenteret i farvearrayet. Derefter sender du den nærmeste farveværdi videre til chrome runtime.
Chrome.runtime har [en API](https://developer.chrome.com/extensions/runtime), der håndterer alle slags baggrundsopgaver, og din udvidelse udnytter dette:
> "Brug chrome.runtime API'en til at hente baggrundssiden, returnere detaljer om manifestet og lytte til og reagere på begivenheder i appens eller udvidelsens livscyklus. Du kan også bruge denne API til at konvertere den relative sti for URL'er til fuldt kvalificerede URL'er."
> "Brug chrome.runtime API'en til at hente baggrundssiden, returnere detaljer om manifestet og lytte til og reagere på begivenheder i appens eller udvidelsens livscyklus. Du kan også bruge denne API til at konvertere relative stier til fuldt kvalificerede URL'er."
✅ Hvis du udvikler denne browserudvidelse til Edge, kan det overraske dig, at du bruger en chrome API. De nyere Edge-browserversioner kører på Chromium-browsermotoren, så du kan udnytte disse værktøjer.
✅ Hvis du udvikler denne browserudvidelse til Edge, kan det overraske dig, at du bruger en chrome API. De nyere versioner af Edge-browseren kører på Chromium-browsermotoren, så du kan udnytte disse værktøjer.
> Bemærk, hvis du vil profilere en browserudvidelse, skal du starte udviklerværktøjerne fra selve udvidelsen, da den er sin egen separate browserinstans.
### Indstil en standardfarve for ikonet
### Indstil en standard ikonfarve
Nu, i `init()`-funktionen, skal du indstille ikonet til at være generisk grønt til at starte med ved igen at kalde chromes `updateIcon`-handling:
@ -113,14 +113,14 @@ chrome.runtime.sendMessage({
### Kald funktionen, udfør kaldet
Dernæst skal du kalde den funktion, du lige har oprettet, ved at tilføje den til det løfte, der returneres af C02Signal API'en:
Kald derefter den funktion, du lige har oprettet, ved at tilføje den til løftet returneret af C02Signal API:
```JavaScript
//let CO2...
calculateColor(CO2);
```
Og endelig, i `/dist/background.js`, tilføj lytteren til disse baggrundsaktionskald:
Og endelig, i `/dist/background.js`, tilføj lytteren til disse baggrundshandlingskald:
```JavaScript
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
@ -142,9 +142,9 @@ function drawIcon(value) {
}
```
I denne kode tilføjer du en lytter til eventuelle beskeder, der kommer til baggrundsopgavehåndteringen. Hvis den kaldes 'updateIcon', køres den næste kode for at tegne et ikon med den korrekte farve ved hjælp af Canvas API'en.
I denne kode tilføjer du en lytter til eventuelle beskeder, der kommer til baggrundsopgavehåndteringen. Hvis den kaldes 'updateIcon', køres den næste kode for at tegne et ikon i den korrekte farve ved hjælp af Canvas API'en.
✅ Du lærer mere om Canvas API'en i [Space Game-lektionerne](../../6-space-game/2-drawing-to-canvas/README.md).
✅ Du vil lære mere om Canvas API'en i [Space Game-lektionerne](../../6-space-game/2-drawing-to-canvas/README.md).
Nu skal du genopbygge din udvidelse (`npm run build`), opdatere og starte din udvidelse og se farven ændre sig. Er det et godt tidspunkt at tage en pause eller vaske op? Nu ved du det!
@ -154,17 +154,17 @@ Tillykke, du har bygget en nyttig browserudvidelse og lært mere om, hvordan bro
## 🚀 Udfordring
Undersøg nogle open source-websteder, der har eksisteret i lang tid, og baseret på deres GitHub-historik, se om du kan afgøre, hvordan de blev optimeret gennem årene for ydeevne, hvis overhovedet. Hvad er det mest almindelige problemområde?
Undersøg nogle open source-websteder, der har eksisteret i lang tid, og se, baseret på deres GitHub-historik, om du kan afgøre, hvordan de blev optimeret over årene for ydeevne, hvis overhovedet. Hvad er det mest almindelige problemområde?
## Quiz efter lektionen
## Quiz efter forelæsning
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/28)
[Quiz efter forelæsning](https://ff-quizzes.netlify.app/web/quiz/28)
## Gennemgang & Selvstudie
Overvej at tilmelde dig et [ydeevne-nyhedsbrev](https://perf.email/)
Undersøg nogle af de måder, browsere vurderer webydeevne ved at kigge gennem ydeevnefanerne i deres webværktøjer. Finder du nogen større forskelle?
Undersøg nogle af de måder, browsere vurderer webydeevne ved at kigge gennem ydeevnefanerne i deres webværktøjer. Finder du nogen større forskelle?
## Opgave
@ -173,4 +173,4 @@ Undersøg nogle af de måder, browsere vurderer webydeevne ved at kigge gennem y
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,13 +1,13 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "d9da6dc61fb712b29f65e108c79b8a5d",
"translation_date": "2025-08-26T22:06:25+00:00",
"original_hash": "979cfcce2413a87d9e4c67eb79234bc3",
"translation_date": "2025-08-29T08:15:12+00:00",
"source_file": "6-space-game/1-introduction/README.md",
"language_code": "da"
}
-->
# Byg et rumspil del 1: Introduktion
# Byg et Rumspil Del 1: Introduktion
![video](../../../../6-space-game/images/pewpew.gif)
@ -15,24 +15,24 @@ CO_OP_TRANSLATOR_METADATA:
[Quiz før forelæsning](https://ff-quizzes.netlify.app/web/quiz/29)
### Arv og komposition i spiludvikling
### Arv og Komposition i spiludvikling
I tidligere lektioner var der ikke meget behov for at bekymre sig om designarkitekturen i de apps, du byggede, da projekterne var meget små i omfang. Men når dine applikationer vokser i størrelse og omfang, bliver arkitektoniske beslutninger en større bekymring. Der er to hovedtilgange til at skabe større applikationer i JavaScript: *komposition* eller *arv*. Begge har fordele og ulemper, men lad os forklare dem inden for konteksten af et spil.
I tidligere lektioner var der ikke meget behov for at bekymre sig om designarkitekturen i de apps, du byggede, da projekterne var meget små i omfang. Men når dine applikationer vokser i størrelse og kompleksitet, bliver arkitektoniske beslutninger en større bekymring. Der er to hovedtilgange til at skabe større applikationer i JavaScript: *komposition* eller *arv*. Begge har deres fordele og ulemper, men lad os forklare dem i konteksten af et spil.
✅ En af de mest berømte programmeringsbøger nogensinde handler om [designmønstre](https://en.wikipedia.org/wiki/Design_Patterns).
I et spil har du `spilobjekter`, som er objekter, der findes på en skærm. Det betyder, at de har en placering i et kartesisk koordinatsystem, karakteriseret ved at have en `x` og `y` koordinat. Når du udvikler et spil, vil du bemærke, at alle dine spilobjekter har en standardegenskab, fælles for hvert spil, du skaber, nemlig elementer, der er:
I et spil har du `spilobjekter`, som er objekter, der eksisterer på en skærm. Det betyder, at de har en placering i et kartesisk koordinatsystem, karakteriseret ved at have en `x`- og `y`-koordinat. Når du udvikler et spil, vil du bemærke, at alle dine spilobjekter har en standardegenskab, som er fælles for hvert spil, du skaber, nemlig elementer, der er:
- **positionsbaserede** De fleste, hvis ikke alle, spilelementer er positionsbaserede. Det betyder, at de har en placering, en `x` og `y`.
- **bevægelige** Dette er objekter, der kan flytte sig til en ny placering. Typisk er det en helt, et monster eller en NPC (en ikke-spilbar karakter), men ikke for eksempel et statisk objekt som et træ.
- **selvdestruerende** Disse objekter eksisterer kun i en bestemt periode, før de sætter sig selv op til sletning. Normalt er dette repræsenteret af en `dead` eller `destroyed` boolean, der signalerer til spilmotoren, at dette objekt ikke længere skal vises.
- **nedkøling** 'Nedkøling' er en typisk egenskab blandt kortvarige objekter. Et typisk eksempel er et stykke tekst eller en grafisk effekt som en eksplosion, der kun skal ses i nogle få millisekunder.
- **bevægelige** Dette er objekter, der kan flytte sig til en ny placering. Typisk er det en helt, et monster eller en NPC (en ikke-spiller karakter), men ikke for eksempel et statisk objekt som et træ.
- **selvdestruerende** Disse objekter eksisterer kun i en bestemt periode, før de markerer sig selv til sletning. Normalt repræsenteres dette af en `dead` eller `destroyed` boolean, der signalerer til spilmotoren, at dette objekt ikke længere skal vises.
- **cool-down** 'Cool-down' er en typisk egenskab blandt kortlivede objekter. Et typisk eksempel er et stykke tekst eller en grafisk effekt som en eksplosion, der kun skal ses i nogle få millisekunder.
✅ Tænk på et spil som Pac-Man. Kan du identificere de fire objekttyper, der er nævnt ovenfor, i dette spil?
### Udtryk adfærd
### Udtryk af adfærd
Alt det, vi beskrev ovenfor, er adfærd, som spilobjekter kan have. Så hvordan koder vi dem? Vi kan udtrykke denne adfærd som metoder, der er knyttet til enten klasser eller objekter.
Alt det, vi har beskrevet ovenfor, er adfærd, som spilobjekter kan have. Så hvordan koder vi det? Vi kan udtrykke denne adfærd som metoder, der er knyttet til enten klasser eller objekter.
**Klasser**
@ -88,7 +88,7 @@ hero.moveTo(5,5);
const tree = new Tree();
```
✅ Brug et par minutter på at forestille dig en Pac-Man helt (Inky, Pinky eller Blinky, for eksempel) og hvordan det ville blive skrevet i JavaScript.
✅ Brug et par minutter på at forestille dig en Pac-Man-helt (Inky, Pinky eller Blinky, for eksempel) og hvordan den ville blive skrevet i JavaScript.
**Komposition**
@ -149,9 +149,9 @@ Et andet mønster, der er almindeligt i spiludvikling, adresserer problemet med
✅ Pub/Sub står for 'publish-subscribe'
Dette mønster adresserer ideen om, at de forskellige dele af din applikation ikke bør kende til hinanden. Hvorfor er det sådan? Det gør det meget lettere at se, hvad der generelt foregår, hvis de forskellige dele er adskilt. Det gør det også lettere pludselig at ændre adfærd, hvis du har brug for det. Hvordan opnår vi dette? Vi gør det ved at etablere nogle begreber:
Dette mønster adresserer ideen om, at de forskellige dele af din applikation ikke bør kende til hinanden. Hvorfor det? Det gør det meget lettere at få et overblik, hvis de forskellige dele er adskilt. Det gør det også lettere at ændre adfærd, hvis det er nødvendigt. Hvordan opnår vi dette? Vi gør det ved at etablere nogle begreber:
- **besked**: En besked er normalt en tekststreng ledsaget af en valgfri payload (et stykke data, der præciserer, hvad beskeden handler om). En typisk besked i et spil kan være `KEY_PRESSED_ENTER`.
- **besked**: En besked er normalt en tekststreng ledsaget af en valgfri nyttelast (et stykke data, der præciserer, hvad beskeden handler om). En typisk besked i et spil kan være `KEY_PRESSED_ENTER`.
- **udgiver**: Dette element *udgiver* en besked og sender den ud til alle abonnenter.
- **abonnent**: Dette element *lytter* til specifikke beskeder og udfører en opgave som resultat af at modtage denne besked, såsom at affyre en laser.
@ -204,7 +204,7 @@ window.addEventListener('keyup', (evt) => {
});
```
Ovenfor forbinder vi en tastaturhændelse, `ArrowLeft`, og sender beskeden `HERO_MOVE_LEFT`. Vi lytter til den besked og flytter `hero` som resultat. Styrken ved dette mønster er, at event listeneren og helten ikke kender til hinanden. Du kan omdanne `ArrowLeft` til `A`-tasten. Derudover ville det være muligt at gøre noget helt andet på `ArrowLeft` ved at lave nogle få ændringer i eventEmitter's `on`-funktion:
Ovenfor forbinder vi en tastaturhændelse, `ArrowLeft`, og sender beskeden `HERO_MOVE_LEFT`. Vi lytter til den besked og flytter `hero` som resultat. Styrken ved dette mønster er, at event listeneren og helten ikke kender til hinanden. Du kan ommappe `ArrowLeft` til `A`-tasten. Derudover ville det være muligt at gøre noget helt andet på `ArrowLeft` ved at lave nogle få ændringer i eventEmitter's `on`-funktion:
```javascript
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
@ -212,13 +212,13 @@ eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
});
```
Efterhånden som tingene bliver mere komplicerede, når dit spil vokser, forbliver dette mønster det samme i kompleksitet, og din kode forbliver ren. Det anbefales virkelig at adoptere dette mønster.
Når tingene bliver mere komplekse, efterhånden som dit spil vokser, forbliver dette mønster det samme i kompleksitet, og din kode forbliver ren. Det anbefales virkelig at adoptere dette mønster.
---
## 🚀 Udfordring
Tænk over, hvordan pub-sub-mønsteret kan forbedre et spil. Hvilke dele bør udsende hændelser, og hvordan bør spillet reagere på dem? Nu har du chancen for at være kreativ og tænke på et nyt spil og hvordan dets dele kunne opføre sig.
Tænk over, hvordan pub-sub-mønsteret kan forbedre et spil. Hvilke dele bør udsende hændelser, og hvordan skal spillet reagere på dem? Nu har du chancen for at være kreativ og tænke på et nyt spil og hvordan dets dele kunne opføre sig.
## Quiz efter forelæsning
@ -230,9 +230,9 @@ Lær mere om Pub/Sub ved at [læse om det](https://docs.microsoft.com/azure/arch
## Opgave
[Mock et spil](assignment.md)
[Mock et spil op](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.

@ -1,25 +1,25 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "41be8d35e7f30aa9dad10773c35e89c4",
"translation_date": "2025-08-26T22:00:06+00:00",
"original_hash": "056641280211e52fd0adb81b6058ec55",
"translation_date": "2025-08-29T08:14:11+00:00",
"source_file": "6-space-game/2-drawing-to-canvas/README.md",
"language_code": "da"
}
-->
# Byg et Rumspil Del 2: Tegn Helten og Monstrene på Canvas
# Byg et rumspil del 2: Tegn helten og monstre på lærredet
## Quiz før forelæsning
[Quiz før forelæsning](https://ff-quizzes.netlify.app/web/quiz/31)
## Canvas
## Lærredet
Canvas er et HTML-element, der som standard ikke har noget indhold; det er en tom flade. Du skal tilføje indhold ved at tegne på det.
Lærredet er et HTML-element, der som standard ikke har noget indhold; det er en tom flade. Du skal tilføje indhold ved at tegne på det.
✅ Læs [mere om Canvas API'et](https://developer.mozilla.org/docs/Web/API/Canvas_API) på MDN.
✅ Læs [mere om Canvas API](https://developer.mozilla.org/docs/Web/API/Canvas_API) på MDN.
Sådan ser det typisk ud, når det erklæres som en del af sidens body:
Her er, hvordan det typisk deklareres som en del af sidens body:
```html
<canvas id="myCanvas" width="200" height="100"></canvas>
@ -27,24 +27,24 @@ Sådan ser det typisk ud, når det erklæres som en del af sidens body:
Ovenfor sætter vi `id`, `width` og `height`.
- `id`: angiv dette, så du kan få en reference, når du skal interagere med det.
- `id`: sæt dette, så du kan få en reference, når du skal interagere med det.
- `width`: dette er elementets bredde.
- `height`: dette er elementets højde.
## Tegning af simpel geometri
Canvas bruger et kartesisk koordinatsystem til at tegne ting. Det betyder, at det bruger en x-akse og en y-akse til at angive, hvor noget er placeret. Positionen `0,0` er øverste venstre hjørne, og nederste højre hjørne er det, du har angivet som CANVAS' BREDDE og HØJDE.
Lærredet bruger et kartesisk koordinatsystem til at tegne ting. Det betyder, at det bruger en x-akse og y-akse til at udtrykke, hvor noget er placeret. Placeringen `0,0` er øverste venstre hjørne, og nederste højre hjørne er det, du har angivet som lærredets BREDDE og HØJDE.
![canvas' gitter](../../../../translated_images/canvas_grid.5f209da785ded492a01ece440e3032afe51efa500cc2308e5ea4252487ceaf0b.da.png)
![lærredets gitter](../../../../translated_images/canvas_grid.5f209da785ded492a01ece440e3032afe51efa500cc2308e5ea4252487ceaf0b.da.png)
> Billede fra [MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
For at tegne på canvas-elementet skal du gennemgå følgende trin:
For at tegne på lærredselementet skal du følge disse trin:
1. **Få en reference** til Canvas-elementet.
2. **Få en reference** til Context-elementet, der sidder på Canvas-elementet.
3. **Udfør en tegneoperation** ved hjælp af Context-elementet.
1. **Få en reference** til lærredselementet.
1. **Få en reference** til kontekstelementet, der sidder på lærredselementet.
1. **Udfør en tegneoperation** ved hjælp af kontekstelementet.
Koden for ovenstående trin ser typisk sådan ud:
Kode for ovenstående trin ser typisk sådan ud:
```javascript
// draws a red rectangle
@ -61,21 +61,21 @@ ctx.fillStyle = 'red';
ctx.fillRect(0,0, 200, 200) // x,y,width, height
```
✅ Canvas API'et fokuserer primært på 2D-former, men du kan også tegne 3D-elementer på en webside; til dette kan du bruge [WebGL API'et](https://developer.mozilla.org/docs/Web/API/WebGL_API).
✅ Canvas API fokuserer primært på 2D-former, men du kan også tegne 3D-elementer på en hjemmeside; til dette kan du bruge [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API).
Du kan tegne mange forskellige ting med Canvas API'et, såsom:
Du kan tegne mange forskellige ting med Canvas API, såsom:
- **Geometriske former**, vi har allerede vist, hvordan man tegner et rektangel, men der er meget mere, du kan tegne.
- **Tekst**, du kan tegne tekst med enhver skrifttype og farve, du ønsker.
- **Billeder**, du kan tegne et billede baseret på en billedfil som f.eks. en .jpg eller .png.
- **Geometriske former**, vi har allerede vist, hvordan man tegner et rektangel, men der er meget mere, du kan tegne.
- **Tekst**, du kan tegne tekst med enhver skrifttype og farve, du ønsker.
- **Billeder**, du kan tegne et billede baseret på en billedfil som f.eks. en .jpg eller .png.
✅ Prøv det! Du ved, hvordan man tegner et rektangel, kan du tegne en cirkel på en side? Tag et kig på nogle interessante Canvas-tegninger på CodePen. Her er et [særligt imponerende eksempel](https://codepen.io/dissimulate/pen/KrAwx).
## Indlæs og tegn en billedressource
## Indlæs og tegn en billedfil
Du indlæser en billedressource ved at oprette et `Image`-objekt og sætte dets `src`-egenskab. Derefter lytter du til `load`-hændelsen for at vide, hvornår det er klar til brug. Koden ser sådan ud:
Du indlæser en billedfil ved at oprette et `Image`-objekt og sætte dets `src`-egenskab. Derefter lytter du til `load`-begivenheden for at vide, hvornår det er klar til brug. Koden ser sådan ud:
### Indlæs ressource
### Indlæs fil
```javascript
const img = new Image();
@ -85,9 +85,9 @@ img.onload = () => {
}
```
### Mønster for indlæsning af ressource
### Indlæsningsmønster
Det anbefales at pakke ovenstående ind i en konstruktion som denne, så det er nemmere at bruge, og du kun forsøger at manipulere det, når det er fuldt indlæst:
Det anbefales at pakke ovenstående ind i en konstruktion som denne, så det er lettere at bruge, og du kun forsøger at manipulere det, når det er fuldt indlæst:
```javascript
function loadAsset(path) {
@ -128,19 +128,19 @@ async function run() {
### Hvad skal bygges
Du skal bygge en webside med et Canvas-element. Det skal vise en sort skærm `1024*768`. Vi har givet dig to billeder:
Du skal bygge en webside med et lærredselement. Det skal vise en sort skærm `1024*768`. Vi har givet dig to billeder:
- Helteskib
- Helteskib
![Helteskib](../../../../translated_images/player.dd24c1afa8c71e9b82b2958946d4bad13308681392d4b5ddcc61a0e818ef8088.da.png)
- 5*5 monster
- 5*5 monster
![Monsterskib](../../../../translated_images/enemyShip.5df2a822c16650c2fb3c06652e8ec8120cdb9122a6de46b9a1a56d54db22657f.da.png)
### Anbefalede trin for at starte udviklingen
### Anbefalede trin til at starte udviklingen
Find de filer, der er blevet oprettet til dig i undermappen `your-work`. Den bør indeholde følgende:
Find de filer, der er oprettet til dig i undermappen `your-work`. Den bør indeholde følgende:
```bash
-| assets
@ -151,7 +151,7 @@ Find de filer, der er blevet oprettet til dig i undermappen `your-work`. Den bø
-| package.json
```
Åbn en kopi af denne mappe i Visual Studio Code. Du skal have et lokalt udviklingsmiljø opsat, helst med Visual Studio Code med NPM og Node installeret. Hvis du ikke har `npm` opsat på din computer, [sådan gør du det](https://www.npmjs.com/get-npm).
Åbn en kopi af denne mappe i Visual Studio Code. Du skal have et lokalt udviklingsmiljø sat op, helst med Visual Studio Code med NPM og Node installeret. Hvis du ikke har `npm` sat op på din computer, [sådan gør du](https://www.npmjs.com/get-npm).
Start dit projekt ved at navigere til mappen `your_work`:
@ -168,16 +168,16 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
Tilføj den nødvendige kode til `your-work/app.js` for at løse nedenstående:
1. **Tegn** et canvas med sort baggrund
> tip: tilføj to linjer under den relevante TODO i `/app.js`, der sætter `ctx`-elementet til at være sort og top/venstre koordinater til at være 0,0, og højden og bredden til at svare til canvas.
2. **Indlæs** teksturer
> tip: tilføj spiller- og fjendebilleder ved hjælp af `await loadTexture` og angiv billedstien. Du vil endnu ikke kunne se dem på skærmen!
3. **Tegn** helten i midten af skærmen i den nederste halvdel
> tip: brug `drawImage` API'et til at tegne heroImg på skærmen, og sæt `canvas.width / 2 - 45` og `canvas.height - canvas.height / 4)`.
4. **Tegn** 5*5 monstre
> tip: Nu kan du fjerne kommenteringen af koden for at tegne fjender på skærmen. Gå derefter til funktionen `createEnemies` og byg den ud.
1. **Tegn** et lærred med sort baggrund
> tip: tilføj to linjer under den relevante TODO i `/app.js`, der sætter `ctx`-elementet til sort og top/venstre koordinater til 0,0 og højden og bredden til at matche lærredet.
2. **Indlæs** teksturer
> tip: tilføj spiller- og fjendebilleder ved hjælp af `await loadTexture` og angiv stien til billedet. Du vil ikke se dem på skærmen endnu!
3. **Tegn** helten i midten af skærmen i den nederste halvdel
> tip: brug `drawImage` API til at tegne heroImg på skærmen, og sæt `canvas.width / 2 - 45` og `canvas.height - canvas.height / 4)`.
4. **Tegn** 5*5 monstre
> tip: Nu kan du fjerne kommentaren fra koden for at tegne fjender på skærmen. Gå derefter til funktionen `createEnemies` og byg den ud.
Først, opsæt nogle konstanter:
Først skal du opsætte nogle konstanter:
```javascript
const MONSTER_TOTAL = 5;
@ -186,7 +186,7 @@ Tilføj den nødvendige kode til `your-work/app.js` for at løse nedenstående:
const STOP_X = START_X + MONSTER_WIDTH;
```
derefter, opret en løkke for at tegne arrayet af monstre på skærmen:
derefter oprette en løkke for at tegne arrayet af monstre på skærmen:
```javascript
for (let x = START_X; x < STOP_X; x += 98) {
@ -198,19 +198,19 @@ Tilføj den nødvendige kode til `your-work/app.js` for at løse nedenstående:
## Resultat
Det færdige resultat bør se sådan ud:
Det færdige resultat skal se sådan ud:
![Sort skærm med en helt og 5*5 monstre](../../../../translated_images/partI-solution.36c53b48c9ffae2a5e15496b23b604ba5393433e4bf91608a7a0a020eb7a2691.da.png)
## Løsning
Prøv venligst at løse det selv først, men hvis du sidder fast, kan du se en [løsning](../../../../6-space-game/2-drawing-to-canvas/solution/app.js).
Prøv først at løse det selv, men hvis du går i stå, kan du se en [løsning](../../../../6-space-game/2-drawing-to-canvas/solution/app.js).
---
## 🚀 Udfordring
Du har lært om at tegne med det 2D-fokuserede Canvas API; tag et kig på [WebGL API'et](https://developer.mozilla.org/docs/Web/API/WebGL_API), og prøv at tegne et 3D-objekt.
Du har lært om at tegne med det 2D-fokuserede Canvas API; tag et kig på [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API), og prøv at tegne et 3D-objekt.
## Quiz efter forelæsning
@ -218,13 +218,13 @@ Du har lært om at tegne med det 2D-fokuserede Canvas API; tag et kig på [WebGL
## Gennemgang & Selvstudie
Lær mere om Canvas API'et ved at [læse om det](https://developer.mozilla.org/docs/Web/API/Canvas_API).
Lær mere om Canvas API ved at [læse om det](https://developer.mozilla.org/docs/Web/API/Canvas_API).
## Opgave
[Leg med Canvas API'et](assignment.md)
[Leg med Canvas API](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "23f088add24f0f1fa51014a9e27ea280",
"translation_date": "2025-08-26T21:57:14+00:00",
"original_hash": "a9a161871de7706cb0e23b1bd0c74559",
"translation_date": "2025-08-29T08:12:45+00:00",
"source_file": "6-space-game/3-moving-elements-around/README.md",
"language_code": "da"
}
@ -15,10 +15,10 @@ CO_OP_TRANSLATOR_METADATA:
Spil er ikke særlig sjove, før du har rumvæsener, der bevæger sig rundt på skærmen! I dette spil vil vi gøre brug af to typer bevægelser:
- **Tastatur/mus bevægelse**: når brugeren interagerer med tastaturet eller musen for at flytte et objekt på skærmen.
- **Tastatur/mus-bevægelse**: når brugeren interagerer med tastaturet eller musen for at flytte et objekt på skærmen.
- **Spilinduceret bevægelse**: når spillet flytter et objekt med et bestemt tidsinterval.
Så hvordan flytter vi ting på en skærm? Det handler alt sammen om kartesiske koordinater: vi ændrer objektets placering (x,y) og tegner derefter skærmen igen.
Så hvordan flytter vi ting på en skærm? Det handler alt sammen om kartesiske koordinater: vi ændrer objektets placering (x, y) og tegner derefter skærmen igen.
Typisk har du brug for følgende trin for at opnå *bevægelse* på en skærm:
@ -39,7 +39,7 @@ ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);
```
✅ Kan du komme i tanke om en grund til, at det kan medføre ydeevneomkostninger at tegne din helt mange gange i sekundet? Læs om [alternativer til dette mønster](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas).
✅ Kan du tænke på en grund til, at det kan medføre ydeevneomkostninger at tegne din helt mange gange i sekundet? Læs om [alternativer til dette mønster](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas).
## Håndtering af tastaturhændelser
@ -58,16 +58,16 @@ window.addEventListener('keyup', (evt) => {
})
```
For tastaturhændelser er der to egenskaber på hændelsen, du kan bruge til at se, hvilken tast der blev trykket:
For tastaturhændelser er der to egenskaber på hændelsen, du kan bruge til at se, hvilken tast der blev trykket:
- `key`, dette er en strengrepræsentation af den trykkede tast, for eksempel `ArrowUp`.
- `keyCode`, dette er en numerisk repræsentation, for eksempel `37`, som svarer til `ArrowLeft`.
✅ Manipulation af tastaturhændelser er nyttig uden for spiludvikling. Hvilke andre anvendelser kan du komme i tanke om for denne teknik?
### Specialtaster: en advarsel
### Specielle taster: en advarsel
Der er nogle *specialtaster*, der påvirker vinduet. Det betyder, at hvis du lytter til en `keyup`-hændelse og bruger disse specialtaster til at flytte din helt, vil det også udføre horisontal rulning. Af den grund vil du måske *slå fra* denne indbyggede browseradfærd, mens du bygger dit spil. Du har brug for kode som denne:
Der er nogle *specielle* taster, der påvirker vinduet. Det betyder, at hvis du lytter til en `keyup`-hændelse og bruger disse specielle taster til at flytte din helt, vil det også udføre horisontal rulning. Af den grund vil du måske *slå fra* denne indbyggede browseradfærd, mens du bygger dit spil. Du har brug for kode som denne:
```javascript
let onKeyDown = function (e) {
@ -92,7 +92,7 @@ Koden ovenfor sikrer, at piletasterne og mellemrumstasten får deres *standard*
## Spilinduceret bevægelse
Vi kan få ting til at bevæge sig af sig selv ved at bruge timere som `setTimeout()` eller `setInterval()`-funktionen, der opdaterer objektets placering ved hver tik eller tidsinterval. Sådan kan det se ud:
Vi kan få ting til at bevæge sig af sig selv ved at bruge timere som funktionerne `setTimeout()` eller `setInterval()`, der opdaterer objektets placering ved hvert tick eller tidsinterval. Sådan kan det se ud:
```javascript
let id = setInterval(() => {
@ -123,7 +123,7 @@ Loopet ovenfor kaldes hvert `200` millisekund for at tegne lærredet igen. Du ha
## Fortsættelse af rumspillet
Du vil tage den eksisterende kode og udvide den. Enten start med den kode, du færdiggjorde under del I, eller brug koden i [Del II - startkode](../../../../6-space-game/3-moving-elements-around/your-work).
Du vil tage den eksisterende kode og udvide den. Enten start med den kode, du færdiggjorde under del I, eller brug koden i [Del II - starter](../../../../6-space-game/3-moving-elements-around/your-work).
- **Flyt helten**: du vil tilføje kode for at sikre, at du kan flytte helten ved hjælp af piletasterne.
- **Flyt fjender**: du skal også tilføje kode for at sikre, at fjenderne bevæger sig fra top til bund med en given hastighed.
@ -148,13 +148,13 @@ cd your-work
npm start
```
Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn en browser og indtast den adresse, lige nu bør den vise helten og alle fjenderne; intet bevæger sig - endnu!
Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn en browser og indtast den adresse. Lige nu bør den vise helten og alle fjenderne; intet bevæger sig - endnu!
### Tilføj kode
1. **Tilføj dedikerede objekter** for `hero`, `enemy` og `game object`, de skal have `x` og `y` egenskaber. (Husk afsnittet om [Arv eller komposition](../README.md)).
1. **Tilføj dedikerede objekter** for `hero`, `enemy` og `game object`, de skal have `x`- og `y`-egenskaber. (Husk afsnittet om [Arv eller komposition](../README.md)).
*TIP* `game object` bør være det objekt, der har `x` og `y` og evnen til at tegne sig selv på et lærred.
*TIP* `game object` bør være det, der har `x` og `y` og evnen til at tegne sig selv på et lærred.
>tip: start med at tilføje en ny GameObject-klasse med dens constructor defineret som nedenfor, og tegn den derefter på lærredet:
@ -205,7 +205,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
2. **Tilføj tastaturhændelses-håndterere** for at håndtere navigation med taster (flyt helten op/ned venstre/højre).
2. **Tilføj tastaturhændelses-håndterere** for at håndtere navigation med taster (flyt helten op/ned, venstre/højre).
*HUSK* det er et kartesisk system, øverst til venstre er `0,0`. Husk også at tilføje kode for at stoppe *standardadfærd*.
@ -223,7 +223,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
Tjek din browsers konsol på dette tidspunkt, og se tastetrykkene blive logget.
3. **Implementer** [Pub sub-mønsteret](../README.md), dette vil holde din kode ren, mens du følger de resterende dele.
3. **Implementer** [Pub-sub-mønsteret](../README.md), dette vil holde din kode ren, mens du følger de resterende dele.
For at gøre denne sidste del kan du:
@ -313,7 +313,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
1. **Opsæt spil-loopet**
Refaktorer window.onload-funktionen for at initialisere spillet og opsætte et spil-loop med et passende interval. Du tilføjer også en laserstråle:
Refaktorer window.onload-funktionen for at initialisere spillet og opsætte et spil-loop med et passende interval. Du vil også tilføje en laserstråle:
```javascript
window.onload = async () => {
@ -368,7 +368,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
og til sidst, tilføj en `drawGameObjects()`-funktion for at starte tegningen:
og til sidst tilføj en `drawGameObjects()`-funktion for at starte tegningen:
```javascript
function drawGameObjects(ctx) {
@ -382,7 +382,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
## 🚀 Udfordring
Som du kan se, kan din kode blive til 'spaghettikode', når du begynder at tilføje funktioner, variabler og klasser. Hvordan kan du bedre organisere din kode, så den er mere læsbar? Skitser et system til at organisere din kode, selvom den stadig befinder sig i én fil.
Som du kan se, kan din kode blive til 'spaghetti-kode', når du begynder at tilføje funktioner, variabler og klasser. Hvordan kan du bedre organisere din kode, så den er mere læsbar? Skitser et system til at organisere din kode, selvom den stadig befinder sig i én fil.
## Quiz efter forelæsning
@ -399,4 +399,4 @@ Mens vi skriver vores spil uden at bruge frameworks, findes der mange JavaScript
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,40 +1,40 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2e83e38c35dc003f046d7cc0bbfd4920",
"translation_date": "2025-08-26T22:03:07+00:00",
"original_hash": "a6ce295ff03bb49df7a3e17e6e7100a0",
"translation_date": "2025-08-29T08:13:36+00:00",
"source_file": "6-space-game/4-collision-detection/README.md",
"language_code": "da"
}
-->
# Byg et rumspil del 4: Tilføj en laser og registrer kollisioner
# Byg et Rumspil Del 4: Tilføjelse af en Laser og Registrering af Kollisioner
## Quiz før lektionen
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/35)
I denne lektion lærer du, hvordan du skyder med laser ved hjælp af JavaScript! Vi vil tilføje to ting til vores spil:
I denne lektion lærer du, hvordan man skyder med lasere ved hjælp af JavaScript! Vi tilføjer to ting til vores spil:
- **En laser**: Denne laser bliver skudt fra din helts rumskib og bevæger sig lodret opad.
- **Kollisionsregistrering**: Som en del af implementeringen af evnen til at *skyde* vil vi også tilføje nogle gode spilleregler:
- **Laser rammer fjende**: Fjenden dør, hvis den bliver ramt af en laser.
- **Laser rammer toppen af skærmen**: En laser bliver ødelagt, hvis den rammer den øverste del af skærmen.
- **Fjende og helt kolliderer**: En fjende og helten bliver ødelagt, hvis de rammer hinanden.
- **Fjende rammer bunden af skærmen**: En fjende og helten bliver ødelagt, hvis fjenden rammer bunden af skærmen.
- **En laser**: Denne laser affyres fra din helts skib og bevæger sig lodret opad.
- **Registrering af kollisioner**, som en del af implementeringen af evnen til at *skyde*, tilføjer vi også nogle spændende spilleregler:
- **Laser rammer fjende**: Fjenden dør, hvis den rammes af en laser.
- **Laser rammer toppen af skærmen**: En laser destrueres, hvis den rammer den øverste del af skærmen.
- **Fjende og helt kollision**: En fjende og helten destrueres, hvis de rammer hinanden.
- **Fjende rammer bunden af skærmen**: En fjende og helten destrueres, hvis fjenden rammer bunden af skærmen.
Kort sagt, du -- *helten* -- skal ramme alle fjender med en laser, før de når bunden af skærmen.
✅ Lav lidt research om det allerførste computerspil nogensinde. Hvad var dets funktionalitet?
✅ Lav lidt research om det allerførste computerspil, der nogensinde blev skrevet. Hvad var dets funktionalitet?
Lad os være heroiske sammen!
Lad os være heltemodige sammen!
## Kollisionsregistrering
## Registrering af kollisioner
Hvordan registrerer vi kollisioner? Vi skal tænke på vores spilobjekter som rektangler, der bevæger sig rundt. Hvorfor det, spørger du måske? Jo, det billede, der bruges til at tegne et spilobjekt, er et rektangel: det har en `x`, `y`, `bredde` og `højde`.
Hvordan registrerer vi kollisioner? Vi skal tænke på vores spilobjekter som rektangler, der bevæger sig rundt. Hvorfor det, spørger du måske? Jo, billedet, der bruges til at tegne et spilobjekt, er et rektangel: det har en `x`, `y`, `bredde` og `højde`.
Hvis to rektangler, dvs. en helt og en fjende, *skærer hinanden*, har du en kollision. Hvad der skal ske derefter, afhænger af spillereglerne. For at implementere kollisionsregistrering skal du derfor bruge følgende:
Hvis to rektangler, dvs. en helt og en fjende, *overlapper*, har du en kollision. Hvad der derefter skal ske, afhænger af spillereglerne. For at implementere registrering af kollisioner skal du derfor bruge følgende:
1. En måde at få en rektangelrepræsentation af et spilobjekt, noget i stil med dette:
1. En måde at få en rektangelrepræsentation af et spilobjekt, noget i denne stil:
```javascript
rectFromGameObject() {
@ -58,32 +58,32 @@ Hvis to rektangler, dvs. en helt og en fjende, *skærer hinanden*, har du en kol
}
```
## Hvordan ødelægger vi ting
## Hvordan destruerer vi ting
For at ødelægge ting i et spil skal du lade spillet vide, at det ikke længere skal tegne dette objekt i spil-loopet, der udløses med et bestemt interval. En måde at gøre dette på er at markere et spilobjekt som *dødt*, når noget sker, som :
For at destruerer ting i et spil skal du fortælle spillet, at det ikke længere skal tegne dette objekt i spillets løkke, som udløses med et bestemt interval. En måde at gøre dette på er at markere et spilobjekt som *dødt*, når noget sker, som dette:
```javascript
// collision happened
enemy.dead = true
```
Derefter kan du sortere *døde* objekter fra, før skærmen bliver tegnet igen, som så:
Derefter kan du sortere *døde* objekter fra, før skærmen genmales, som dette:
```javascript
gameObjects = gameObject.filter(go => !go.dead);
```
## Hvordan skyder vi en laser
## Hvordan affyrer vi en laser
At skyde en laser betyder at reagere på en tastaturhændelse og oprette et objekt, der bevæger sig i en bestemt retning. Vi skal derfor udføre følgende trin:
At affyre en laser betyder at reagere på en tastaturhændelse og skabe et objekt, der bevæger sig i en bestemt retning. Vi skal derfor udføre følgende trin:
1. **Opret et laserobjekt**: fra toppen af heltenes rumskib, som ved oprettelse begynder at bevæge sig opad mod toppen af skærmen.
2. **Tilføj kode til en tastaturhændelse**: Vi skal vælge en tast på tastaturet, der repræsenterer spilleren, der skyder laseren.
1. **Opret et laserobjekt**: fra toppen af helteskibet, som ved oprettelse begynder at bevæge sig opad mod skærmens top.
2. **Tilføj kode til en tastaturhændelse**: vi skal vælge en tast på tastaturet, der repræsenterer spillerens affyring af laseren.
3. **Opret et spilobjekt, der ligner en laser**, når tasten trykkes.
## Cooldown på vores laser
Laseren skal affyres hver gang du trykker på en tast, f.eks. *mellemrum*. For at forhindre spillet i at producere alt for mange lasere på kort tid, skal vi løse dette. Løsningen er at implementere en såkaldt *cooldown*, en timer, der sikrer, at en laser kun kan affyres med bestemte intervaller. Du kan implementere det på følgende måde:
Laseren skal affyres hver gang du trykker på en tast, f.eks. *mellemrumstasten*. For at forhindre spillet i at producere alt for mange lasere på kort tid, skal vi løse dette. Løsningen er at implementere en såkaldt *cooldown*, en timer, der sikrer, at en laser kun kan affyres med bestemte intervaller. Du kan implementere det på følgende måde:
```javascript
class Cooldown {
@ -109,19 +109,19 @@ class Weapon {
}
```
Henvis til lektion 1 i rumspilsserien for at minde dig selv om *cooldowns*.
Gå tilbage til lektion 1 i rumspilsserien for at minde dig selv om *cooldowns*.
## Hvad skal bygges
Du skal tage den eksisterende kode (som du burde have ryddet op i og refaktoreret) fra den forrige lektion og udvide den. Enten start med koden fra del II eller brug koden fra [Del III - starter](../../../../../../../../../your-work).
Du skal tage den eksisterende kode (som du burde have ryddet op i og refaktoreret) fra den forrige lektion og udvide den. Start enten med koden fra del II eller brug koden fra [Del III - startkode](../../../../../../../../../your-work).
> tip: Laseren, du skal arbejde med, er allerede i din assets-mappe og refereret af din kode.
> tip: Laseren, du skal arbejde med, findes allerede i din assets-mappe og er refereret i din kode.
- **Tilføj kollisionsregistrering**, når en laser kolliderer med noget, skal følgende regler gælde:
1. **Laser rammer fjende**: Fjenden dør, hvis den bliver ramt af en laser.
2. **Laser rammer toppen af skærmen**: En laser bliver ødelagt, hvis den rammer den øverste del af skærmen.
3. **Fjende og helt kolliderer**: En fjende og helten bliver ødelagt, hvis de rammer hinanden.
4. **Fjende rammer bunden af skærmen**: En fjende og helten bliver ødelagt, hvis fjenden rammer bunden af skærmen.
- **Tilføj registrering af kollisioner**, når en laser kolliderer med noget, skal følgende regler gælde:
1. **Laser rammer fjende**: Fjenden dør, hvis den rammes af en laser.
2. **Laser rammer toppen af skærmen**: En laser destrueres, hvis den rammer den øverste del af skærmen.
3. **Fjende og helt kollision**: En fjende og helten destrueres, hvis de rammer hinanden.
4. **Fjende rammer bunden af skærmen**: En fjende og helten destrueres, hvis fjenden rammer bunden af skærmen.
## Anbefalede trin
@ -137,7 +137,7 @@ Find de filer, der er blevet oprettet til dig i undermappen `your-work`. Den bø
-| package.json
```
Du starter dit projekt i mappen `your_work` ved at skrive:
Du starter dit projekt i `your_work`-mappen ved at skrive:
```bash
cd your-work
@ -148,7 +148,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
### Tilføj kode
1. **Opsæt en rektangelrepræsentation af dit spilobjekt for at håndtere kollisioner**. Nedenstående kode giver dig mulighed for at få en rektangelrepræsentation af et `GameObject`. Rediger din GameObject-klasse for at udvide den:
1. **Opsæt en rektangelrepræsentation af dit spilobjekt for at håndtere kollisioner** Følgende kode giver dig mulighed for at få en rektangelrepræsentation af et `GameObject`. Rediger din GameObject-klasse for at udvide den:
```javascript
rectFromGameObject() {
@ -161,7 +161,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
2. **Tilføj kode, der kontrollerer kollisioner**. Dette vil være en ny funktion, der tester, om to rektangler skærer hinanden:
2. **Tilføj kode, der tjekker kollisioner** Dette vil være en ny funktion, der tester, om to rektangler overlapper:
```javascript
function intersectRect(r1, r2) {
@ -174,8 +174,8 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
3. **Tilføj laser-skydningsfunktionalitet**
1. **Tilføj tastaturhændelsesmeddelelse**. *Mellemrumstasten* skal oprette en laser lige over heltenes rumskib. Tilføj tre konstanter i Messages-objektet:
3. **Tilføj laser-affyringsfunktionalitet**
1. **Tilføj tastaturhændelse**. *Mellemrumstasten* skal skabe en laser lige over helteskibet. Tilføj tre konstanter i Messages-objektet:
```javascript
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
@ -183,7 +183,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
COLLISION_ENEMY_HERO: "COLLISION_ENEMY_HERO",
```
1. **Håndter mellemrumstasten**. Rediger funktionen `window.addEventListener` keyup for at håndtere mellemrumstasten:
1. **Håndter mellemrumstasten**. Rediger `window.addEventListener` keyup-funktionen for at håndtere mellemrumstasten:
```javascript
} else if(evt.keyCode === 32) {
@ -191,7 +191,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
1. **Tilføj lyttere**. Rediger funktionen `initGame()` for at sikre, at helten kan skyde, når mellemrumstasten trykkes:
1. **Tilføj lyttere**. Rediger `initGame()`-funktionen for at sikre, at helten kan affyre, når mellemrumstasten trykkes:
```javascript
eventEmitter.on(Messages.KEY_EVENT_SPACE, () => {
@ -209,7 +209,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
})
```
1. **Bevæg objektet**, Sørg for, at laseren gradvist bevæger sig mod toppen af skærmen. Du opretter en ny Laser-klasse, der udvider `GameObject`, som du har gjort før:
1. **Bevæg objekt**, Sørg for, at laseren gradvist bevæger sig mod toppen af skærmen. Du opretter en ny Laser-klasse, der udvider `GameObject`, som du har gjort før:
```javascript
class Laser extends GameObject {
@ -252,11 +252,11 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
Sørg for at tilføje `updateGameObjects()` til dit spil-loop i `window.onload`.
Sørg for at tilføje `updateGameObjects()` i din spillykke i `window.onload`.
4. **Implementer cooldown** på laseren, så den kun kan affyres med bestemte intervaller.
Til sidst skal du redigere Hero-klassen, så den kan håndtere cooldown:
Til sidst rediger Hero-klassen, så den kan håndtere cooldown:
```javascript
class Hero extends GameObject {
@ -285,7 +285,7 @@ Ovenstående starter en HTTP-server på adressen `http://localhost:5000`. Åbn e
}
```
På dette tidspunkt har dit spil noget funktionalitet! Du kan navigere med dine piletaster, skyde en laser med din mellemrumstast, og fjender forsvinder, når du rammer dem. Godt gået!
På dette tidspunkt har dit spil noget funktionalitet! Du kan navigere med piletasterne, affyre en laser med mellemrumstasten, og fjender forsvinder, når du rammer dem. Godt gået!
---
@ -299,7 +299,7 @@ Tilføj en eksplosion! Tag et kig på spilassets i [Space Art-repoet](../../../.
## Gennemgang & Selvstudie
Eksperimenter med intervallerne i dit spil indtil videre. Hvad sker der, når du ændrer dem? Læs mere om [JavaScript timing events](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
Eksperimentér med intervallerne i dit spil indtil videre. Hvad sker der, når du ændrer dem? Læs mere om [JavaScript timing events](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
## Opgave
@ -308,4 +308,4 @@ Eksperimenter med intervallerne i dit spil indtil videre. Hvad sker der, når du
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,23 +1,23 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "4e8250db84b027c9ff816b4e4c093457",
"translation_date": "2025-08-26T21:53:45+00:00",
"original_hash": "adda95e02afa3fbee67b6e385b1109e1",
"translation_date": "2025-08-29T08:13:14+00:00",
"source_file": "6-space-game/5-keeping-score/README.md",
"language_code": "da"
}
-->
# Byg et Rumspil Del 5: Point og Liv
## Quiz før lektion
## Quiz før lektionen
[Quiz før lektion](https://ff-quizzes.netlify.app/web/quiz/37)
[Quiz før lektionen](https://ff-quizzes.netlify.app/web/quiz/37)
I denne lektion vil du lære, hvordan du tilføjer point til et spil og beregner liv.
I denne lektion lærer du, hvordan du tilføjer point til et spil og beregner liv.
## Tegn tekst på skærmen
For at kunne vise en spilscore på skærmen skal du vide, hvordan man placerer tekst på skærmen. Svaret er at bruge metoden `fillText()` på canvas-objektet. Du kan også kontrollere andre aspekter som hvilken skrifttype der skal bruges, tekstens farve og endda dens justering (venstre, højre, center). Nedenfor er der noget kode, der tegner tekst på skærmen.
For at kunne vise en spilscore på skærmen skal du vide, hvordan man placerer tekst på skærmen. Svaret er at bruge `fillText()`-metoden på canvas-objektet. Du kan også styre andre aspekter som hvilken skrifttype, der skal bruges, tekstens farve og endda dens justering (venstre, højre, center). Nedenfor er noget kode, der tegner tekst på skærmen.
```javascript
ctx.font = "30px Arial";
@ -30,14 +30,14 @@ ctx.fillText("show this on the screen", 0, 0);
## Liv som et spilkoncept
Konceptet med at have liv i et spil er blot et tal. I konteksten af et rumspil er det almindeligt at tildele et sæt liv, der bliver trukket fra ét ad gangen, når dit rumskib tager skade. Det er en god idé at vise en grafisk repræsentation af dette, som for eksempel små rumskibe eller hjerter i stedet for et tal.
Konceptet med at have liv i et spil er blot et tal. I konteksten af et rumspil er det almindeligt at tildele et sæt liv, som trækkes fra ét ad gangen, når dit skib tager skade. Det er en god idé at vise en grafisk repræsentation af dette, som for eksempel små skibe eller hjerter i stedet for et tal.
## Hvad skal bygges
Lad os tilføje følgende til dit spil:
- **Spilscore**: For hver fjendtlig rumskib, der bliver ødelagt, skal helten tildeles nogle point. Vi foreslår 100 point pr. skib. Spilscoren skal vises nederst til venstre.
- **Liv**: Dit rumskib har tre liv. Du mister et liv, hver gang et fjendtligt rumskib kolliderer med dig. En livscore skal vises nederst til højre og bestå af følgende grafik ![livsbillede](../../../../translated_images/life.6fb9f50d53ee0413cd91aa411f7c296e10a1a6de5c4a4197c718b49bf7d63ebf.da.png).
- **Spilscore**: For hver fjendeskib, der bliver ødelagt, skal helten tildeles nogle point. Vi foreslår 100 point pr. skib. Spilscoren skal vises nederst til venstre.
- **Liv**: Dit skib har tre liv. Du mister et liv, hver gang et fjendeskib kolliderer med dig. En livscore skal vises nederst til højre og bestå af følgende grafik ![livsbillede](../../../../translated_images/life.6fb9f50d53ee0413cd91aa411f7c296e10a1a6de5c4a4197c718b49bf7d63ebf.da.png).
## Anbefalede trin
@ -53,24 +53,24 @@ Find de filer, der er blevet oprettet til dig i undermappen `your-work`. Den bø
-| package.json
```
Start dit projekt i mappen `your_work` ved at skrive:
Du starter dit projekt i mappen `your_work` ved at skrive:
```bash
cd your-work
npm start
```
Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åbn en browser og indtast den adresse. Lige nu bør den vise helten og alle fjenderne, og når du trykker på venstre og højre piletaster, bevæger helten sig og kan skyde fjender ned.
Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åbn en browser og indtast den adresse. Lige nu bør den vise helten og alle fjenderne, og når du trykker på dine venstre og højre piletaster, bevæger helten sig og kan skyde fjender ned.
### Tilføj kode
1. **Kopier de nødvendige aktiver** fra mappen `solution/assets/` til mappen `your-work`; du vil tilføje en `life.png`-fil. Tilføj lifeImg til funktionen window.onload:
1. **Kopier de nødvendige ressourcer** fra mappen `solution/assets/` til mappen `your-work`; du skal tilføje en `life.png`-ressource. Tilføj `lifeImg` til `window.onload`-funktionen:
```javascript
lifeImg = await loadTexture("assets/life.png");
```
1. Tilføj `lifeImg` til listen over aktiver:
1. Tilføj `lifeImg` til listen over ressourcer:
```javascript
let heroImg,
@ -82,7 +82,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
2. **Tilføj variabler**. Tilføj kode, der repræsenterer din samlede score (0) og resterende liv (3), og vis disse scores på skærmen.
3. **Udvid `updateGameObjects()`-funktionen**. Udvid `updateGameObjects()`-funktionen til at håndtere fjendtlige kollisioner:
3. **Udvid `updateGameObjects()`-funktionen**. Udvid `updateGameObjects()`-funktionen til at håndtere fjendekollisioner:
```javascript
enemies.forEach(enemy => {
@ -94,7 +94,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
```
4. **Tilføj `liv` og `point`**.
1. **Initialiser variabler**. Under `this.cooldown = 0` i klassen `Hero`, sæt liv og point:
1. **Initialiser variabler**. Under `this.cooldown = 0` i `Hero`-klassen, sæt liv og point:
```javascript
this.life = 3;
@ -128,7 +128,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
```
1. **Tilføj metoder til spil-loopet**. Sørg for at tilføje disse funktioner til din window.onload-funktion under `updateGameObjects()`:
1. **Tilføj metoder til spilloopet**. Sørg for at tilføje disse funktioner til din `window.onload`-funktion under `updateGameObjects()`:
```javascript
drawPoints();
@ -137,9 +137,9 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
1. **Implementer spilleregler**. Implementer følgende spilleregler:
1. **For hver kollision mellem helten og en fjende**, træk et liv fra.
1. **For hver helt og fjendekollision**, træk et liv fra.
Udvid klassen `Hero` til at gøre dette fradrag:
Udvid `Hero`-klassen til at gøre dette fradrag:
```javascript
decrementLife() {
@ -152,7 +152,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
2. **For hver laser, der rammer en fjende**, øg spilscoren med 100 point.
Udvid klassen Hero til at gøre denne forøgelse:
Udvid `Hero`-klassen til at gøre denne forøgelse:
```javascript
incrementPoints() {
@ -175,9 +175,9 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
});
```
✅ Lav lidt research for at opdage andre spil, der er lavet med JavaScript/Canvas. Hvad er deres fælles træk?
✅ Lav lidt research for at opdage andre spil, der er lavet med JavaScript/Canvas. Hvad er deres fællestræk?
Når du er færdig med dette arbejde, bør du kunne se de små 'livs'-rumskibe nederst til højre, point nederst til venstre, og du bør se din livstæller falde, når du kolliderer med fjender, og dine point stige, når du skyder fjender. Godt gået! Dit spil er næsten færdigt.
Når du er færdig med dette arbejde, bør du kunne se de små 'livsskibe' nederst til højre, point nederst til venstre, og du bør se din livstæller falde, når du kolliderer med fjender, og dine point stige, når du skyder fjender. Godt gået! Dit spil er næsten færdigt.
---
@ -185,13 +185,13 @@ Når du er færdig med dette arbejde, bør du kunne se de små 'livs'-rumskibe n
Din kode er næsten færdig. Kan du forestille dig dine næste skridt?
## Quiz efter lektion
## Quiz efter lektionen
[Quiz efter lektion](https://ff-quizzes.netlify.app/web/quiz/38)
[Quiz efter lektionen](https://ff-quizzes.netlify.app/web/quiz/38)
## Gennemgang & Selvstudie
Undersøg nogle måder, hvorpå du kan øge og mindske spilscorer og liv. Der findes nogle interessante spilmotorer som [PlayFab](https://playfab.com). Hvordan kunne brugen af en af disse forbedre dit spil?
Undersøg nogle måder, hvorpå du kan øge og mindske spilscore og liv. Der findes nogle interessante spilmotorer som [PlayFab](https://playfab.com). Hvordan kunne brugen af en af disse forbedre dit spil?
## Opgave
@ -200,4 +200,4 @@ Undersøg nogle måder, hvorpå du kan øge og mindske spilscorer og liv. Der fi
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at opnå nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,36 +1,36 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "01336cddd638242e99b133614111ea40",
"translation_date": "2025-08-26T22:08:41+00:00",
"original_hash": "05be6c37791668e3719c4fba94566367",
"translation_date": "2025-08-29T08:14:46+00:00",
"source_file": "6-space-game/6-end-condition/README.md",
"language_code": "da"
}
-->
# Byg et Rumspil Del 6: Afslutning og Genstart
# Byg et Rumspil Del 6: Afslut og Genstart
## Quiz før forelæsning
[Quiz før forelæsning](https://ff-quizzes.netlify.app/web/quiz/39)
Der er forskellige måder at udtrykke en *slutbetingelse* i et spil. Det er op til dig som spillets skaber at definere, hvorfor spillet er slut. Her er nogle mulige grunde, hvis vi antager, at vi taler om det rumspil, du har bygget indtil videre:
Der er forskellige måder at udtrykke en *slutbetingelse* i et spil. Det er op til dig som spilskaber at definere, hvorfor spillet slutter. Her er nogle mulige grunde, hvis vi antager, at vi taler om det rumspil, du har bygget indtil videre:
- **`N` fjendtlige skibe er blevet ødelagt**: Det er ret almindeligt, hvis du deler et spil op i forskellige niveauer, at du skal ødelægge `N` fjendtlige skibe for at fuldføre et niveau.
- **`N` fjendtlige skibe er blevet ødelagt**: Det er ret almindeligt, hvis du opdeler et spil i forskellige niveauer, at du skal ødelægge `N` fjendtlige skibe for at fuldføre et niveau.
- **Dit skib er blevet ødelagt**: Der findes helt sikkert spil, hvor du taber, hvis dit skib bliver ødelagt. En anden almindelig tilgang er at have et koncept med liv. Hver gang dit skib bliver ødelagt, mister du et liv. Når alle liv er tabt, taber du spillet.
- **Du har samlet `N` point**: En anden almindelig slutbetingelse er, at du samler point. Hvordan du får point, er op til dig, men det er ret almindeligt at tildele point til forskellige aktiviteter som at ødelægge et fjendtligt skib eller måske samle genstande, som bliver *droppet*, når de ødelægges.
- **Fuldfør et niveau**: Dette kan involvere flere betingelser såsom `X` fjendtlige skibe ødelagt, `Y` point samlet eller måske, at en specifik genstand er blevet samlet.
- **Du har samlet `N` point**: En anden almindelig slutbetingelse er, at du skal samle point. Hvordan du får point, er op til dig, men det er ret almindeligt at tildele point for forskellige aktiviteter som at ødelægge et fjendtligt skib eller måske samle genstande, som bliver *droppet*, når de ødelægges.
- **Fuldfør et niveau**: Dette kan involvere flere betingelser, såsom `X` fjendtlige skibe ødelagt, `Y` point samlet eller måske, at en specifik genstand er blevet samlet.
## Genstart
Hvis folk nyder dit spil, vil de sandsynligvis gerne spille det igen. Når spillet slutter af en eller anden grund, bør du tilbyde en mulighed for at genstarte.
✅ Tænk lidt over, under hvilke betingelser du synes, et spil slutter, og hvordan du bliver bedt om at genstarte.
✅ Tænk lidt over, under hvilke betingelser du synes, et spil slutter, og hvordan du bliver opfordret til at genstarte.
## Hvad skal bygges
Du vil tilføje disse regler til dit spil:
Du skal tilføje følgende regler til dit spil:
1. **Vind spillet**. Når alle fjendtlige skibe er blevet ødelagt, vinder du spillet. Derudover skal der vises en form for sejrsmelding.
1. **Vinde spillet**. Når alle fjendtlige skibe er blevet ødelagt, vinder du spillet. Derudover skal der vises en form for sejrsmeddelelse.
1. **Genstart**. Når alle dine liv er tabt, eller spillet er vundet, skal du tilbyde en måde at genstarte spillet på. Husk! Du skal reinitialisere spillet, og den tidligere spiltilstand skal ryddes.
## Anbefalede trin
@ -48,20 +48,20 @@ Find de filer, der er blevet oprettet til dig i undermappen `your-work`. Den bø
-| package.json
```
Start dit projekt i mappen `your_work` ved at skrive:
Du starter dit projekt i mappen `your_work` ved at skrive:
```bash
cd your-work
npm start
```
Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åbn en browser og indtast den adresse. Dit spil bør være i en spilbar tilstand.
Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åbn en browser, og indtast den adresse. Dit spil bør være i en spilbar tilstand.
> tip: For at undgå advarsler i Visual Studio Code, rediger funktionen `window.onload` til at kalde `gameLoopId` som den er (uden `let`), og deklarer `gameLoopId` øverst i filen, uafhængigt: `let gameLoopId;`
> tip: For at undgå advarsler i Visual Studio Code skal du redigere funktionen `window.onload` til at kalde `gameLoopId` som den er (uden `let`), og erklære `gameLoopId` øverst i filen uafhængigt: `let gameLoopId;`
### Tilføj kode
1. **Spor slutbetingelse**. Tilføj kode, der holder styr på antallet af fjender, eller om helteskibet er blevet ødelagt ved at tilføje disse to funktioner:
1. **Spor slutbetingelse**. Tilføj kode, der holder styr på antallet af fjender, eller om helteskibet er blevet ødelagt, ved at tilføje disse to funktioner:
```javascript
function isHeroDead() {
@ -74,7 +74,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
}
```
1. **Tilføj logik til beskedhåndtering**. Rediger `eventEmitter` til at håndtere disse betingelser:
1. **Tilføj logik til meddelelseshåndterere**. Rediger `eventEmitter` til at håndtere disse betingelser:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
@ -108,16 +108,16 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
});
```
1. **Tilføj nye beskedtyper**. Tilføj disse beskeder til constants-objektet:
1. **Tilføj nye meddelelsestyper**. Tilføj disse meddelelser til konstantobjektet:
```javascript
GAME_END_LOSS: "GAME_END_LOSS",
GAME_END_WIN: "GAME_END_WIN",
```
2. **Tilføj genstartskode**. Tilføj kode, der genstarter spillet ved tryk på en valgt knap.
2. **Tilføj genstartskode** kode, der genstarter spillet ved tryk på en valgt knap.
1. **Lyt til tastetryk `Enter`**. Rediger din vindues eventListener til at lytte efter dette tryk:
1. **Lyt efter tastetryk `Enter`**. Rediger din vindues `eventListener` til at lytte efter dette tryk:
```javascript
else if(evt.key === "Enter") {
@ -125,7 +125,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
}
```
1. **Tilføj genstartsbesked**. Tilføj denne besked til din Messages constant:
1. **Tilføj genstartsmeddelelse**. Tilføj denne meddelelse til dine meddelelseskonstanter:
```javascript
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
@ -133,9 +133,9 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
1. **Implementer spilleregler**. Implementer følgende spilleregler:
1. **Spillerens vindbetingelse**. Når alle fjendtlige skibe er ødelagt, vis en sejrsmelding.
1. **Spillerens sejrsbetingelse**. Når alle fjendtlige skibe er ødelagt, vis en sejrsmeddelelse.
1. Først, opret en `displayMessage()`-funktion:
1. Først skal du oprette en funktion `displayMessage()`:
```javascript
function displayMessage(message, color = "red") {
@ -146,7 +146,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
}
```
1. Opret en `endGame()`-funktion:
1. Opret en funktion `endGame()`:
```javascript
function endGame(win) {
@ -171,7 +171,7 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
}
```
1. **Genstartlogik**. Når alle liv er tabt, eller spilleren har vundet spillet, vis, at spillet kan genstartes. Genstart desuden spillet, når genstartstasten trykkes (du kan beslutte, hvilken tast der skal bruges til genstart).
1. **Genstartlogik**. Når alle liv er tabt, eller spilleren har vundet spillet, vis, at spillet kan genstartes. Genstart desuden spillet, når genstartstasten trykkes (du kan selv bestemme, hvilken tast der skal bruges til genstart).
1. Opret funktionen `resetGame()`:
@ -210,13 +210,13 @@ Ovenstående vil starte en HTTP-server på adressen `http://localhost:5000`. Åb
}
```
👽 💥 🚀 Tillykke, kaptajn! Dit spil er færdigt! Godt klaret! 🚀 💥 👽
👽 💥 🚀 Tillykke, Kaptajn! Dit spil er færdigt! Godt klaret! 🚀 💥 👽
---
## 🚀 Udfordring
Tilføj en lyd! Kan du tilføje en lyd for at forbedre din spiloplevelse, måske når der er et laserhit, eller helten dør eller vinder? Se denne [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) for at lære, hvordan man afspiller lyd med JavaScript.
Tilføj en lyd! Kan du tilføje en lyd for at forbedre din spiloplevelse, måske når der er et laserhit, eller når helten dør eller vinder? Tag et kig på denne [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) for at lære, hvordan man afspiller lyd ved hjælp af JavaScript.
## Quiz efter forelæsning
@ -224,13 +224,13 @@ Tilføj en lyd! Kan du tilføje en lyd for at forbedre din spiloplevelse, måske
## Gennemgang & Selvstudie
Din opgave er at skabe et nyt prøve-spil, så udforsk nogle af de interessante spil derude for at se, hvilken type spil du kunne bygge.
Din opgave er at skabe et nyt eksempelspil, så udforsk nogle af de interessante spil derude for at se, hvilken type spil du kunne bygge.
## Opgave
[Byg et prøve-spil](assignment.md)
[Byg et Eksempelspil](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,13 +1,13 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "8da1b5e2c63f749808858c53f37b8ce7",
"translation_date": "2025-08-26T23:05:46+00:00",
"original_hash": "8a07db14e75ac62f013b7de5df05981d",
"translation_date": "2025-08-29T08:08:59+00:00",
"source_file": "7-bank-project/1-template-route/README.md",
"language_code": "da"
}
-->
# Byg en Bankapp Del 1: HTML-skabeloner og Ruter i en Webapp
# Byg en bankapp Del 1: HTML-skabeloner og ruter i en webapp
## Quiz før lektionen
@ -15,7 +15,7 @@ CO_OP_TRANSLATOR_METADATA:
### Introduktion
Siden JavaScript blev introduceret i browsere, er hjemmesider blevet mere interaktive og komplekse end nogensinde før. Webteknologier bruges nu ofte til at skabe fuldt funktionelle applikationer, der kører direkte i en browser, og som vi kalder [webapplikationer](https://en.wikipedia.org/wiki/Web_application). Da webapps er meget interaktive, ønsker brugerne ikke at vente på, at hele siden genindlæses, hver gang en handling udføres. Derfor bruges JavaScript til at opdatere HTML direkte via DOM'en for at give en mere gnidningsfri brugeroplevelse.
Siden JavaScript blev introduceret i browsere, er hjemmesider blevet mere interaktive og komplekse end nogensinde før. Webteknologier bruges nu ofte til at skabe fuldt funktionelle applikationer, der kører direkte i en browser, og som vi kalder [webapplikationer](https://en.wikipedia.org/wiki/Web_application). Da webapps er meget interaktive, ønsker brugerne ikke at vente på, at hele siden genindlæses, hver gang en handling udføres. Derfor bruges JavaScript til at opdatere HTML direkte via DOM'en for at give en mere flydende brugeroplevelse.
I denne lektion vil vi lægge fundamentet for at skabe en bankwebapp ved at bruge HTML-skabeloner til at lave flere skærme, der kan vises og opdateres uden at genindlæse hele HTML-siden.
@ -25,7 +25,7 @@ Du skal bruge en lokal webserver for at teste den webapp, vi bygger i denne lekt
### Forberedelse
På din computer skal du oprette en mappe kaldet `bank` med en fil ved navn `index.html` indeni. Vi starter med denne HTML [grundstruktur](https://en.wikipedia.org/wiki/Boilerplate_code):
På din computer skal du oprette en mappe kaldet `bank` med en fil ved navn `index.html` indeni. Vi starter med denne HTML-[grundstruktur](https://en.wikipedia.org/wiki/Boilerplate_code):
```html
<!DOCTYPE html>
@ -45,26 +45,26 @@ På din computer skal du oprette en mappe kaldet `bank` med en fil ved navn `ind
## HTML-skabeloner
Hvis du vil oprette flere skærme til en webside, kunne en løsning være at lave én HTML-fil for hver skærm, du vil vise. Men denne løsning har nogle ulemper:
Hvis du vil oprette flere skærme til en webside, kunne en løsning være at lave en HTML-fil for hver skærm, du vil vise. Denne løsning har dog nogle ulemper:
- Hele HTML'en skal genindlæses, når du skifter skærm, hvilket kan være langsomt.
- Du skal genindlæse hele HTML'en, når du skifter skærm, hvilket kan være langsomt.
- Det er svært at dele data mellem de forskellige skærme.
En anden tilgang er at have kun én HTML-fil og definere flere [HTML-skabeloner](https://developer.mozilla.org/docs/Web/HTML/Element/template) ved hjælp af `<template>`-elementet. En skabelon er en genanvendelig HTML-blok, der ikke vises af browseren og skal instansieres ved kørselstidspunktet ved hjælp af JavaScript.
En anden tilgang er kun at have én HTML-fil og definere flere [HTML-skabeloner](https://developer.mozilla.org/docs/Web/HTML/Element/template) ved hjælp af `<template>`-elementet. En skabelon er en genanvendelig HTML-blok, der ikke vises af browseren og skal instansieres under kørslen ved hjælp af JavaScript.
### Opgave
Vi opretter en bankapp med to skærme: login-siden og dashboardet. Først tilføjer vi i HTML-body'en et pladsholder-element, som vi vil bruge til at instansiere de forskellige skærme i vores app:
Vi vil oprette en bankapp med to skærme: login-siden og dashboardet. Først tilføjer vi i HTML-body'en et pladsholder-element, som vi vil bruge til at instansiere de forskellige skærme i vores app:
```html
<div id="app">Loading...</div>
```
Vi giver det en `id` for at gøre det nemmere at finde det med JavaScript senere.
Vi giver det et `id` for at gøre det nemmere at finde det med JavaScript senere.
> Tip: Da indholdet af dette element vil blive erstattet, kan vi indsætte en indlæsningsmeddelelse eller indikator, der vises, mens appen indlæses.
Dernæst tilføjer vi HTML-skabelonen til login-siden nedenfor. For nu vil vi kun tilføje en titel og en sektion, der indeholder et link, som vi vil bruge til navigation.
Dernæst tilføjer vi HTML-skabelonen til login-siden nedenfor. For nu vil vi kun tilføje en titel og en sektion med et link, som vi vil bruge til at navigere.
```html
<template id="login">
@ -106,7 +106,7 @@ Derefter tilføjer vi en anden HTML-skabelon til dashboard-siden. Denne side vil
</template>
```
> Tip: Når du opretter HTML-skabeloner, kan du, hvis du vil se, hvordan de ser ud, kommentere `<template>` og `</template>` linjerne ved at omslutte dem med `<!-- -->`.
> Tip: Når du opretter HTML-skabeloner, kan du, hvis du vil se, hvordan de ser ud, kommentere `<template>`- og `</template>`-linjerne ved at omslutte dem med `<!-- -->`.
✅ Hvorfor tror du, vi bruger `id`-attributter på skabelonerne? Kunne vi bruge noget andet som klasser?
@ -114,7 +114,7 @@ Derefter tilføjer vi en anden HTML-skabelon til dashboard-siden. Denne side vil
Hvis du prøver din nuværende HTML-fil i en browser, vil du se, at den sidder fast på "Loading...". Det skyldes, at vi skal tilføje noget JavaScript-kode for at instansiere og vise HTML-skabelonerne.
Instansiering af en skabelon sker normalt i 3 trin:
At instansiere en skabelon gøres normalt i 3 trin:
1. Hent skabelonelementet i DOM'en, for eksempel ved hjælp af [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Klon skabelonelementet ved hjælp af [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
@ -154,7 +154,7 @@ updateRoute('login');
## Oprettelse af ruter
Når vi taler om en webapp, kalder vi *Routing* intentionen om at kortlægge **URL'er** til specifikke skærme, der skal vises. På en hjemmeside med flere HTML-filer sker dette automatisk, da filstierne afspejles i URL'en. For eksempel med disse filer i din projektmappe:
Når vi taler om en webapp, kalder vi *Routing* for hensigten om at kortlægge **URLs** til specifikke skærme, der skal vises. På et websted med flere HTML-filer sker dette automatisk, da filstierne afspejles i URL'en. For eksempel med disse filer i din projektmappe:
```
mywebsite/index.html
@ -183,7 +183,7 @@ const routes = {
};
```
Lad os nu ændre lidt på `updateRoute`-funktionen. I stedet for at sende `templateId` direkte som et argument, vil vi hente det ved først at kigge på den aktuelle URL og derefter bruge vores kort til at få den tilsvarende skabelon-id-værdi. Vi kan bruge [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) til kun at få stisektionen fra URL'en.
Lad os nu ændre funktionen `updateRoute` en smule. I stedet for at sende `templateId` direkte som et argument, vil vi hente det ved først at kigge på den aktuelle URL og derefter bruge vores kort til at få den tilsvarende skabelon-id-værdi. Vi kan bruge [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) til kun at få sti-sektionen fra URL'en.
```js
function updateRoute() {
@ -198,7 +198,7 @@ function updateRoute() {
}
```
Her kortlagde vi de ruter, vi erklærede, til den tilsvarende skabelon. Du kan prøve, at det fungerer korrekt ved manuelt at ændre URL'en i din browser.
Her kortlagde vi de ruter, vi erklærede, til den tilsvarende skabelon. Du kan prøve, om det fungerer korrekt, ved manuelt at ændre URL'en i din browser.
✅ Hvad sker der, hvis du indtaster en ukendt sti i URL'en? Hvordan kunne vi løse dette?
@ -209,11 +209,11 @@ Det næste trin for vores app er at tilføje muligheden for at navigere mellem s
1. Opdatering af den aktuelle URL
2. Opdatering af den viste skabelon baseret på den nye URL
Vi har allerede taget os af den anden del med `updateRoute`-funktionen, så vi skal finde ud af, hvordan vi opdaterer den aktuelle URL.
Vi har allerede taget os af den anden del med funktionen `updateRoute`, så vi skal finde ud af, hvordan vi opdaterer den aktuelle URL.
Vi skal bruge JavaScript og mere specifikt [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), som gør det muligt at opdatere URL'en og oprette en ny post i browserens historik uden at genindlæse HTML'en.
Vi skal bruge JavaScript og mere specifikt [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), som giver mulighed for at opdatere URL'en og oprette en ny post i browserens historik uden at genindlæse HTML'en.
> Bemærk: Mens HTML-anker-elementet [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) kan bruges alene til at oprette hyperlinks til forskellige URL'er, vil det som standard få browseren til at genindlæse HTML'en. Det er nødvendigt at forhindre denne adfærd, når man håndterer routing med brugerdefineret JavaScript, ved at bruge `preventDefault()`-funktionen på klikbegivenheden.
> Bemærk: Selvom HTML-anker-elementet [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) kan bruges alene til at oprette hyperlinks til forskellige URLs, vil det som standard få browseren til at genindlæse HTML'en. Det er nødvendigt at forhindre denne adfærd, når man håndterer routing med brugerdefineret JavaScript, ved at bruge funktionen `preventDefault()` på klikbegivenheden.
### Opgave
@ -226,9 +226,9 @@ function navigate(path) {
}
```
Denne metode opdaterer først den aktuelle URL baseret på den givne sti og opdaterer derefter skabelonen. Egenskaben `window.location.origin` returnerer URL-roden, hvilket gør det muligt for os at rekonstruere en komplet URL ud fra en given sti.
Denne metode opdaterer først den aktuelle URL baseret på den givne sti og opdaterer derefter skabelonen. Egenskaben `window.location.origin` returnerer URL-roden, hvilket giver os mulighed for at rekonstruere en komplet URL ud fra en given sti.
Nu hvor vi har denne funktion, kan vi tage os af problemet, vi har, hvis en sti ikke matcher nogen defineret rute. Vi ændrer `updateRoute`-funktionen ved at tilføje en fallback til en af de eksisterende ruter, hvis vi ikke kan finde et match.
Nu hvor vi har denne funktion, kan vi tage os af problemet, vi har, hvis en sti ikke matcher nogen defineret rute. Vi ændrer funktionen `updateRoute` ved at tilføje en fallback til en af de eksisterende ruter, hvis vi ikke kan finde et match.
```js
function updateRoute() {
@ -242,7 +242,7 @@ function updateRoute() {
...
```
Hvis en rute ikke kan findes, omdirigerer vi nu til `login`-siden.
Hvis en rute ikke kan findes, omdirigerer vi nu til login-siden.
Lad os nu oprette en funktion til at få URL'en, når et link klikkes, og forhindre browserens standard linkadfærd:
@ -261,23 +261,23 @@ Lad os fuldføre navigationssystemet ved at tilføje bindinger til vores *Login*
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
`event`-objektet ovenfor fanger `click`-begivenheden og sender den til vores `onLinkClick`-funktion.
Objektet `event` ovenfor fanger `click`-begivenheden og sender den til vores funktion `onLinkClick`.
Ved hjælp af [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick)-attributten binder vi `click`-begivenheden til JavaScript-koden, her kaldet til `navigate()`-funktionen.
Ved hjælp af attributten [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) binder vi `click`-begivenheden til JavaScript-koden, her kaldet til funktionen `navigate()`.
Prøv at klikke på disse links, du burde nu kunne navigere mellem de forskellige skærme i din app.
Prøv at klikke på disse links. Du burde nu kunne navigere mellem de forskellige skærme i din app.
✅ Metoden `history.pushState` er en del af HTML5-standarden og implementeret i [alle moderne browsere](https://caniuse.com/?search=pushState). Hvis du bygger en webapp til ældre browsere, er der et trick, du kan bruge i stedet for dette API: Ved at bruge et [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) før stien kan du implementere routing, der fungerer med almindelig anker-navigation og ikke genindlæser siden, da dens formål var at skabe interne links inden for en side.
## Håndtering af browserens tilbage- og fremadknapper
Brug af `history.pushState` opretter nye poster i browserens navigationshistorik. Du kan tjekke det ved at holde *tilbage-knappen* i din browser nede, det skulle vise noget som dette:
Brugen af `history.pushState` opretter nye poster i browserens navigationshistorik. Du kan tjekke det ved at holde *tilbage-knappen* i din browser, det skulle vise noget som dette:
![Skærmbillede af navigationshistorik](../../../../translated_images/history.7fdabbafa521e06455b738d3dafa3ff41d3071deae60ead8c7e0844b9ed987d8.da.png)
Hvis du prøver at klikke på tilbage-knappen et par gange, vil du se, at den aktuelle URL ændres, og historikken opdateres, men den samme skabelon bliver ved med at blive vist.
Det skyldes, at applikationen ikke ved, at vi skal kalde `updateRoute()` hver gang historikken ændres. Hvis du kigger på [`history.pushState`-dokumentationen](https://developer.mozilla.org/docs/Web/API/History/pushState), kan du se, at hvis tilstanden ændres - hvilket betyder, at vi flyttede til en anden URL - udløses [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event)-begivenheden. Vi vil bruge det til at løse dette problem.
Det skyldes, at applikationen ikke ved, at vi skal kalde `updateRoute()` hver gang historikken ændres. Hvis du kigger på dokumentationen for [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), kan du se, at hvis tilstanden ændres - hvilket betyder, at vi flyttede til en anden URL - udløses begivenheden [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event). Vi vil bruge det til at løse dette problem.
### Opgave
@ -288,13 +288,13 @@ window.onpopstate = () => updateRoute();
updateRoute();
```
> Bemærk: Vi brugte en [pilesyntaks](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) her til at erklære vores `popstate`-begivenhedshåndtering for kortfattethed, men en almindelig funktion ville fungere på samme måde.
> Bemærk: Vi brugte en [arrow-funktion](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) her til at erklære vores `popstate`-begivenhedshåndtering for kortfattethed, men en almindelig funktion ville fungere på samme måde.
Her er en genopfriskningsvideo om pilesyntaks:
Her er en genopfriskningsvideo om arrow-funktioner:
[![Pilesyntaks](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Pilesyntaks")
[![Arrow-funktioner](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Arrow-funktioner")
> 🎥 Klik på billedet ovenfor for en video om pilesyntaks.
> 🎥 Klik på billedet ovenfor for en video om arrow-funktioner.
Prøv nu at bruge tilbage- og fremadknapperne i din browser, og tjek, at den viste rute opdateres korrekt denne gang.
@ -314,9 +314,9 @@ Routing er en af de overraskende vanskelige dele af webudvikling, især efterhå
## Opgave
[Forbedr routing](assignment.md)
[Forbedr routingen](assignment.md)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "b667b7d601e2ee19acb5aa9d102dc9f3",
"translation_date": "2025-08-26T22:55:57+00:00",
"original_hash": "8baca047d77a5f43fa4099c0578afa42",
"translation_date": "2025-08-29T08:07:06+00:00",
"source_file": "7-bank-project/2-forms/README.md",
"language_code": "da"
}
@ -15,9 +15,9 @@ CO_OP_TRANSLATOR_METADATA:
### Introduktion
I næsten alle moderne webapps kan du oprette en konto for at få dit eget private område. Da flere brugere kan tilgå en webapp samtidig, har du brug for en mekanisme til at gemme hver brugers personlige data separat og vælge, hvilken information der skal vises. Vi vil ikke dække, hvordan man [håndterer brugeridentitet sikkert](https://en.wikipedia.org/wiki/Authentication), da det er et omfattende emne i sig selv, men vi vil sikre, at hver bruger kan oprette en (eller flere) bankkonti i vores app.
I næsten alle moderne webapps kan du oprette en konto for at få din egen private plads. Da flere brugere kan tilgå en webapp samtidig, har du brug for en mekanisme til at gemme hver brugers personlige data separat og vælge, hvilken information der skal vises. Vi vil ikke dække, hvordan man [håndterer brugeridentitet sikkert](https://en.wikipedia.org/wiki/Authentication), da det er et omfattende emne i sig selv, men vi vil sikre, at hver bruger kan oprette en (eller flere) bankkonti i vores app.
I denne del vil vi bruge HTML-formularer til at tilføje login og registrering til vores webapp. Vi vil se, hvordan man sender data til en server-API programmæssigt, og til sidst hvordan man definerer grundlæggende valideringsregler for brugerinput.
I denne del vil vi bruge HTML-formularer til at tilføje login og registrering til vores webapp. Vi vil se, hvordan man sender data til en server-API programmatisk, og til sidst hvordan man definerer grundlæggende valideringsregler for brugerinput.
### Forudsætninger
@ -41,9 +41,9 @@ curl http://localhost:5000/api
## Formular og kontroller
`<form>`-elementet indkapsler en sektion af et HTML-dokument, hvor brugeren kan indtaste og indsende data med interaktive kontroller. Der findes alle mulige brugergrænseflade (UI)-kontroller, der kan bruges inden for en formular, hvor de mest almindelige er `<input>`- og `<button>`-elementerne.
`<form>`-elementet indkapsler en sektion af et HTML-dokument, hvor brugeren kan indtaste og indsende data med interaktive kontroller. Der findes alle mulige brugergrænseflade (UI)-kontroller, der kan bruges inden for en formular, hvor de mest almindelige er `<input>` og `<button>`-elementerne.
Der er mange forskellige [typer](https://developer.mozilla.org/docs/Web/HTML/Element/input) af `<input>`. For eksempel kan du oprette et felt, hvor brugeren kan indtaste sit brugernavn, ved at bruge:
Der er mange forskellige [typer](https://developer.mozilla.org/docs/Web/HTML/Element/input) af `<input>`. For eksempel, for at oprette et felt, hvor brugeren kan indtaste sit brugernavn, kan du bruge:
```html
<input id="username" name="username" type="text">
@ -55,7 +55,7 @@ Der er mange forskellige [typer](https://developer.mozilla.org/docs/Web/HTML/Ele
✅ Bemærk, at `<input>` er et [tomt element](https://developer.mozilla.org/docs/Glossary/Empty_element), som du *ikke* bør tilføje en matchende afsluttende tag til. Du kan dog bruge den selv-lukkende `<input/>`-notation, men det er ikke nødvendigt.
`<button>`-elementet inden for en formular er lidt specielt. Hvis du ikke angiver dets `type`-attribut, vil det automatisk indsende formularens data til serveren, når det trykkes. Her er de mulige `type`-værdier:
`<button>`-elementet inden for en formular er lidt specielt. Hvis du ikke angiver dens `type`-attribut, vil den automatisk indsende formularens data til serveren, når den trykkes. Her er de mulige `type`-værdier:
- `submit`: Standard inden for en `<form>`, knappen udløser formularens indsendelseshandling.
- `reset`: Knappen nulstiller alle formularens kontroller til deres oprindelige værdier.
@ -79,7 +79,7 @@ Lad os starte med at tilføje en formular til `login`-skabelonen. Vi skal bruge
</template>
```
Hvis du ser nærmere på, kan du bemærke, at vi også har tilføjet et `<label>`-element her. `<label>`-elementer bruges til at tilføje et navn til UI-kontroller, såsom vores brugernavnfelt. Labels er vigtige for læsbarheden af dine formularer, men de har også yderligere fordele:
Hvis du ser nærmere på, kan du bemærke, at vi også har tilføjet et `<label>`-element her. `<label>`-elementer bruges til at tilføje et navn til UI-kontroller, såsom vores brugernavnsfelt. Labels er vigtige for læsbarheden af dine formularer, men kommer også med yderligere fordele:
- Ved at associere en label med en formularkontrol hjælper det brugere, der bruger hjælpemidler (som en skærmlæser), med at forstå, hvilke data de forventes at indtaste.
- Du kan klikke på labelen for direkte at sætte fokus på den tilknyttede input, hvilket gør det lettere at nå på enheder med berøringsskærm.
@ -105,13 +105,13 @@ Nu tilføjer vi en anden formular til registrering, lige under den forrige:
```
Ved hjælp af `value`-attributten kan vi definere en standardværdi for en given input.
Bemærk også, at input for `balance` har typen `number`. Ser det anderledes ud end de andre inputs? Prøv at interagere med det.
Bemærk også, at inputtet for `balance` har typen `number`. Ser det anderledes ud end de andre inputs? Prøv at interagere med det.
✅ Kan du navigere og interagere med formularerne ved hjælp af kun et tastatur? Hvordan ville du gøre det?
✅ Kan du navigere og interagere med formularerne ved kun at bruge et tastatur? Hvordan ville du gøre det?
## Indsendelse af data til serveren
Nu hvor vi har en funktionel brugergrænseflade, er næste skridt at sende dataene videre til vores server. Lad os lave en hurtig test med vores nuværende kode: hvad sker der, hvis du klikker på *Login*- eller *Register*-knappen?
Nu hvor vi har en funktionel brugergrænseflade, er næste skridt at sende data til vores server. Lad os lave en hurtig test med vores nuværende kode: hvad sker der, hvis du klikker på *Login*- eller *Register*-knappen?
Bemærkede du ændringen i browserens URL-sektion?
@ -125,7 +125,7 @@ Standardhandlingen for en `<form>` er at indsende formularen til den aktuelle se
Derfor kan du ændre det til at bruge [POST-metoden](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5), som sender formularens data til serveren i HTTP-anmodningens body, uden nogen af de tidligere begrænsninger.
> Selvom POST er den mest almindeligt anvendte metode til at sende data, [i nogle specifikke scenarier](https://www.w3.org/2001/tag/doc/whenToUseGet.html) er det bedre at bruge GET-metoden, for eksempel når man implementerer et søgefelt.
> Selvom POST er den mest almindeligt anvendte metode til at sende data, [kan det i nogle specifikke scenarier](https://www.w3.org/2001/tag/doc/whenToUseGet.html) være bedre at bruge GET-metoden, f.eks. når man implementerer et søgefelt.
### Opgave
@ -147,7 +147,7 @@ Hvis alt går godt, bør serveren svare på din anmodning med et [JSON](https://
Som du sikkert har bemærket, er der et lille problem med den tilgang, vi lige brugte: når formularen indsendes, forlader vi vores app, og browseren omdirigerer til serverens URL. Vi forsøger at undgå alle sidegenindlæsninger med vores webapp, da vi laver en [Single-page application (SPA)](https://en.wikipedia.org/wiki/Single-page_application).
For at sende formularens data til serveren uden at tvinge en sidegenindlæsning skal vi bruge JavaScript-kode. I stedet for at sætte en URL i `action`-egenskaben for et `<form>`-element, kan du bruge enhver JavaScript-kode, der er foranstillet med `javascript:`-strengen, til at udføre en brugerdefineret handling. Ved at bruge dette betyder det også, at du skal implementere nogle opgaver, som tidligere blev udført automatisk af browseren:
For at sende formularens data til serveren uden at tvinge en sidegenindlæsning, skal vi bruge JavaScript-kode. I stedet for at sætte en URL i `action`-egenskaben for et `<form>`-element, kan du bruge enhver JavaScript-kode, der begynder med `javascript:`-strengen, til at udføre en brugerdefineret handling. Ved at bruge dette betyder det også, at du skal implementere nogle opgaver, som tidligere blev gjort automatisk af browseren:
- Hente formularens data
- Konvertere og kode formularens data til et passende format
@ -191,7 +191,7 @@ async function createAccount(account) {
}
```
Hvad gør denne funktion? Bemærk først `async`-nøgleordet her. Det betyder, at funktionen indeholder kode, der vil blive udført [**asynkront**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Når det bruges sammen med `await`-nøgleordet, giver det mulighed for at vente på, at asynkron kode udføres - som at vente på serverens svar her - før man fortsætter.
Hvad gør denne funktion? Først, bemærk `async`-nøgleordet her. Det betyder, at funktionen indeholder kode, der vil blive udført [**asynkront**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Når det bruges sammen med `await`-nøgleordet, giver det mulighed for at vente på, at asynkron kode udføres - som at vente på serverens svar her - før man fortsætter.
Her er en kort video om brugen af `async/await`:
@ -201,12 +201,12 @@ Her er en kort video om brugen af `async/await`:
Vi bruger `fetch()`-API'en til at sende JSON-data til serveren. Denne metode tager 2 parametre:
- Serverens URL, så vi sætter `//localhost:5000/api/accounts` her igen.
- Serverens URL, så vi sætter `//localhost:5000/api/accounts` her.
- Indstillingerne for anmodningen. Det er her, vi sætter metoden til `POST` og angiver `body` for anmodningen. Da vi sender JSON-data til serveren, skal vi også sætte `Content-Type`-headeren til `application/json`, så serveren ved, hvordan den skal fortolke indholdet.
Da serveren vil svare på anmodningen med JSON, kan vi bruge `await response.json()` til at analysere JSON-indholdet og returnere det resulterende objekt. Bemærk, at denne metode er asynkron, så vi bruger `await`-nøgleordet her før returnering for at sikre, at eventuelle fejl under analysen også fanges.
Da serveren vil svare på anmodningen med JSON, kan vi bruge `await response.json()` til at analysere JSON-indholdet og returnere det resulterende objekt. Bemærk, at denne metode er asynkron, så vi bruger `await`-nøgleordet her før returneringen for at sikre, at eventuelle fejl under analysen også fanges.
Tilføj nu noget kode til `register`-funktionen for at kalde `createAccount()`:
Nu tilføjer vi noget kode til `register`-funktionen for at kalde `createAccount()`:
```js
const result = await createAccount(jsonData);
@ -245,14 +245,14 @@ Det var lidt langt, men vi kom i mål! Hvis du åbner dine [browserudviklerværk
Hvis du prøver at registrere en ny konto uden først at angive et brugernavn, kan du se, at serveren returnerer en fejl med statuskode [400 (Bad Request)](https://developer.mozilla.org/docs/Web/HTTP/Status/400#:~:text=The%20HyperText%20Transfer%20Protocol%20(HTTP,%2C%20or%20deceptive%20request%20routing).).
Før du sender data til en server, er det en god praksis at [validere formularens data](https://developer.mozilla.org/docs/Learn/Forms/Form_validation) på forhånd, når det er muligt, for at sikre, at du sender en gyldig anmodning. HTML5-formularkontroller tilbyder indbygget validering ved hjælp af forskellige attributter:
Før du sender data til en server, er det en god praksis at [validere formularens data](https://developer.mozilla.org/docs/Learn/Forms/Form_validation) på forhånd, når det er muligt, for at sikre, at du sender en gyldig anmodning. HTML5-formularkontroller giver indbygget validering ved hjælp af forskellige attributter:
- `required`: Feltet skal udfyldes, ellers kan formularen ikke indsendes.
- `minlength` og `maxlength`: Definerer det minimale og maksimale antal tegn i tekstfelter.
- `min` og `max`: Definerer den minimale og maksimale værdi for et numerisk felt.
- `type`: Definerer den type data, der forventes, såsom `number`, `email`, `file` eller [andre indbyggede typer](https://developer.mozilla.org/docs/Web/HTML/Element/input). Denne attribut kan også ændre den visuelle rendering af formularens kontrol.
- `pattern`: Tillader at definere et [regulært udtryk](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_Expressions) mønster for at teste, om de indtastede data er gyldige eller ej.
> Tip: du kan tilpasse udseendet af dine formularkontroller afhængigt af, om de er gyldige eller ej, ved at bruge CSS-pseudoklasserne `:valid` og `:invalid`.
- `pattern`: Tillader at definere et [regulært udtryk](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_Expressions)-mønster for at teste, om de indtastede data er gyldige eller ej.
> Tip: Du kan tilpasse udseendet af dine formularfelter afhængigt af, om de er gyldige eller ej, ved at bruge CSS-pseudoklasserne `:valid` og `:invalid`.
### Opgave
Der er 2 obligatoriske felter for at oprette en gyldig ny konto: brugernavn og valuta. De øvrige felter er valgfrie. Opdater formularens HTML ved at bruge både attributten `required` og tekst i feltets label, så det ser sådan ud:
@ -265,7 +265,7 @@ Der er 2 obligatoriske felter for at oprette en gyldig ny konto: brugernavn og v
<input id="currency" name="currency" type="text" value="$" required>
```
Selvom denne specifikke serverimplementering ikke håndhæver specifikke grænser for felternes maksimale længde, er det altid en god praksis at definere rimelige grænser for enhver tekstindtastning fra brugeren.
Selvom denne specifikke serverimplementering ikke håndhæver specifikke grænser for felternes maksimale længde, er det altid en god praksis at definere rimelige grænser for enhver brugerindtastning.
Tilføj attributten `maxlength` til tekstfelterne:
@ -277,19 +277,19 @@ Tilføj attributten `maxlength` til tekstfelterne:
<input id="description" name="description" type="text" maxlength="100">
```
Hvis du nu trykker på *Registrer* knappen, og et felt ikke overholder en valideringsregel, vi har defineret, vil du se noget som dette:
Hvis du nu trykker på *Registrer* knappen, og et felt ikke overholder en af de valideringsregler, vi har defineret, vil du se noget som dette:
![Skærmbillede, der viser valideringsfejl ved forsøg på at indsende formularen](../../../../translated_images/validation-error.8bd23e98d416c22f80076d04829a4bb718e0e550fd622862ef59008ccf0d5dce.da.png)
Validering som denne, der udføres *før* data sendes til serveren, kaldes **klient-side** validering. Men bemærk, at det ikke altid er muligt at udføre alle tjek uden at sende data. For eksempel kan vi her ikke kontrollere, om en konto allerede eksisterer med samme brugernavn, uden at sende en forespørgsel til serveren. Yderligere validering, der udføres på serveren, kaldes **server-side** validering.
Validering som denne, der udføres *før* nogen data sendes til serveren, kaldes **klient-side** validering. Men bemærk, at det ikke altid er muligt at udføre alle tjek uden at sende data. For eksempel kan vi her ikke tjekke, om en konto allerede eksisterer med samme brugernavn, uden at sende en forespørgsel til serveren. Yderligere validering, der udføres på serveren, kaldes **server-side** validering.
Normalt skal begge implementeres, og mens brugen af klient-side validering forbedrer brugeroplevelsen ved at give øjeblikkelig feedback til brugeren, er server-side validering afgørende for at sikre, at de brugerdata, du arbejder med, er korrekte og sikre.
Normalt skal begge implementeres, og selvom brugen af klient-side validering forbedrer brugeroplevelsen ved at give øjeblikkelig feedback til brugeren, er server-side validering afgørende for at sikre, at de brugerdata, du arbejder med, er korrekte og sikre.
---
## 🚀 Udfordring
Vis en fejlmeddelelse i HTML, hvis brugeren allerede eksisterer.
Vis en fejlmeddelelse i HTML'en, hvis brugeren allerede eksisterer.
Her er et eksempel på, hvordan den endelige login-side kan se ud efter lidt styling:
@ -310,4 +310,4 @@ Udviklere er blevet meget kreative med deres formularopbygning, især når det g
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at opnå nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "f587e913e3f7c0b1c549a05dd74ee8e5",
"translation_date": "2025-08-26T23:01:35+00:00",
"original_hash": "89d0df9854ed020f155e94882ae88d4c",
"translation_date": "2025-08-29T08:06:10+00:00",
"source_file": "7-bank-project/3-data/README.md",
"language_code": "da"
}
@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA:
### Introduktion
Kernen i enhver webapplikation er *data*. Data kan have mange former, men dens hovedformål er altid at vise information til brugeren. Med webapps, der bliver stadig mere interaktive og komplekse, er måden, brugeren tilgår og interagerer med information på, nu en vigtig del af webudvikling.
Kernen i enhver webapplikation er *data*. Data kan tage mange former, men dens hovedformål er altid at vise information til brugeren. Med webapps, der bliver stadig mere interaktive og komplekse, er måden, hvorpå brugeren tilgår og interagerer med information, nu en nøglekomponent i webudvikling.
I denne lektion vil vi se, hvordan man henter data fra en server asynkront og bruger disse data til at vise information på en webside uden at genindlæse HTML'en.
### Forudsætninger
Du skal have bygget [Login- og Registreringsformularen](../2-forms/README.md) som en del af webappen for denne lektion. Du skal også installere [Node.js](https://nodejs.org) og [køre server-API'et](../api/README.md) lokalt, så du kan få kontodata.
Du skal have bygget [Login- og Registreringsformularen](../2-forms/README.md) som en del af webappen for denne lektion. Du skal også installere [Node.js](https://nodejs.org) og [køre server-API'et](../api/README.md) lokalt, så du får kontodata.
Du kan teste, om serveren kører korrekt, ved at udføre denne kommando i en terminal:
@ -36,11 +36,11 @@ curl http://localhost:5000/api
Traditionelle websites opdaterer det viste indhold, når brugeren vælger et link eller sender data via en formular, ved at genindlæse hele HTML-siden. Hver gang nye data skal indlæses, returnerer webserveren en helt ny HTML-side, som skal behandles af browseren, hvilket afbryder den aktuelle brugerhandling og begrænser interaktioner under genindlæsningen. Denne arbejdsgang kaldes også en *Multi-Page Application* eller *MPA*.
![Opdateringsarbejdsgang i en multi-page applikation](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.da.png)
![Opdateringsarbejdsgang i en multi-side applikation](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.da.png)
Da webapplikationer begyndte at blive mere komplekse og interaktive, opstod en ny teknik kaldet [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Denne teknik gør det muligt for webapps at sende og hente data fra en server asynkront ved hjælp af JavaScript, uden at skulle genindlæse HTML-siden, hvilket resulterer i hurtigere opdateringer og mere glidende brugerinteraktioner. Når nye data modtages fra serveren, kan den aktuelle HTML-side også opdateres med JavaScript ved hjælp af [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)-API'en. Over tid har denne tilgang udviklet sig til det, der nu kaldes en [*Single-Page Application* eller *SPA*](https://en.wikipedia.org/wiki/Single-page_application).
![Opdateringsarbejdsgang i en single-page applikation](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.da.png)
![Opdateringsarbejdsgang i en single-side applikation](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.da.png)
Da AJAX først blev introduceret, var den eneste API tilgængelig for asynkron datahentning [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Men moderne browsere implementerer nu også den mere praktiske og kraftfulde [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), som bruger promises og er bedre egnet til at manipulere JSON-data.
@ -72,9 +72,9 @@ async function getAccount(user) {
}
```
Vi bruger `fetch`-API'et til at anmode om data asynkront fra serveren, men denne gang behøver vi ikke andre parametre end URL'en, da vi kun forespørger data. Som standard opretter `fetch` en [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) HTTP-forespørgsel, hvilket er det, vi søger her.
Vi bruger `fetch`-API'et til at anmode om data asynkront fra serveren, men denne gang behøver vi ikke andre parametre end URL'en, da vi kun forespørger data. Som standard opretter `fetch` en [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET)-HTTP-forespørgsel, hvilket er præcis, hvad vi har brug for her.
`encodeURIComponent()` er en funktion, der undgår specialtegn i en URL. Hvilke problemer kunne vi muligvis , hvis vi ikke kalder denne funktion og bruger `user`-værdien direkte i URL'en?
`encodeURIComponent()` er en funktion, der undgår specialtegn i en URL. Hvilke problemer kunne vi muligvis have, hvis vi ikke kalder denne funktion og bruger `user`-værdien direkte i URL'en?
Lad os nu opdatere vores `login`-funktion til at bruge `getAccount`:
@ -95,7 +95,7 @@ async function login() {
Først, da `getAccount` er en asynkron funktion, skal vi matche den med nøgleordet `await` for at vente på serverresultatet. Som med enhver serverforespørgsel skal vi også håndtere fejltilfælde. For nu vil vi kun tilføje en logbesked for at vise fejlen og vende tilbage til det senere.
Derefter skal vi gemme dataene et sted, så vi senere kan bruge dem til at vise dashboard-information. Da variablen `account` endnu ikke eksisterer, opretter vi en global variabel til den øverst i vores fil:
Derefter skal vi gemme dataene et sted, så vi senere kan bruge dem til at vise dashboard-informationen. Da variablen `account` endnu ikke eksisterer, opretter vi en global variabel til den øverst i vores fil:
```js
let account = null;
@ -118,7 +118,7 @@ account = result;
navigate('/dashboard');
```
✅ Vidste du, at du som standard kun kan kalde server-API'er fra *samme domæne og port* som den webside, du ser? Dette er en sikkerhedsmekanisme, der håndhæves af browsere. Men vent, vores webapp kører på `localhost:3000`, mens server-API'et kører på `localhost:5000`. Hvorfor virker det? Ved at bruge en teknik kaldet [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/docs/Web/HTTP/CORS) er det muligt at udføre cross-origin HTTP-forespørgsler, hvis serveren tilføjer specielle headers til svaret, der tillader undtagelser for specifikke domæner.
✅ Vidste du, at du som standard kun kan kalde server-API'er fra *samme domæne og port* som den webside, du ser? Dette er en sikkerhedsmekanisme, der håndhæves af browsere. Men vent, vores webapp kører på `localhost:3000`, mens server-API'et kører på `localhost:5000`. Hvorfor virker det? Ved at bruge en teknik kaldet [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/docs/Web/HTTP/CORS) er det muligt at udføre cross-origin HTTP-forespørgsler, hvis serveren tilføjer særlige headers til svaret, der tillader undtagelser for specifikke domæner.
> Lær mere om API'er ved at tage denne [lektion](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon)
@ -126,11 +126,11 @@ navigate('/dashboard');
Nu hvor vi har brugerdataene, skal vi opdatere den eksisterende HTML for at vise dem. Vi ved allerede, hvordan man henter et element fra DOM'en, for eksempel ved hjælp af `document.getElementById()`. Når du har et baseelement, er her nogle API'er, du kan bruge til at ændre det eller tilføje underordnede elementer til det:
- Ved hjælp af egenskaben [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) kan du ændre teksten i et element. Bemærk, at ændring af denne værdi fjerner alle elementets underordnede (hvis der er nogen) og erstatter det med den angivne tekst. Som sådan er det også en effektiv metode til at fjerne alle underordnede elementer af et givet element ved at tildele en tom streng `''` til det.
- Ved at bruge egenskaben [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) kan du ændre teksten i et element. Bemærk, at ændring af denne værdi fjerner alle elementets underordnede (hvis der er nogen) og erstatter det med den angivne tekst. Som sådan er det også en effektiv metode til at fjerne alle underordnede af et givet element ved at tildele en tom streng `''` til det.
- Ved hjælp af [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) sammen med metoden [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) kan du oprette og vedhæfte et eller flere nye underordnede elementer.
- Ved at bruge [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) sammen med metoden [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) kan du oprette og vedhæfte et eller flere nye underordnede elementer.
✅ Ved hjælp af egenskaben [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) for et element er det også muligt at ændre dets HTML-indhold, men denne bør undgås, da den er sårbar over for [cross-site scripting (XSS)](https://developer.mozilla.org/docs/Glossary/Cross-site_scripting)-angreb.
✅ Ved at bruge egenskaben [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) for et element er det også muligt at ændre dets HTML-indhold, men denne metode bør undgås, da den er sårbar over for [cross-site scripting (XSS)](https://developer.mozilla.org/docs/Glossary/Cross-site_scripting)-angreb.
### Opgave
@ -156,7 +156,7 @@ function updateElement(id, text) {
}
```
Denne er ret ligetil: givet et element-*id* og *tekst*, vil den opdatere tekstindholdet i DOM-elementet med det matchende `id`. Lad os bruge denne metode i stedet for den tidligere fejlmeddelelse i `login`-funktionen:
Denne funktion er ret ligetil: givet et element-*id* og *tekst* vil den opdatere tekstindholdet i DOM-elementet med det matchende `id`. Lad os bruge denne metode i stedet for den tidligere fejlmeddelelse i `login`-funktionen:
```js
if (data.error) {
@ -200,7 +200,7 @@ Sådan ser et kontoobjekt modtaget fra serveren ud:
### Opgave
Lad os starte med at erstatte sektionen "Balance" i HTML for at tilføje pladsholderelementer:
Lad os starte med at erstatte sektionen "Balance" i HTML'en for at tilføje pladsholderelementer:
```html
<section>
@ -230,9 +230,9 @@ function updateDashboard() {
}
```
Først tjekker vi, at vi har de kontodata, vi har brug for, før vi går videre. Derefter bruger vi funktionen `updateElement()`, som vi oprettede tidligere, til at opdatere HTML'en.
Først tjekker vi, at vi har de nødvendige kontodata, før vi går videre. Derefter bruger vi funktionen `updateElement()`, som vi oprettede tidligere, til at opdatere HTML'en.
> For at gøre balancevisningen pænere bruger vi metoden [`toFixed(2)`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) for at sikre, at værdien vises med 2 decimaler.
> For at gøre balancevisningen pænere bruger vi metoden [`toFixed(2)`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) til at tvinge visning af værdien med 2 decimaler.
Nu skal vi kalde vores `updateDashboard()`-funktion hver gang dashboardet indlæses. Hvis du allerede har afsluttet [lektion 1-opgaven](../1-template-route/assignment.md), bør dette være ligetil, ellers kan du bruge følgende implementering.
@ -297,7 +297,7 @@ function createTransactionRow(transaction) {
}
```
Denne funktion gør præcis, hvad dens navn antyder: ved hjælp af skabelonen, vi oprettede tidligere, opretter den en ny tabelrække og udfylder dens indhold med transaktionsdata. Vi vil bruge denne i vores `updateDashboard()`-funktion til at udfylde tabellen:
Denne funktion gør præcis, hvad dens navn antyder: ved hjælp af den skabelon, vi oprettede tidligere, opretter den en ny tabelrække og udfylder dens indhold med transaktionsdata. Vi vil bruge denne i vores `updateDashboard()`-funktion til at udfylde tabellen:
```js
const transactionsRows = document.createDocumentFragment();
@ -308,9 +308,9 @@ for (const transaction of account.transactions) {
updateElement('transactions', transactionsRows);
```
Her bruger vi metoden [`document.createDocumentFragment()`](https://developer.mozilla.org/docs/Web/API/Document/createDocumentFragment), der opretter et nyt DOM-fragment, som vi kan arbejde på, før vi endelig vedhæfter det til vores HTML-tabel.
Her bruger vi metoden [`document.createDocumentFragment()`](https://developer.mozilla.org/docs/Web/API/Document/createDocumentFragment), der opretter et nyt DOM-fragment, som vi kan arbejde på, før det endelig vedhæftes til vores HTML-tabel.
Der er stadig én ting, vi skal gøre, før denne kode kan fungere, da vores `updateElement()`-funktion i øjeblikket kun understøtter tekstindhold. Lad os ændre dens kode en smule:
Der er stadig én ting, vi skal gøre, før denne kode kan fungere, da vores `updateElement()`-funktion i øjeblikket kun understøtter tekstindhold. Lad os ændre dens kode lidt:
```js
function updateElement(id, textOrNode) {
@ -321,7 +321,7 @@ function updateElement(id, textOrNode) {
```
Vi bruger metoden [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append), da den gør det muligt at vedhæfte enten tekst eller [DOM Nodes](https://developer.mozilla.org/docs/Web/API/Node) til et overordnet element, hvilket er perfekt til alle vores anvendelser.
Hvis du prøver at bruge `test`-kontoen til at logge ind, bør du nu se en transaktionsliste på dashboardet 🎉.
Hvis du prøver at logge ind med `test`-kontoen, bør du nu se en transaktionsliste på dashboardet 🎉.
---
@ -331,7 +331,7 @@ Arbejd sammen om at få dashboard-siden til at ligne en rigtig bankapp. Hvis du
Her er et eksempel på en stylet dashboard-side:
![Skærmbillede af et eksempelresultat af dashboardet efter styling](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.da.png)
![Skærmbillede af et eksempel dashboardet efter styling](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.da.png)
## Quiz efter forelæsning
@ -344,4 +344,4 @@ Her er et eksempel på en stylet dashboard-side:
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,23 +1,23 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "4fa20c513e367e9cdd401bf49ae16e33",
"translation_date": "2025-08-26T23:11:09+00:00",
"original_hash": "5d2efabbc8f94d89f4317ee8646c3ce9",
"translation_date": "2025-08-29T08:08:04+00:00",
"source_file": "7-bank-project/4-state-management/README.md",
"language_code": "da"
}
-->
# Byg en Bankapp Del 4: Koncepter for Tilstandshåndtering
# Byg en Bankapp Del 4: Koncepter inden for State Management
## Quiz før Forelæsning
## Quiz før forelæsning
[Quiz før forelæsning](https://ff-quizzes.netlify.app/web/quiz/47)
### Introduktion
Når en webapplikation vokser, bliver det en udfordring at holde styr på alle dataflows. Hvilken kode henter data, hvilken side bruger det, hvor og hvornår skal det opdateres... det er nemt at ende med rodet kode, der er svær at vedligeholde. Dette gælder især, når du skal dele data mellem forskellige sider i din app, for eksempel brugerdata. Konceptet *tilstandshåndtering* har altid eksisteret i alle slags programmer, men efterhånden som webapps bliver mere komplekse, er det nu et nøglepunkt at tænke over under udviklingen.
Når en webapplikation vokser, bliver det en udfordring at holde styr på alle dataflows. Hvilken kode henter data, hvilken side bruger det, hvor og hvornår skal det opdateres...det er nemt at ende med rodet kode, der er svær at vedligeholde. Dette er især tilfældet, når du skal dele data mellem forskellige sider i din app, for eksempel brugerdata. Konceptet *state management* har altid eksisteret i alle slags programmer, men efterhånden som webapps bliver mere komplekse, er det nu et centralt punkt at tænke over under udviklingen.
I denne sidste del vil vi gennemgå den app, vi har bygget, for at genoverveje, hvordan tilstanden håndteres, så vi kan understøtte browseropdatering på ethvert tidspunkt og bevare data på tværs af brugersessioner.
I denne sidste del vil vi gennemgå den app, vi har bygget, for at genoverveje, hvordan state håndteres, så vi kan understøtte browseropdatering på ethvert tidspunkt og bevare data på tværs af brugersessioner.
### Forudsætninger
@ -32,32 +32,32 @@ curl http://localhost:5000/api
---
## Genovervej tilstandshåndtering
## Genovervej state management
I [den forrige lektion](../3-data/README.md) introducerede vi et grundlæggende koncept for tilstand i vores app med den globale `account`-variabel, som indeholder bankdata for den aktuelt loggede bruger. Men vores nuværende implementering har nogle mangler. Prøv at opdatere siden, når du er på dashboardet. Hvad sker der?
I [den forrige lektion](../3-data/README.md) introducerede vi et grundlæggende koncept for state i vores app med den globale `account`-variabel, som indeholder bankdata for den aktuelt loggede bruger. Men vores nuværende implementering har nogle mangler. Prøv at opdatere siden, når du er på dashboardet. Hvad sker der?
Der er 3 problemer med den nuværende kode:
Der er tre problemer med den nuværende kode:
- Tilstanden gemmes ikke, da en browseropdatering sender dig tilbage til login-siden.
- Der er flere funktioner, der ændrer tilstanden. Når appen vokser, kan det gøre det svært at holde styr på ændringerne, og det er nemt at glemme at opdatere én.
- Tilstanden ryddes ikke op, så når du klikker på *Log ud*, er kontodataene stadig der, selvom du er på login-siden.
- State bliver ikke bevaret, da en browseropdatering sender dig tilbage til login-siden.
- Der er flere funktioner, der ændrer state. Efterhånden som appen vokser, kan det gøre det svært at spore ændringer, og det er nemt at glemme at opdatere en.
- State bliver ikke ryddet op, så når du klikker på *Logout*, er kontodata stadig der, selvom du er på login-siden.
Vi kunne opdatere vores kode for at tackle disse problemer ét ad gangen, men det ville skabe mere kodegentagelse og gøre appen mere kompleks og svær at vedligeholde. Eller vi kunne tage et par minutter og genoverveje vores strategi.
Vi kunne opdatere vores kode for at tackle disse problemer ét ad gangen, men det ville skabe mere kodegentagelse og gøre appen mere kompleks og svær at vedligeholde. Eller vi kunne tage et øjeblik og genoverveje vores strategi.
> Hvilke problemer prøver vi egentlig at løse her?
[Tilstandshåndtering](https://en.wikipedia.org/wiki/State_management) handler om at finde en god tilgang til at løse disse to specifikke problemer:
[State management](https://en.wikipedia.org/wiki/State_management) handler om at finde en god tilgang til at løse disse to specifikke problemer:
- Hvordan holder vi dataflows i en app forståelige?
- Hvordan holder vi tilstandsdata altid synkroniseret med brugergrænsefladen (og omvendt)?
- Hvordan holder vi state-data altid i sync med brugergrænsefladen (og omvendt)?
Når du har taget hånd om disse, kan andre problemer, du måtte have, enten allerede være løst eller være blevet lettere at løse. Der er mange mulige tilgange til at løse disse problemer, men vi vil vælge en almindelig løsning, der består i **at centralisere dataene og måderne at ændre dem på**. Dataflows ville se sådan ud:
Når du har taget hånd om disse, kan andre problemer enten allerede være løst eller være blevet lettere at løse. Der er mange mulige tilgange til at løse disse problemer, men vi vil vælge en almindelig løsning, der består i **at centralisere data og måderne at ændre dem på**. Dataflows ville se sådan ud:
![Skema, der viser dataflows mellem HTML, brugerhandlinger og tilstand](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.da.png)
![Skema, der viser dataflows mellem HTML, brugerhandlinger og state](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.da.png)
> Vi dækker ikke her den del, hvor data automatisk udløser opdatering af visningen, da det er knyttet til mere avancerede koncepter inden for [Reaktiv Programmering](https://en.wikipedia.org/wiki/Reactive_programming). Det er et godt emne at dykke ned i, hvis du er interesseret.
> Vi vil ikke dække den del, hvor data automatisk udløser opdatering af visningen, da det er knyttet til mere avancerede koncepter inden for [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming). Det er et godt emne til en dybere dykning.
✅ Der findes mange biblioteker med forskellige tilgange til tilstandshåndtering, hvor [Redux](https://redux.js.org) er en populær mulighed. Tag et kig på de koncepter og mønstre, der bruges, da det ofte er en god måde at lære om potentielle problemer, du kan stå over for i store webapps, og hvordan de kan løses.
✅ Der findes mange biblioteker med forskellige tilgange til state management, hvor [Redux](https://redux.js.org) er en populær mulighed. Tag et kig på de koncepter og mønstre, der bruges, da det ofte er en god måde at lære om potentielle problemer, du kan stå over for i store webapps, og hvordan de kan løses.
### Opgave
@ -75,11 +75,11 @@ let state = {
};
```
Ideen er at *centralisere* alle vores appdata i et enkelt tilstandsobjekt. Vi har kun `account` i tilstanden for nu, så det ændrer ikke meget, men det skaber en vej for fremtidige udvidelser.
Ideen er at *centralisere* alle vores appdata i et enkelt state-objekt. Vi har kun `account` i state lige nu, så det ændrer ikke meget, men det skaber en vej for fremtidige udvidelser.
Vi skal også opdatere de funktioner, der bruger det. I `register()`- og `login()`-funktionerne skal du erstatte `account = ...` med `state.account = ...`;
Vi skal også opdatere de funktioner, der bruger det. I funktionerne `register()` og `login()` skal du erstatte `account = ...` med `state.account = ...`;
Øverst i `updateDashboard()`-funktionen skal du tilføje denne linje:
Øverst i funktionen `updateDashboard()` skal du tilføje denne linje:
```js
const account = state.account;
@ -89,13 +89,13 @@ Denne refaktorering i sig selv har ikke bragt mange forbedringer, men ideen var
## Spor dataændringer
Nu hvor vi har etableret `state`-objektet til at gemme vores data, er det næste skridt at centralisere opdateringerne. Målet er at gøre det lettere at holde styr på eventuelle ændringer og hvornår de sker.
Nu hvor vi har oprettet `state`-objektet til at gemme vores data, er næste skridt at centralisere opdateringerne. Målet er at gøre det lettere at holde styr på eventuelle ændringer og hvornår de sker.
For at undgå, at der foretages ændringer i `state`-objektet, er det også en god praksis at betragte det som [*uforanderligt*](https://en.wikipedia.org/wiki/Immutable_object), hvilket betyder, at det slet ikke kan ændres. Det betyder også, at du skal oprette et nyt tilstandsobjekt, hvis du vil ændre noget i det. Ved at gøre dette bygger du en beskyttelse mod potentielt uønskede [sideeffekter](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) og åbner op for muligheder for nye funktioner i din app, som at implementere fortryd/gendan, samtidig med at det bliver lettere at fejlfinde. For eksempel kunne du logge hver ændring, der foretages i tilstanden, og holde en historik over ændringerne for at forstå kilden til en fejl.
For at undgå, at der foretages ændringer i `state`-objektet, er det også en god praksis at betragte det som [*immutable*](https://en.wikipedia.org/wiki/Immutable_object), hvilket betyder, at det slet ikke kan ændres. Det betyder også, at du skal oprette et nyt state-objekt, hvis du vil ændre noget i det. Ved at gøre dette bygger du en beskyttelse mod potentielt uønskede [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) og åbner op for nye funktioner i din app, som f.eks. implementering af undo/redo, samtidig med at det bliver lettere at debugge. For eksempel kunne du logge hver ændring, der foretages i state, og holde en historik over ændringerne for at forstå kilden til en fejl.
I JavaScript kan du bruge [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) til at oprette en uforanderlig version af et objekt. Hvis du forsøger at foretage ændringer i et uforanderligt objekt, vil der blive rejst en undtagelse.
I JavaScript kan du bruge [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) til at oprette en immutable version af et objekt. Hvis du forsøger at foretage ændringer i et immutable objekt, vil der blive rejst en undtagelse.
✅ Kender du forskellen mellem et *shallow* og et *deep* uforanderligt objekt? Du kan læse om det [her](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze).
✅ Kender du forskellen mellem et *shallow* og et *deep* immutable objekt? Du kan læse om det [her](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze).
### Opgave
@ -110,9 +110,9 @@ function updateState(property, newData) {
}
```
I denne funktion opretter vi et nyt tilstandsobjekt og kopierer data fra den tidligere tilstand ved hjælp af [*spread (`...`) operatoren*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Derefter overskriver vi en bestemt egenskab i tilstandsobjektet med de nye data ved hjælp af [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` til tildeling. Til sidst låser vi objektet for at forhindre ændringer ved hjælp af `Object.freeze()`. Vi har kun `account`-egenskaben gemt i tilstanden for nu, men med denne tilgang kan du tilføje så mange egenskaber, som du har brug for i tilstanden.
I denne funktion opretter vi et nyt state-objekt og kopierer data fra det tidligere state ved hjælp af [*spread (`...`) operatoren*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Derefter overskriver vi en bestemt egenskab i state-objektet med de nye data ved hjælp af [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` til tildeling. Til sidst låser vi objektet for at forhindre ændringer ved hjælp af `Object.freeze()`. Vi har kun egenskaben `account` gemt i state lige nu, men med denne tilgang kan du tilføje så mange egenskaber, som du har brug for i state.
Vi opdaterer også `state`-initialiseringen for at sikre, at den oprindelige tilstand også er låst:
Vi opdaterer også `state`-initialiseringen for at sikre, at den oprindelige state også er frosset:
```js
let state = Object.freeze({
@ -126,13 +126,13 @@ Derefter opdaterer vi `register`-funktionen ved at erstatte `state.account = res
updateState('account', result);
```
Gør det samme med `login`-funktionen, og erstat `state.account = data;` med:
Gør det samme med `login`-funktionen ved at erstatte `state.account = data;` med:
```js
updateState('account', data);
```
Vi benytter nu lejligheden til at løse problemet med, at kontodata ikke ryddes, når brugeren klikker på *Log ud*.
Vi benytter nu lejligheden til at løse problemet med, at kontodata ikke bliver ryddet, når brugeren klikker på *Logout*.
Opret en ny funktion `logout()`:
@ -147,45 +147,45 @@ I `updateDashboard()` skal du erstatte omdirigeringen `return navigate('/login')
Prøv at registrere en ny konto, logge ud og logge ind igen for at kontrollere, at alt stadig fungerer korrekt.
> Tip: Du kan se alle tilstandsændringer ved at tilføje `console.log(state)` nederst i `updateState()` og åbne konsollen i din browsers udviklingsværktøjer.
> Tip: Du kan se alle state-ændringer ved at tilføje `console.log(state)` nederst i `updateState()` og åbne konsollen i din browsers udviklingsværktøjer.
## Bevar tilstanden
## Bevar state
De fleste webapps har brug for at gemme data for at kunne fungere korrekt. Alle kritiske data gemmes normalt i en database og tilgås via et server-API, som for eksempel brugerens kontodata i vores tilfælde. Men nogle gange er det også interessant at gemme nogle data i klientappen, der kører i din browser, for at give en bedre brugeroplevelse eller forbedre indlæsningsydelsen.
De fleste webapps har brug for at bevare data for at kunne fungere korrekt. Alle kritiske data gemmes normalt i en database og tilgås via et server-API, som f.eks. brugerens kontodata i vores tilfælde. Men nogle gange kan det også være interessant at bevare nogle data i klientappen, der kører i din browser, for at give en bedre brugeroplevelse eller forbedre indlæsningshastigheden.
Når du vil gemme data i din browser, er der nogle vigtige spørgsmål, du bør stille dig selv:
Når du vil bevare data i din browser, er der nogle vigtige spørgsmål, du bør stille dig selv:
- *Er dataene følsomme?* Du bør undgå at gemme følsomme data på klienten, såsom brugeradgangskoder.
- *Er dataene følsomme?* Du bør undgå at gemme følsomme data på klienten, såsom brugerens adgangskoder.
- *Hvor længe har du brug for at gemme disse data?* Planlægger du kun at tilgå disse data under den aktuelle session, eller vil du have dem gemt for evigt?
Der er flere måder at gemme information i en webapp på, afhængigt af hvad du vil opnå. For eksempel kan du bruge URL'er til at gemme en søgeforespørgsel og gøre den delbar mellem brugere. Du kan også bruge [HTTP-cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), hvis dataene skal deles med serveren, som for eksempel [autentifikations](https://en.wikipedia.org/wiki/Authentication)-information.
Der er flere måder at gemme information i en webapp på, afhængigt af hvad du vil opnå. For eksempel kan du bruge URL'er til at gemme en søgeforespørgsel og gøre den delbar mellem brugere. Du kan også bruge [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), hvis dataene skal deles med serveren, som f.eks. [autentifikations](https://en.wikipedia.org/wiki/Authentication)-information.
En anden mulighed er at bruge en af de mange browser-API'er til at gemme data. To af dem er særligt interessante:
- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): en [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), der gør det muligt at gemme data, der er specifikke for det aktuelle websted, på tværs af forskellige sessioner. De data, der gemmes i den, udløber aldrig.
- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): denne fungerer på samme måde som `localStorage`, bortset fra at de data, der gemmes i den, slettes, når sessionen slutter (når browseren lukkes).
- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): en [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), der gør det muligt at bevare data, der er specifikke for det aktuelle websted, på tværs af forskellige sessioner. De gemte data udløber aldrig.
- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): denne fungerer på samme måde som `localStorage`, bortset fra at de gemte data ryddes, når sessionen slutter (når browseren lukkes).
Bemærk, at begge disse API'er kun tillader at gemme [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Hvis du vil gemme komplekse objekter, skal du serialisere dem til [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formatet ved hjælp af [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
✅ Hvis du vil oprette en webapp, der ikke arbejder med en server, er det også muligt at oprette en database på klienten ved hjælp af [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Denne er forbeholdt avancerede brugsscenarier eller hvis du har brug for at gemme betydelige mængder data, da den er mere kompleks at bruge.
✅ Hvis du vil oprette en webapp, der ikke arbejder med en server, er det også muligt at oprette en database på klienten ved hjælp af [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Denne er reserveret til avancerede brugsscenarier eller hvis du har brug for at gemme betydelige mængder data, da den er mere kompleks at bruge.
### Opgave
Vi ønsker, at vores brugere forbliver logget ind, indtil de eksplicit klikker på *Log ud*-knappen, så vi bruger `localStorage` til at gemme kontodata. Først definerer vi en nøgle, som vi vil bruge til at gemme vores data.
Vi vil gerne have, at vores brugere forbliver logget ind, indtil de eksplicit klikker på *Logout*-knappen, så vi bruger `localStorage` til at gemme kontodata. Først definerer vi en nøgle, som vi vil bruge til at gemme vores data.
```js
const storageKey = 'savedAccount';
```
Tilføj derefter denne linje i slutningen af `updateState()`-funktionen:
Tilføj derefter denne linje nederst i `updateState()`-funktionen:
```js
localStorage.setItem(storageKey, JSON.stringify(state.account));
```
Med dette vil brugerens kontodata blive gemt og altid være opdateret, da vi tidligere centraliserede alle vores tilstandsopdateringer. Det er her, vi begynder at drage fordel af alle vores tidligere refaktoreringer 🙂.
Med dette vil brugerens kontodata blive bevaret og altid være opdateret, da vi tidligere centraliserede alle vores state-opdateringer. Det er her, vi begynder at drage fordel af alle vores tidligere refaktoreringer 🙂.
Da dataene gemmes, skal vi også sørge for at gendanne dem, når appen indlæses. Da vi begynder at få mere initialiseringskode, kan det være en god idé at oprette en ny `init`-funktion, der også inkluderer vores tidligere kode nederst i `app.js`:
Da dataene gemmes, skal vi også tage os af at gendanne dem, når appen indlæses. Da vi begynder at have mere initialiseringskode, kan det være en god idé at oprette en ny `init`-funktion, der også inkluderer vores tidligere kode nederst i `app.js`:
```js
function init() {
@ -202,15 +202,15 @@ function init() {
init();
```
Her henter vi de gemte data, og hvis der er nogen, opdaterer vi tilstanden i overensstemmelse hermed. Det er vigtigt at gøre dette *før* opdatering af ruten, da der kan være kode, der afhænger af tilstanden under sideopdateringen.
Her henter vi de gemte data, og hvis der er nogen, opdaterer vi state tilsvarende. Det er vigtigt at gøre dette *før* opdatering af ruten, da der kan være kode, der afhænger af state under sideopdateringen.
Vi kan også gøre *Dashboard*-siden til vores applikations standardside, da vi nu gemmer kontodataene. Hvis der ikke findes data, sørger dashboardet for at omdirigere til *Login*-siden alligevel. I `updateRoute()` skal du erstatte fallbacken `return navigate('/login');` med `return navigate('/dashboard');`.
Vi kan også gøre *Dashboard*-siden til vores applikations standardside, da vi nu bevarer kontodata. Hvis der ikke findes data, sørger dashboardet for at omdirigere til *Login*-siden alligevel. I `updateRoute()` skal du erstatte fallback `return navigate('/login');` med `return navigate('/dashboard');`.
Log nu ind i appen og prøv at opdatere siden. Du bør forblive på dashboardet. Med den opdatering har vi taget hånd om alle vores oprindelige problemer...
Log nu ind i appen og prøv at opdatere siden. Du bør forblive på dashboardet. Med denne opdatering har vi taget hånd om alle vores oprindelige problemer...
## Opdater dataene
...Men vi har måske også skabt et nyt. Ups!
...Men vi har måske også skabt et nyt problem. Ups!
Gå til dashboardet ved hjælp af `test`-kontoen, og kør derefter denne kommando i en terminal for at oprette en ny transaktion:
@ -223,9 +223,9 @@ curl --request POST \
Prøv at opdatere dashboard-siden i browseren nu. Hvad sker der? Ser du den nye transaktion?
Tilstanden gemmes på ubestemt tid takket være `localStorage`, men det betyder også, at den aldrig opdateres, før du logger ud af appen og logger ind igen!
State bevares på ubestemt tid takket være `localStorage`, men det betyder også, at det aldrig opdateres, før du logger ud af appen og logger ind igen!
En mulig strategi for at løse det er at genindlæse kontodataene, hver gang dashboardet indlæses, for at undgå forældede data.
En mulig strategi for at løse dette er at genindlæse kontodataene hver gang dashboardet indlæses, for at undgå forældede data.
### Opgave
@ -247,9 +247,9 @@ async function updateAccountData() {
}
```
Denne metode tjekker, at vi i øjeblikket er logget ind, og genindlæser derefter kontodataene fra serveren.
Denne metode kontrollerer, at vi i øjeblikket er logget ind, og genindlæser derefter kontodataene fra serveren.
Opret en anden funktion kaldet `refresh`:
Opret en anden funktion ved navn `refresh`:
```js
async function refresh() {
@ -258,7 +258,7 @@ async function refresh() {
}
```
Denne opdaterer kontodataene og tager sig derefter af at opdatere HTML'en på dashboard-siden. Det er den, vi skal kalde, når dashboard-ruten indlæses. Opdater rutedefinitionen med:
Denne opdaterer kontodataene og sørger derefter for at opdatere HTML'en på dashboard-siden. Det er den, vi skal kalde, når dashboard-ruten indlæses. Opdater rutedefinitionen med:
```js
const routes = {
@ -267,28 +267,28 @@ const routes = {
};
```
Prøv at genindlæse dashboardet nu, det bør vise de opdaterede kontodata.
Prøv at genindlæse dashboardet nu, det burde vise de opdaterede kontodata.
---
## 🚀 Udfordring
Nu hvor vi genindlæser kontodataene, hver gang dashboardet indlæses, tror du så, at vi stadig har brug for at gemme *alle kontodata*?
Nu hvor vi genindlæser kontodataene hver gang dashboardet indlæses, tror du, vi stadig har brug for at bevare *alle kontodata*?
Prøv at arbejde sammen om at ændre, hvad der gemmes og indlæses fra `localStorage`, så det kun inkluderer det, der absolut er nødvendigt for, at appen fungerer.
Prøv at arbejde sammen om at ændre, hvad der gemmes og hentes fra `localStorage`, så det kun inkluderer det, der er absolut nødvendigt for, at appen fungerer.
## Quiz efter forelæsning
## Quiz efter Forelæsning
[Quiz efter forelæsning](https://ff-quizzes.netlify.app/web/quiz/48)
## Opgave
[Implementer "Tilføj transaktion"-dialog](assignment.md)
[Implementer dialogen "Tilføj transaktion"](assignment.md)
Her er et eksempel på resultatet efter at have fuldført opgaven:
Her er et eksempelresultat efter at have fuldført opgaven:
![Skærmbillede, der viser et eksempel på dialogen "Tilføj transaktion"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.da.png)
![Skærmbillede, der viser et eksempel på "Tilføj transaktion"-dialog](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.da.png)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,15 +1,15 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "7aa6e4f270d38d9cb17f2b5bd86b863d",
"translation_date": "2025-08-26T22:27:26+00:00",
"original_hash": "1ba61d96a11309a2a6ea507496dcf7e5",
"translation_date": "2025-08-29T08:20:39+00:00",
"source_file": "8-code-editor/1-using-a-code-editor/README.md",
"language_code": "da"
}
-->
# Brug af en kodeeditor
Denne lektion dækker det grundlæggende i at bruge [VSCode.dev](https://vscode.dev), en webbaseret kodeeditor, så du kan foretage ændringer i din kode og bidrage til et projekt uden at installere noget på din computer.
Denne lektion dækker det grundlæggende i at bruge [VSCode.dev](https://vscode.dev), en webbaseret kodeeditor, så du kan foretage ændringer i din kode og bidrage til et projekt uden at skulle installere noget på din computer.
## Læringsmål
@ -25,11 +25,11 @@ Før du begynder, skal du oprette en konto hos [GitHub](https://github.com). Gå
### Introduktion
En kodeeditor er et essentielt værktøj til at skrive programmer og samarbejde om eksisterende kodeprojekter. Når du forstår det grundlæggende i en editor og hvordan du udnytter dens funktioner, kan du anvende dem, når du skriver kode.
En kodeeditor er et vigtigt værktøj til at skrive programmer og samarbejde om eksisterende kodeprojekter. Når du forstår det grundlæggende i en editor og hvordan du udnytter dens funktioner, kan du anvende dem, når du skriver kode.
## Kom godt i gang med VSCode.dev
[VSCode.dev](https://vscode.dev) er en kodeeditor på nettet. Du behøver ikke installere noget for at bruge den, det er ligesom at åbne en hvilken som helst anden hjemmeside. For at komme i gang med editoren skal du åbne følgende link: [https://vscode.dev](https://vscode.dev). Hvis du ikke er logget ind på [GitHub](https://github.com/), skal du følge anvisningerne for at logge ind eller oprette en ny konto og derefter logge ind.
[VSCode.dev](https://vscode.dev) er en kodeeditor på nettet. Du behøver ikke at installere noget for at bruge den, det er lige så nemt som at åbne en hvilken som helst anden hjemmeside. For at komme i gang med editoren skal du åbne følgende link: [https://vscode.dev](https://vscode.dev). Hvis du ikke er logget ind på [GitHub](https://github.com/), skal du følge vejledningen for at logge ind eller oprette en ny konto og derefter logge ind.
Når editoren er indlæst, bør den se nogenlunde sådan ud:
@ -37,29 +37,29 @@ Når editoren er indlæst, bør den se nogenlunde sådan ud:
Der er tre hovedsektioner, fra venstre mod højre:
1. _Aktivitetsbjælken_, som inkluderer nogle ikoner, som forstørrelsesglasset 🔎, tandhjulet ⚙️ og et par andre.
1. _Aktivitetsbjælken_, som inkluderer nogle ikoner, som for eksempel forstørrelsesglasset 🔎, tandhjulet ⚙️ og et par andre.
2. Den udvidede aktivitetsbjælke, som som standard viser _Explorer_, kaldet _sidebjælken_.
3. Og til sidst kodeområdet til højre.
Klik på hvert af ikonerne for at vise en anden menu. Når du er færdig, skal du klikke på _Explorer_, så du er tilbage, hvor du startede.
Når du begynder at oprette kode eller ændre eksisterende kode, vil det ske i det største område til højre. Du vil også bruge dette område til at visualisere eksisterende kode, hvilket du vil gøre næste gang.
Når du begynder at oprette kode eller ændre eksisterende kode, sker det i det største område til højre. Du vil også bruge dette område til at visualisere eksisterende kode, hvilket du vil gøre næste gang.
## Åbn et GitHub-repository
Det første, du skal gøre, er at åbne et GitHub-repository. Der er flere måder at åbne et repository på. I denne sektion vil du se to forskellige måder, du kan åbne et repository på, så du kan begynde at arbejde med ændringer.
Det første, du skal gøre, er at åbne et GitHub-repository. Der er flere måder at åbne et repository på. I dette afsnit vil du se to forskellige måder, du kan åbne et repository på, så du kan begynde at arbejde med ændringer.
### 1. Med editoren
Brug selve editoren til at åbne et fjernrepository. Hvis du går til [VSCode.dev](https://vscode.dev), vil du se en knap med teksten _"Open Remote Repository"_:
Brug selve editoren til at åbne et eksternt repository. Hvis du går til [VSCode.dev](https://vscode.dev), vil du se en knap med teksten _"Open Remote Repository"_:
![Åbn fjernrepository](../../../../translated_images/open-remote-repository.bd9c2598b8949e7fc283cdfc8f4050c6205a7c7c6d3f78c4b135115d037d6fa2.da.png)
![Åbn eksternt repository](../../../../translated_images/open-remote-repository.bd9c2598b8949e7fc283cdfc8f4050c6205a7c7c6d3f78c4b135115d037d6fa2.da.png)
Du kan også bruge kommandopaletten. Kommandopaletten er en inputboks, hvor du kan skrive et ord, der er en del af en kommando eller handling, for at finde den rigtige kommando at udføre. Brug menuen øverst til venstre, vælg derefter _View_, og vælg _Command Palette_, eller brug følgende tastaturgenvej: Ctrl-Shift-P (på MacOS er det Command-Shift-P).
Du kan også bruge kommando-paletten. Kommando-paletten er en inputboks, hvor du kan skrive et hvilket som helst ord, der er en del af en kommando eller handling, for at finde den rigtige kommando at udføre. Brug menuen øverst til venstre, vælg derefter _View_, og vælg derefter _Command Palette_, eller brug følgende tastaturgenvej: Ctrl-Shift-P (på MacOS ville det være Command-Shift-P).
![Palette-menu](../../../../translated_images/palette-menu.4946174e07f426226afcdad707d19b8d5150e41591c751c45b5dee213affef91.da.png)
Når menuen åbnes, skal du skrive _open remote repository_ og derefter vælge den første mulighed. Flere repositories, som du er en del af eller har åbnet for nylig, vil blive vist. Du kan også bruge en fuld GitHub-URL til at vælge et. Brug følgende URL og indsæt den i boksen:
Når menuen åbnes, skal du skrive _open remote repository_ og derefter vælge den første mulighed. Flere repositories, som du er en del af, eller som du for nylig har åbnet, vil blive vist. Du kan også bruge en fuld GitHub-URL til at vælge et. Brug følgende URL og indsæt den i boksen:
```
https://github.com/microsoft/Web-Dev-For-Beginners
@ -67,9 +67,9 @@ https://github.com/microsoft/Web-Dev-For-Beginners
✅ Hvis det lykkes, vil du se alle filer for dette repository indlæst i teksteditoren.
### 2. Brug af URL'en
### 2. Brug af URL
Du kan også bruge en URL direkte til at indlæse et repository. For eksempel er den fulde URL for det aktuelle repository [https://github.com/microsoft/Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners), men du kan bytte GitHub-domænet med `VSCode.dev/github` og indlæse repositoryet direkte. Den resulterende URL ville være [https://vscode.dev/github/microsoft/Web-Dev-For-Beginners](https://vscode.dev/github/microsoft/Web-Dev-For-Beginners).
Du kan også bruge en URL direkte til at indlæse et repository. For eksempel er den fulde URL for det aktuelle repository [https://github.com/microsoft/Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners), men du kan erstatte GitHub-domænet med `VSCode.dev/github` og indlæse repositoryet direkte. Den resulterende URL ville være [https://vscode.dev/github/microsoft/Web-Dev-For-Beginners](https://vscode.dev/github/microsoft/Web-Dev-For-Beginners).
## Rediger filer
@ -77,39 +77,37 @@ Når du har åbnet repositoryet i browseren/vscode.dev, er det næste skridt at
### 1. Opret en ny fil
Du kan enten oprette en fil inde i en eksisterende mappe eller oprette den i rodkataloget/mappen. For at oprette en ny fil skal du åbne en placering/mappe, hvor du vil gemme filen, og vælge ikonet _'New file ...'_ på aktivitetsbjælken _(venstre)_, give den et navn og trykke enter.
Du kan enten oprette en fil i en eksisterende mappe eller oprette den i rodmappen. For at oprette en ny fil skal du åbne den placering/mappe, hvor du vil gemme filen, vælge ikonet _'New file ...'_ på aktivitetsbjælken _(venstre)_, give den et navn og trykke enter.
![Opret en ny fil](../../../../translated_images/create-new-file.2814e609c2af9aeb6c6fd53156c503ac91c3d538f9cac63073b2dd4a7631f183.da.png)
### 2. Rediger og gem en fil i repositoryet
Brug af vscode.dev er nyttigt, når du vil foretage hurtige opdateringer af dit projekt uden at skulle indlæse software lokalt.
For at opdatere din kode skal du klikke på 'Explorer'-ikonet, som også er placeret på aktivitetsbjælken, for at se filer og mapper i repositoryet.
Vælg en fil for at åbne den i kodeområdet, foretag dine ændringer og gem.
At bruge vscode.dev er nyttigt, når du hurtigt vil opdatere dit projekt uden at skulle indlæse nogen software lokalt. For at opdatere din kode skal du klikke på 'Explorer'-ikonet, som også findes på aktivitetsbjælken, for at se filer og mapper i repositoryet. Vælg en fil for at åbne den i kodeområdet, foretag dine ændringer og gem.
![Rediger en fil](../../../../translated_images/edit-a-file.52c0ee665ef19f08119d62d63f395dfefddc0a4deb9268d73bfe791f52c5807a.da.png)
Når du er færdig med at opdatere dit projekt, skal du vælge ikonet _`source control`_, som indeholder alle de nye ændringer, du har foretaget i dit repository.
For at se de ændringer, du har foretaget i dit projekt, skal du vælge filerne i mappen `Changes` i den udvidede aktivitetsbjælke. Dette vil åbne et 'Working Tree', hvor du visuelt kan se de ændringer, du har foretaget i filen. Rød viser en udeladelse i projektet, mens grøn angiver en tilføjelse.
For at se de ændringer, du har foretaget i dit projekt, skal du vælge filen(e) i mappen `Changes` i den udvidede aktivitetsbjælke. Dette åbner et 'Working Tree', så du visuelt kan se de ændringer, du har foretaget i filen. Rød viser en fjernelse fra projektet, mens grøn angiver en tilføjelse.
![Se ændringer](../../../../translated_images/working-tree.c58eec08e6335c79cc708c0c220c0b7fea61514bd3c7fb7471905a864aceac7c.da.png)
Hvis du er tilfreds med de ændringer, du har foretaget, skal du holde musen over mappen `Changes` og klikke på `+`-knappen for at stage ændringerne. At stage betyder simpelthen at forberede dine ændringer til at blive committet til GitHub.
Hvis du er tilfreds med de ændringer, du har foretaget, skal du holde musen over mappen `Changes` og klikke på `+`-knappen for at stage ændringerne. At stage betyder blot at forberede dine ændringer til at blive committet til GitHub.
Hvis du derimod ikke er tilfreds med nogle ændringer og vil kassere dem, skal du holde musen over mappen `Changes` og vælge ikonet `undo`.
Hvis du derimod ikke er tilfreds med nogle ændringer og ønsker at kassere dem, skal du holde musen over mappen `Changes` og vælge ikonet `undo`.
Derefter skal du skrive en `commit message` _(En beskrivelse af den ændring, du har foretaget i projektet)_, klikke på ikonet `check` for at committe og pushe dine ændringer.
Derefter skal du skrive en `commit-besked` _(En beskrivelse af den ændring, du har foretaget i projektet)_, klikke på `check-ikonet` for at committe og pushe dine ændringer.
Når du er færdig med at arbejde på dit projekt, skal du vælge ikonet `hamburger menu` øverst til venstre for at vende tilbage til repositoryet på github.com.
Når du er færdig med at arbejde på dit projekt, skal du vælge `hamburger-menuikonet` øverst til venstre for at vende tilbage til repositoryet på github.com.
![Stage & commit ændringer](../../../../8-code-editor/images/edit-vscode.dev.gif)
## Brug af udvidelser
Installation af udvidelser i VSCode giver dig mulighed for at tilføje nye funktioner og tilpasse udviklingsmiljøet i din editor for at forbedre din udviklingsworkflow. Disse udvidelser hjælper dig også med at tilføje understøttelse af flere programmeringssprog og er ofte enten generiske udvidelser eller sprog-specifikke udvidelser.
At installere udvidelser i VSCode giver dig mulighed for at tilføje nye funktioner og tilpasse udviklingsmiljøet i din editor for at forbedre din udviklingsarbejdsgang. Disse udvidelser hjælper dig også med at tilføje understøttelse af flere programmeringssprog og er ofte enten generiske udvidelser eller sprog-specifikke udvidelser.
For at gennemse listen over alle tilgængelige udvidelser skal du klikke på ikonet _`Extensions`_ på aktivitetsbjælken og begynde at skrive navnet på udvidelsen i tekstfeltet mærket _'Search Extensions in Marketplace'_.
For at gennemse listen over alle tilgængelige udvidelser skal du klikke på ikonet _`Extensions`_ på aktivitetsbjælken og begynde at skrive navnet på udvidelsen i tekstfeltet mærket _'Search Extensions in Marketplace'_.
Du vil se en liste over udvidelser, hver med **udvidelsens navn, udgiverens navn, en kort beskrivelse, antal downloads** og **en stjernebedømmelse**.
![Udvidelsesdetaljer](../../../../translated_images/extension-details.9f8f1fd4e9eb2de5069ae413119eb8ee43172776383ebe2f7cf640e11df2e106.da.png)
@ -122,13 +120,13 @@ Du kan også se alle tidligere installerede udvidelser ved at udvide mappen _`In
For at installere en udvidelse skal du skrive udvidelsens navn i søgefeltet og klikke på den for at se yderligere oplysninger om udvidelsen i kodeområdet, når den vises i den udvidede aktivitetsbjælke.
Du kan enten klikke på den _blå install-knap_ i den udvidede aktivitetsbjælke for at installere eller bruge install-knappen, der vises i kodeområdet, når du vælger udvidelsen for at indlæse yderligere oplysninger.
Du kan enten klikke på den _blå installer-knap_ i den udvidede aktivitetsbjælke for at installere eller bruge installer-knappen, der vises i kodeområdet, når du vælger udvidelsen for at indlæse yderligere oplysninger.
![Installer udvidelser](../../../../8-code-editor/images/install-extension.gif)
### 2. Tilpas udvidelser
Efter installation af udvidelsen kan du have behov for at ændre dens adfærd og tilpasse den baseret på dine præferencer. For at gøre dette skal du vælge ikonet Extensions, og denne gang vil din udvidelse vises i mappen _Installed_, klikke på _**Gear-ikonet**_ og navigere til _Extensions Setting_.
Efter installation af udvidelsen kan det være nødvendigt at ændre dens adfærd og tilpasse den baseret på dine præferencer. For at gøre dette skal du vælge ikonet Extensions, og denne gang vil din udvidelse vises i mappen _Installed_, klikke på _**Gear-ikonet**_ og navigere til _Extensions Setting_.
![Tilpas udvidelsesindstillinger](../../../../translated_images/extension-settings.21c752ae4f4cdb78a867f140ccd0680e04619d0c44bb4afb26373e54b829d934.da.png)
@ -136,7 +134,7 @@ Efter installation af udvidelsen kan du have behov for at ændre dens adfærd og
Efter installation og brug af din udvidelse tilbyder vscode.dev muligheder for at administrere din udvidelse baseret på forskellige behov. For eksempel kan du vælge at:
- **Deaktivere:** _(Du deaktiverer midlertidigt en udvidelse, når du ikke længere har brug for den, men ikke vil afinstallere den helt)_
- **Deaktivere:** _(Du kan midlertidigt deaktivere en udvidelse, når du ikke længere har brug for den, men ikke ønsker at afinstallere den helt)_
Vælg den installerede udvidelse i den udvidede aktivitetsbjælke > klik på Gear-ikonet > vælg 'Disable' eller 'Disable (Workspace)' **ELLER** Åbn udvidelsen i kodeområdet og klik på den blå Disable-knap.
@ -146,13 +144,13 @@ Efter installation og brug af din udvidelse tilbyder vscode.dev muligheder for a
## Opgave
[Opret en CV-hjemmeside ved hjælp af vscode.dev](https://github.com/microsoft/Web-Dev-For-Beginners/blob/main/8-code-editor/1-using-a-code-editor/assignment.md)
[Opret et CV-websted ved hjælp af vscode.dev](https://github.com/microsoft/Web-Dev-For-Beginners/blob/main/8-code-editor/1-using-a-code-editor/assignment.md)
## Gennemgang & Selvstudie
Læs mere om [VSCode.dev](https://code.visualstudio.com/docs/editor/vscode-web?WT.mc_id=academic-0000-alfredodeza) og nogle af dens andre funktioner.
Læs mere om [VSCode.dev](https://code.visualstudio.com/docs/editor/vscode-web?WT.mc_id=academic-0000-alfredodeza) og nogle af dets andre funktioner.
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,21 +1,21 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2fcb983b8dbadadb1bc2e97f8c12dac5",
"translation_date": "2025-08-26T22:29:41+00:00",
"original_hash": "bd3aa6d2b879c30ea496c43aec1c49ed",
"translation_date": "2025-08-29T08:21:22+00:00",
"source_file": "8-code-editor/1-using-a-code-editor/assignment.md",
"language_code": "da"
}
-->
# Opret en CV-hjemmeside ved hjælp af vscode.dev
# Opret et CV-website ved hjælp af vscode.dev
_Hvor sejt ville det ikke være, hvis en rekrutterer bad om dit CV, og du sendte dem et link?_ 😎
_Hvor fedt ville det ikke være, hvis en rekrutterer bad om dit CV, og du sendte dem et link?_ 😎
## Mål
Efter denne opgave vil du lære at:
- Oprette en hjemmeside til at fremvise dit CV
- Oprette et website til at fremvise dit CV
### Forudsætninger
@ -25,7 +25,7 @@ Efter denne opgave vil du lære at:
**Trin 1:** Opret et nyt GitHub-repository og giv det navnet `my-resume`
**Trin 2** Opret en `index.html`-fil i dit repository. Vi tilføjer mindst én fil direkte på github.com, da du ikke kan åbne et tomt repository på vscode.dev.
**Trin 2:** Opret en `index.html`-fil i dit repository. Vi tilføjer mindst én fil direkte på github.com, da du ikke kan åbne et tomt repository på vscode.dev.
Klik på linket `creating a new file`, skriv navnet `index.html`, og vælg knappen `Commit new file`.
@ -33,7 +33,7 @@ Klik på linket `creating a new file`, skriv navnet `index.html`, og vælg knapp
**Trin 3:** Åbn [VSCode.dev](https://vscode.dev) og vælg knappen `Open Remote Repository`.
Kopier URL'en til det repository, du lige har oprettet til din CV-hjemmeside, og indsæt det i inputfeltet:
Kopier URL'en til det repository, du lige har oprettet til dit CV-website, og indsæt det i inputfeltet:
_Erstat `your-username` med dit GitHub-brugernavn_
@ -41,14 +41,14 @@ _Erstat `your-username` med dit GitHub-brugernavn_
https://github.com/your-username/my-resume
```
✅ Hvis det lykkes, vil du se dit projekt og index.html-filen åbne i teksteditoren i browseren.
✅ Hvis det lykkes, vil du se dit projekt og `index.html`-filen åbne i teksteditoren i browseren.
![Opret en ny fil](../../../../translated_images/project-on-vscode.dev.e79815a9a95ee7feac72ebe5c941c91279716be37c575dbdbf2f43bea2c7d8b6.da.png)
**Trin 4:** Åbn `index.html`-filen, indsæt koden nedenfor i dit kodeområde, og gem.
**Trin 4:** Åbn `index.html`-filen, indsæt koden nedenfor i kodeområdet, og gem.
<details>
<summary><b>HTML-kode, der styrer indholdet på din CV-hjemmeside.</b></summary>
<summary><b>HTML-kode, der styrer indholdet på dit CV-website.</b></summary>
<html>
@ -143,12 +143,12 @@ https://github.com/your-username/my-resume
Tilføj dine CV-oplysninger for at erstatte _pladsholderteksten_ i HTML-koden.
**Trin 5:** Hold musen over My-Resume-mappen, klik på ikonet `New File ...`, og opret 2 nye filer i dit projekt: `style.css` og `codeswing.json`.
**Trin 5:** Hold musen over mappen `My-Resume`, klik på ikonet `New File ...`, og opret 2 nye filer i dit projekt: `style.css` og `codeswing.json`.
**Trin 6:** Åbn `style.css`-filen, indsæt koden nedenfor, og gem.
<details>
<summary><b>CSS-kode til at formatere layoutet på siden.</b></summary>
<summary><b>CSS-kode til at formatere layoutet på websitet.</b></summary>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@ -217,9 +217,9 @@ Tilføj dine CV-oplysninger for at erstatte _pladsholderteksten_ i HTML-koden.
"styles": []
}
**Trin 7:** Installer `Codeswing-udvidelsen` for at visualisere CV-hjemmesiden i kodeområdet.
**Trin 7:** Installer `Codeswing-udvidelsen` for at visualisere CV-websitet i kodeområdet.
Klik på _`Extensions`_-ikonet på aktivitetslinjen, og skriv Codeswing. Klik enten på den _blå installeringsknap_ på den udvidede aktivitetslinje for at installere eller brug installeringsknappen, der vises i kodeområdet, når du vælger udvidelsen for at indlæse yderligere oplysninger. Umiddelbart efter installationen af udvidelsen, observer ændringerne i dit projekt i kodeområdet 😃
Klik på ikonet _`Extensions`_ på aktivitetslinjen, og skriv Codeswing. Klik enten på den _blå installer-knap_ på den udvidede aktivitetslinje for at installere eller brug installer-knappen, der vises i kodeområdet, når du vælger udvidelsen for at indlæse yderligere oplysninger. Umiddelbart efter installationen af udvidelsen skal du observere ændringerne i dit projekt i kodeområdet 😃
![Installer udvidelser](../../../../8-code-editor/images/install-extension.gif)
@ -227,15 +227,15 @@ Dette er, hvad du vil se på din skærm, efter du har installeret udvidelsen.
![Codeswing-udvidelse i aktion](../../../../translated_images/after-codeswing-extension-pb.0ebddddcf73b550994947a9084e35e2836c713ae13839d49628e3c764c1cfe83.da.png)
Hvis du er tilfreds med de ændringer, du har lavet, skal du holde musen over `Changes`-mappen og klikke på `+`-knappen for at stage ændringerne.
Hvis du er tilfreds med de ændringer, du har lavet, skal du holde musen over mappen `Changes` og klikke på `+`-knappen for at stage ændringerne.
Skriv en commit-besked _(En beskrivelse af de ændringer, du har lavet i projektet)_, og commit dine ændringer ved at klikke på `check`. Når du er færdig med at arbejde på dit projekt, skal du vælge hamburger-menuikonet øverst til venstre for at vende tilbage til repository'et på GitHub.
Skriv en commit-besked _(En beskrivelse af de ændringer, du har lavet i projektet)_, og commit dine ændringer ved at klikke på `check`. Når du er færdig med at arbejde på dit projekt, skal du vælge hamburgerikonet øverst til venstre for at vende tilbage til repositoryet på GitHub.
Tillykke 🎉 Du har lige oprettet din CV-hjemmeside ved hjælp af vscode.dev i få trin.
Tillykke 🎉 Du har lige oprettet dit CV-website ved hjælp af vscode.dev i få trin.
## 🚀 Udfordring
Åbn et fjernrepository, som du har tilladelse til at foretage ændringer i, og opdater nogle filer. Prøv derefter at oprette en ny branch med dine ændringer og lave en Pull Request.
Åbn et eksternt repository, som du har tilladelse til at foretage ændringer i, og opdater nogle filer. Prøv derefter at oprette en ny gren med dine ændringer og lave en Pull Request.
## Gennemgang & Selvstudie
@ -244,4 +244,4 @@ Læs mere om [VSCode.dev](https://code.visualstudio.com/docs/editor/vscode-web?W
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -0,0 +1,389 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "cf15ff7770c5a484349383bb27d1131f",
"translation_date": "2025-08-29T09:46:31+00:00",
"source_file": "9-chat-project/README.md",
"language_code": "da"
}
-->
# Chatprojekt
Dette chatprojekt viser, hvordan man bygger en Chat Assistent ved hjælp af GitHub Models.
Her er, hvordan det færdige projekt ser ud:
<div>
<img src="./assets/screenshot.png" alt="Chat app" width="600">
</div>
Lidt kontekst: At bygge chatassistenter ved hjælp af generativ AI er en fantastisk måde at begynde at lære om AI. Det, du vil lære, er at integrere generativ AI i en webapp gennem denne lektion. Lad os komme i gang.
## Forbindelse til generativ AI
Til backend bruger vi GitHub Models. Det er en fremragende tjeneste, der giver dig mulighed for at bruge AI gratis. Gå til dens playground og hent kode, der svarer til det backend-sprog, du har valgt. Her ser det sådan ud på [GitHub Models Playground](https://github.com/marketplace/models/azure-openai/gpt-4o-mini/playground)
<div>
<img src="./assets/playground.png" alt="GitHub Models AI Playground" with="600">
</div>
Som nævnt skal du vælge fanen "Code" og din valgte runtime.
<div>
<img src="./assets/playground-choice.png" alt="playground choice" with="600">
</div>
I dette tilfælde vælger vi Python, hvilket betyder, at vi vælger denne kode:
```python
"""Run this model in Python
> pip install openai
"""
import os
from openai import OpenAI
# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
client = OpenAI(
base_url="https://models.github.ai/inference",
api_key=os.environ["GITHUB_TOKEN"],
)
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "",
},
{
"role": "user",
"content": "What is the capital of France?",
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
print(response.choices[0].message.content)
```
Lad os rydde op i denne kode, så den er genanvendelig:
```python
def call_llm(prompt: str, system_message: str):
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": system_message,
},
{
"role": "user",
"content": prompt,
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
return response.choices[0].message.content
```
Med denne funktion `call_llm` kan vi nu tage en prompt og en systemprompt, og funktionen returnerer resultatet.
### Tilpas AI Assistenten
Hvis du vil tilpasse AI-assistenten, kan du specificere, hvordan du vil have den til at opføre sig, ved at udfylde systemprompten som vist her:
```python
call_llm("Tell me about you", "You're Albert Einstein, you only know of things in the time you were alive")
```
## Eksponér det via en Web API
Fantastisk, vi har AI-delen klar. Lad os se, hvordan vi kan integrere det i en Web API. Til Web API vælger vi Flask, men enhver webframework burde fungere. Her er koden:
```python
# api.py
from flask import Flask, request, jsonify
from llm import call_llm
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # * example.com
@app.route("/", methods=["GET"])
def index():
return "Welcome to this API. Call POST /hello with 'message': 'my message' as JSON payload"
@app.route("/hello", methods=["POST"])
def hello():
# get message from request body { "message": "do this taks for me" }
data = request.get_json()
message = data.get("message", "")
response = call_llm(message, "You are a helpful assistant.")
return jsonify({
"response": response
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
```
Her opretter vi en Flask API og definerer en standardrute "/" og "/chat". Sidstnævnte er beregnet til at blive brugt af vores frontend til at sende spørgsmål til den.
For at integrere *llm.py* skal vi gøre følgende:
- Importere funktionen `call_llm`:
```python
from llm import call_llm
from flask import Flask, request
```
- Kalde den fra "/chat"-ruten:
```python
@app.route("/hello", methods=["POST"])
def hello():
# get message from request body { "message": "do this taks for me" }
data = request.get_json()
message = data.get("message", "")
response = call_llm(message, "You are a helpful assistant.")
return jsonify({
"response": response
})
```
Her parser vi den indkommende anmodning for at hente egenskaben `message` fra JSON-bodyen. Derefter kalder vi LLM med dette kald:
```python
response = call_llm(message, "You are a helpful assistant")
# return the response as JSON
return jsonify({
"response": response
})
```
Fantastisk, nu har vi gjort, hvad der er nødvendigt.
### Konfigurer Cors
Vi bør nævne, at vi opsætter noget som CORS, cross-origin resource sharing. Det betyder, at fordi vores backend og frontend vil køre på forskellige porte, skal vi tillade frontenden at kalde backend. Der er et stykke kode i *api.py*, der opsætter dette:
```python
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # * example.com
```
Lige nu er det sat op til at tillade "*", hvilket er alle oprindelser, og det er lidt usikkert. Vi bør begrænse det, når vi går i produktion.
## Kør dit projekt
Ok, så vi har *llm.py* og *api.py*. Hvordan kan vi få dette til at fungere med en backend? Der er to ting, vi skal gøre:
- Installere afhængigheder:
```sh
cd backend
python -m venv venv
source ./venv/bin/activate
pip install openai flask flask-cors openai
```
- Starte API'en:
```sh
python api.py
```
Hvis du er i Codespaces, skal du gå til Ports nederst i editoren, højreklikke på det og klikke på "Port Visibility" og vælge "Public".
### Arbejd på en frontend
Nu hvor vi har en API oppe at køre, lad os oprette en frontend til dette. En helt basal frontend, som vi vil forbedre trinvis. I en *frontend*-mappe skal du oprette følgende:
```text
backend/
frontend/
index.html
app.js
styles.css
```
Lad os starte med **index.html**:
```html
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<form>
<textarea id="messages"></textarea>
<input id="input" type="text" />
<button type="submit" id="sendBtn">Send</button>
</form>
<script src="app.js" />
</body>
</html>
```
Ovenstående er det absolut minimum, du har brug for til at understøtte et chatvindue, da det består af en textarea, hvor beskeder vil blive vist, et inputfelt til at skrive beskeder og en knap til at sende beskeden til backend. Lad os se på JavaScript i *app.js*.
**app.js**
```js
// app.js
(function(){
// 1. set up elements
const messages = document.getElementById("messages");
const form = document.getElementById("form");
const input = document.getElementById("input");
const BASE_URL = "change this";
const API_ENDPOINT = `${BASE_URL}/hello`;
// 2. create a function that talks to our backend
async function callApi(text) {
const response = await fetch(API_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text })
});
let json = await response.json();
return json.response;
}
// 3. add response to our textarea
function appendMessage(text, role) {
const el = document.createElement("div");
el.className = `message ${role}`;
el.innerHTML = text;
messages.appendChild(el);
}
// 4. listen to submit events
form.addEventListener("submit", async(e) => {
e.preventDefault();
// someone clicked the button in the form
// get input
const text = input.value.trim();
appendMessage(text, "user")
// reset it
input.value = '';
const reply = await callApi(text);
// add to messages
appendMessage(reply, "assistant");
})
})();
```
Lad os gennemgå koden sektion for sektion:
- 1) Her får vi en reference til alle vores elementer, som vi vil referere til senere i koden.
- 2) I denne sektion opretter vi en funktion, der bruger den indbyggede `fetch`-metode til at kalde vores backend.
- 3) `appendMessage` hjælper med at tilføje svar samt det, du som bruger skriver.
- 4) Her lytter vi til submit-eventet, og vi ender med at læse inputfeltet, placere brugerens besked i textarea, kalde API'en og vise svaret i textarea.
Lad os se på styling næste gang. Her kan du virkelig gå amok og få det til at se ud, som du vil, men her er nogle forslag:
**styles.css**
```
.message {
background: #222;
box-shadow: 0 0 0 10px orange;
padding: 10px:
margin: 5px;
}
.message.user {
background: blue;
}
.message.assistant {
background: grey;
}
```
Med disse tre klasser vil du style beskeder forskelligt afhængigt af, om de kommer fra assistenten eller dig som bruger. Hvis du vil have inspiration, kan du tjekke `solution/frontend/styles.css`-mappen.
### Skift Base Url
Der var én ting, vi ikke satte, og det var `BASE_URL`. Dette er ikke kendt, før din backend er startet. For at sætte det:
- Hvis du kører API'en lokalt, skal det sættes til noget som `http://localhost:5000`.
- Hvis det kører i Codespaces, skal det se ud som "[name]app.github.dev".
## Opgave
Opret din egen mappe *project* med indhold som følger:
```text
project/
frontend/
index.html
app.js
styles.css
backend/
api.py
llm.py
```
Kopier indholdet fra det, der blev instrueret ovenfor, men føl dig fri til at tilpasse det efter din smag.
## Løsning
[Løsning](./solution/README.md)
## Bonus
Prøv at ændre personligheden af AI-assistenten. Når du kalder `call_llm` i *api.py*, kan du ændre det andet argument til det, du ønsker, for eksempel:
```python
call_llm(message, "You are Captain Picard")
```
Ændr også CSS og tekst efter din smag, så lav ændringer i *index.html* og *styles.css*.
## Opsummering
Fantastisk, du har lært fra bunden, hvordan man opretter en personlig assistent ved hjælp af AI. Vi har gjort det ved hjælp af GitHub Models, en backend i Python og en frontend i HTML, CSS og JavaScript.
## Opsætning med Codespaces
- Naviger til: [Web Dev For Beginners repo](https://github.com/microsoft/Web-Dev-For-Beginners)
- Opret fra en skabelon (sørg for, at du er logget ind på GitHub) i øverste højre hjørne:
![Opret fra skabelon](../../../translated_images/template.67ad477109d29a2b04599a83c964c87fcde041256d4f04d3589cbb00c696f76c.da.png)
- Når du er i dit repo, skal du oprette en Codespace:
![Opret codespace](../../../translated_images/codespace.bcecbdf5d2747d3d17da67a78ad911c8853d68102e34748ec372cde1e9236e1d.da.png)
Dette skulle starte et miljø, du nu kan arbejde med.
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -0,0 +1,55 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "a7b7f54b13f9e6683a844d173ffdd766",
"translation_date": "2025-08-29T09:48:56+00:00",
"source_file": "9-chat-project/solution/README.md",
"language_code": "da"
}
-->
# Kør kode
## Opsætning
Opret virtuelt miljø
```sh
cd backend
python -m venv venv
source ./venv/bin/activate
```
## Installer afhængigheder
```sh
pip install openai flask flask-cors
```
## Kør API
```sh
python api.py
```
## Kør frontend
Sørg for, at du står i frontend-mappen
Find *app.js*, og ændr `BASE_URL` til URL'en for din backend
Kør det
```
npx http-server -p 8000
```
Prøv at skrive en besked i chatten, du bør se et svar (forudsat at du kører dette i en Codespace eller har opsat en adgangstoken).
## Opsæt adgangstoken (hvis du ikke kører dette i en Codespace)
Se [Opsæt PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "efa251c5fc089367f0a81c572874afca",
"translation_date": "2025-08-28T03:00:41+00:00",
"original_hash": "687c62646ad5595f1ba733edc294cdae",
"translation_date": "2025-08-29T08:04:40+00:00",
"source_file": "README.md",
"language_code": "da"
}
@ -28,69 +28,81 @@ Følg disse trin for at komme i gang med at bruge ressourcerne:
2. **Klon repositoryet**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
3. [**Deltag i Azure AI Foundry Discord og mød eksperter og andre udviklere**](https://discord.com/invite/ByRwuEEgH4)
# Webudvikling for begyndere - Et kursus
# Webudvikling for begyndere - Et kursusforløb
Lær grundlæggende webudvikling med vores 12-ugers omfattende kursus fra Microsoft Cloud Advocates. Hver af de 24 lektioner dykker ned i JavaScript, CSS og HTML gennem praktiske projekter som terrarier, browserudvidelser og rumspil. Engager dig med quizzer, diskussioner og praktiske opgaver. Forbedr dine færdigheder og optimer din viden med vores effektive projektbaserede undervisningsmetode. Start din koderejse i dag!
Lær grundprincipperne i webudvikling med vores 12-ugers omfattende kursus fra Microsoft Cloud Advocates. Hver af de 24 lektioner dækker JavaScript, CSS og HTML gennem praktiske projekter som terrarier, browserudvidelser og rumspil. Deltag i quizzer, diskussioner og praktiske opgaver. Forbedr dine færdigheder og optimer din læring med vores effektive projektbaserede undervisningsmetode. Start din koderejse i dag!
### 🌐 Understøttelse af flere sprog
#### Understøttet via GitHub Action (Automatisk og altid opdateret)
[Fransk](../fr/README.md) | [Spansk](../es/README.md) | [Tysk](../de/README.md) | [Russisk](../ru/README.md) | [Arabisk](../ar/README.md) | [Persisk (Farsi)](../fa/README.md) | [Urdu](../ur/README.md) | [Kinesisk (Forenklet)](../zh/README.md) | [Kinesisk (Traditionel, Macau)](../mo/README.md) | [Kinesisk (Traditionel, Hong Kong)](../hk/README.md) | [Kinesisk (Traditionel, Taiwan)](../tw/README.md) | [Japansk](../ja/README.md) | [Koreansk](../ko/README.md) | [Hindi](../hi/README.md) | [Bengali](../bn/README.md) | [Marathi](../mr/README.md) | [Nepalesisk](../ne/README.md) | [Punjabi (Gurmukhi)](../pa/README.md) | [Portugisisk (Portugal)](../pt/README.md) | [Portugisisk (Brasilien)](../br/README.md) | [Italiensk](../it/README.md) | [Polsk](../pl/README.md) | [Tyrkisk](../tr/README.md) | [Græsk](../el/README.md) | [Thai](../th/README.md) | [Svensk](../sv/README.md) | [Dansk](./README.md) | [Norsk](../no/README.md) | [Finsk](../fi/README.md) | [Hollandsk](../nl/README.md) | [Hebraisk](../he/README.md) | [Vietnamesisk](../vi/README.md) | [Indonesisk](../id/README.md) | [Malay](../ms/README.md) | [Tagalog (Filipino)](../tl/README.md) | [Swahili](../sw/README.md) | [Ungarsk](../hu/README.md) | [Tjekkisk](../cs/README.md) | [Slovakisk](../sk/README.md) | [Rumænsk](../ro/README.md) | [Bulgarsk](../bg/README.md) | [Serbisk (Kyrillisk)](../sr/README.md) | [Kroatisk](../hr/README.md) | [Slovensk](../sl/README.md) | [Ukrainsk](../uk/README.md) | [Burmesisk (Myanmar)](../my/README.md)
**Hvis du ønsker yderligere oversættelser, kan understøttede sprog findes [her](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
#### 🧑‍🎓 _Er du studerende?_
Besøg [**Student Hub-siden**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon), hvor du finder ressourcer for begyndere, studenterpakker og endda måder at få en gratis certifikatvoucher. Dette er siden, du vil bogmærke og tjekke fra tid til anden, da vi skifter indhold månedligt.
Besøg [**Student Hub-siden**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon), hvor du finder ressourcer for begyndere, studenterpakker og endda måder at få en gratis certifikatvoucher. Dette er siden, du bør bogmærke og tjekke regelmæssigt, da vi opdaterer indholdet månedligt.
### 📣 Meddelelse - _Nyt projekt til opbygning med Generativ AI_
### 📣 Meddelelse - _Nyt kursus_ om Generativ AI for JavaScript er netop udgivet
Nyt AI-assistentprojekt er netop tilføjet, tjek det ud [projekt](./09-chat-project/README.md)
Gå ikke glip af vores nye Generativ AI-kursus!
### 📣 Meddelelse - _Nyt kursusforløb_ om Generativ AI for JavaScript er netop udgivet
Gå ikke glip af vores nye kursusforløb om Generativ AI!
Besøg [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) for at komme i gang!
![Baggrund](../../translated_images/background.148a8d43afde57303419a663f50daf586681bc2fabf833f66ef6954073983c66.da.png)
- Lektioner, der dækker alt fra grundlæggende til RAG.
- Interager med historiske figurer ved hjælp af GenAI og vores ledsager-app.
- Sjov og engagerende fortælling, du vil rejse i tiden!
- Interager med historiske figurer ved hjælp af GenAI og vores ledsagerapp.
- Sjov og engagerende fortælling, hvor du rejser i tiden!
![karakter](../../translated_images/character.5c0dd8e067ffd693c16e2c5b7412ab075a2215ce31f998305639fa3a05e14fbe.da.png)
![Karakter](../../translated_images/character.5c0dd8e067ffd693c16e2c5b7412ab075a2215ce31f998305639fa3a05e14fbe.da.png)
Hver lektion inkluderer en opgave, en videnstest og en udfordring, der guider dig i at lære emner som:
- Prompting og prompt engineering
- Tekst- og billedapp-generering
- Søgeapps
Besøg [https://aka.ms/genai-js-course](../../[https:/aka.ms/genai-js-course) for at komme i gang!
Besøg [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) for at komme i gang!
## 🌱 Kom godt i gang
> **Lærere**, vi har [inkluderet nogle forslag](for-teachers.md) til, hvordan man bruger dette kursus. Vi vil meget gerne høre din feedback [i vores diskussionsforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
> **Lærere**, vi har [inkluderet nogle forslag](for-teachers.md) til, hvordan dette kursusforløb kan bruges. Vi vil meget gerne høre din feedback [i vores diskussionsforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
**[Studerende](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, for hver lektion, start med en quiz før lektionen og fortsæt med at læse materialet, fuldføre de forskellige aktiviteter og teste din forståelse med quizzen efter lektionen.
**[Studerende](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, for hver lektion, start med en quiz før lektionen og fortsæt med at læse undervisningsmaterialet, gennemføre de forskellige aktiviteter og teste din forståelse med quizzen efter lektionen.
For at forbedre din læringsoplevelse, forbind med dine medstuderende for at arbejde på projekterne sammen! Diskussioner opfordres i vores [diskussionsforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), hvor vores team af moderatorer vil være tilgængelige for at besvare dine spørgsmål.
For at forbedre din læringsoplevelse, forbind dig med dine medstuderende for at arbejde på projekterne sammen! Diskussioner opfordres i vores [diskussionsforum](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), hvor vores team af moderatorer vil være tilgængelige for at besvare dine spørgsmål.
For at udvide din uddannelse anbefaler vi stærkt at udforske [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) for yderligere studiematerialer.
### 📋 Opsætning af dit miljø
Dette kursus har et udviklingsmiljø klar til brug! Når du starter, kan du vælge at køre kurset i en [Codespace](https://github.com/features/codespaces/) (_et browserbaseret miljø uden behov for installationer_), eller lokalt på din computer ved hjælp af en teksteditor som [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
Dette kursusforløb har et udviklingsmiljø klar til brug! Når du starter, kan du vælge at køre kursusforløbet i en [Codespace](https://github.com/features/codespaces/) (_et browserbaseret miljø uden behov for installationer_) eller lokalt på din computer ved hjælp af en teksteditor som [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
#### Opret dit repository
For nemt at gemme dit arbejde anbefales det, at du opretter din egen kopi af dette repository. Du kan gøre dette ved at klikke på knappen **Use this template** øverst på siden. Dette vil oprette et nyt repository i din GitHub-konto med en kopi af kurset.
For nemt at gemme dit arbejde anbefales det, at du opretter din egen kopi af dette repository. Du kan gøre dette ved at klikke på knappen **Use this template** øverst på siden. Dette vil oprette et nyt repository i din GitHub-konto med en kopi af kursusforløbet.
Følg disse trin:
1. **Fork repositoryet**: Klik på "Fork"-knappen øverst til højre på denne side.
2. **Klon repositoryet**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
#### Kør kurset i en Codespace
#### Kør kursusforløbet i en Codespace
I din kopi af dette repository, som du har oprettet, klik på **Code**-knappen og vælg **Open with Codespaces**. Dette vil oprette en ny Codespace, hvor du kan arbejde.
I din kopi af dette repository, som du har oprettet, skal du klikkeknappen **Code** og vælge **Open with Codespaces**. Dette vil oprette en ny Codespace, som du kan arbejde i.
[!Codespace](../..)./images/createcodespace.png)
#### Kør kurset lokalt på din computer
#### Kør kursusforløbet lokalt på din computer
For at køre dette kursus lokalt på din computer skal du bruge en teksteditor, en browser og et kommandolinjeværktøj. Vores første lektion, [Introduktion til programmeringssprog og værktøjer](../../1-getting-started-lessons/1-intro-to-programming-languages), vil guide dig gennem forskellige muligheder for hvert af disse værktøjer, så du kan vælge det, der passer bedst til dig.
For at køre dette kursusforløb lokalt på din computer skal du bruge en teksteditor, en browser og et kommandolinjeværktøj. Vores første lektion, [Introduktion til programmeringssprog og værktøjer](../../1-getting-started-lessons/1-intro-to-programming-languages), vil guide dig gennem forskellige muligheder for hvert af disse værktøjer, så du kan vælge det, der passer bedst til dig.
Vi anbefaler at bruge [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) som din editor, som også har en indbygget [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon). Du kan downloade Visual Studio Code [her](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
1. Klon dit repository til din computer. Du kan gøre dette ved at klikke på **Code**-knappen og kopiere URL'en:
1. Klon dit repository til din computer. Du kan gøre dette ved at klikke på knappen **Code** og kopiere URL'en:
[!CodeSpace](./images/createcodespace.png)
@ -100,81 +112,81 @@ Vi anbefaler at bruge [Visual Studio Code](https://code.visualstudio.com/?WT.mc_
git clone <your-repository-url>
```
2. Åbn mappen i Visual Studio Code. Du kan gøre dette ved at klikke på **File** > **Open Folder** og vælge den mappe, du lige har klonet.
> Anbefalede Visual Studio Code-udvidelser:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - for at forhåndsvise HTML-sider i Visual Studio Code
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - for at hjælpe dig med at skrive kode hurtigere
## 📂 Hver lektion inkluderer:
- valgfri sketchnote
- valgfri supplerende video
- opvarmningsquiz før lektionen
- skriftlig lektion
- for projektbaserede lektioner, trin-for-trin vejledninger til at bygge projektet
- videnstest
- en udfordring
- supplerende læsning
- opgave
- [quiz efter lektionen](https://ff-quizzes.netlify.app/web/)
> **En note om quizzer**: Alle quizzer findes i Quiz-app-mappen, 48 quizzer i alt med tre spørgsmål hver. De er tilgængelige [her](https://ff-quizzes.netlify.app/web/), og quiz-appen kan køres lokalt eller implementeres på Azure; følg instruktionerne i `quiz-app`-mappen.
## 🗃️ Lektioner
| | Projekt Navn | Koncepter Lært | Læringsmål | Linket Lektion | Forfatter |
| :-: | :------------------------------------------------------: | :--------------------------------------------------------------------: | ----------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------: | :-----------------------: |
| 01 | Kom godt i gang | Introduktion til programmering og værktøjer | Lær de grundlæggende principper bag de fleste programmeringssprog og om software, der hjælper professionelle udviklere i deres arbejde | [Introduktion til programmeringssprog og værktøjer](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Kom godt i gang | Grundlæggende om GitHub, inklusiv teamwork | Hvordan man bruger GitHub i dit projekt, og hvordan man samarbejder med andre om en kodebase | [Introduktion til GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Kom godt i gang | Tilgængelighed | Lær det grundlæggende om webtilgængelighed | [Grundlæggende om tilgængelighed](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS Grundlæggende | JavaScript Datatyper | Det grundlæggende om JavaScript-datatyper | [Datatyper](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS Grundlæggende | Funktioner og Metoder | Lær om funktioner og metoder til at styre en applikations logikflow | [Funktioner og Metoder](./2-js-basics/2-functions-methods/README.md) | Jasmine og Christopher |
| 06 | JS Grundlæggende | Beslutningstagning med JS | Lær hvordan man skaber betingelser i din kode ved hjælp af beslutningstagning | [Beslutningstagning](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS Grundlæggende | Arrays og Loops | Arbejd med data ved hjælp af arrays og loops i JavaScript | [Arrays og Loops](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML i praksis | Byg HTML for at skabe et online terrarium med fokus på at bygge et layout | [Introduktion til HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS i praksis | Byg CSS for at style det online terrarium med fokus på det grundlæggende i CSS, inklusiv at gøre siden responsiv | [Introduktion til CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | JavaScript Closures, DOM-manipulation | Byg JavaScript-koden, der gør terrariet til en drag/drop-grænseflade, med fokus på closures og DOM-manipulation | [JavaScript Closures, DOM-manipulation](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typing Game](./4-typing-game/solution/README.md) | Byg et Typingspil | Lær at bruge tastaturbegivenheder til at styre logikken i din JavaScript-app | [Event-Driven Programming](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Arbejde med Browsere | Lær hvordan browsere fungerer, deres historie, og hvordan man opbygger de første elementer af en browserudvidelse | [About Browsers](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Bygning af en formular, kald til en API og lagring af variabler lokalt | Byg JavaScript-elementerne i din browserudvidelse til at kalde en API ved hjælp af variabler, der er gemt lokalt | [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) | Baggrundsprocesser i browseren, webperformance | Brug browserens baggrundsprocesser til at administrere udvidelsens ikon; lær om webperformance og optimeringer | [Background Tasks and Performance](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | Mere avanceret spiludvikling med JavaScript | Lær om arv ved hjælp af både klasser og komposition samt Pub/Sub-mønsteret som forberedelse til at bygge et spil | [Introduction to Advanced Game Development](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Tegning på canvas | Lær om Canvas API, som bruges til at tegne elementer på en skærm | [Drawing to Canvas](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Flytte elementer rundt på skærmen | Opdag hvordan elementer kan få bevægelse ved hjælp af kartesiske koordinater og Canvas API | [Moving Elements Around](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Kollisionsdetektion | Få elementer til at kollidere og reagere på hinanden ved hjælp af tastetryk og tilføj en cooldown-funktion for at sikre performance | [Collision Detection](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Holde styr på point | Udfør matematiske beregninger baseret på spillets status og performance | [Keeping Score](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Afslutte og genstarte spillet | Lær om at afslutte og genstarte spillet, herunder oprydning af aktiver og nulstilling af variabelværdier | [The Ending Condition](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Banking App](./7-bank-project/solution/README.md) | HTML-skabeloner og ruter i en webapp | Lær hvordan man opbygger strukturen for en fler-sidet webapps arkitektur ved hjælp af routing og HTML-skabeloner | [HTML Templates and Routes](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Banking App](./7-bank-project/solution/README.md) | Byg en login- og registreringsformular | Lær om at bygge formularer og håndtere valideringsrutiner | [Forms](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Banking App](./7-bank-project/solution/README.md) | Metoder til at hente og bruge data | Hvordan data flyder ind og ud af din app, hvordan man henter det, gemmer det og sletter det | [Data](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Banking App](./7-bank-project/solution/README.md) | Koncepter for tilstandsadministration | Lær hvordan din app bevarer tilstand og hvordan man administrerer den programmatisk | [State Management](./7-bank-project/4-state-management/README.md) | Yohan |
2. Åbn mappen i Visual Studio Code. Du kan gøre dette ved at klikke på **File**
> **Åbn mappe** og vælg den mappe, du lige har klonet.
> Anbefalede Visual Studio Code-udvidelser:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - til at forhåndsvise HTML-sider direkte i Visual Studio Code
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - til at hjælpe dig med at skrive kode hurtigere
## 📂 Hver lektion inkluderer:
- valgfri sketchnote
- valgfri supplerende video
- opvarmningsquiz før lektionen
- skriftlig lektion
- for projektbaserede lektioner, trin-for-trin vejledninger til at bygge projektet
- videnskontroller
- en udfordring
- supplerende læsning
- opgave
- [quiz efter lektionen](https://ff-quizzes.netlify.app/web/)
> **En note om quizzer**: Alle quizzer findes i Quiz-app-mappen, i alt 48 quizzer med tre spørgsmål hver. De er tilgængelige [her](https://ff-quizzes.netlify.app/web/), og quiz-appen kan køres lokalt eller implementeres på Azure; følg instruktionerne i `quiz-app`-mappen.
## 🗃️ Lektioner
| | Projektnavn | Lærte begreber | Læringsmål | Linket lektion | Forfatter |
| :-: | :------------------------------------------------------: | :--------------------------------------------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------- | :-----------------------------------------------------------------------------------------------------------------------------: | :-----------------------: |
| 01 | Kom godt i gang | Introduktion til programmering og værktøjer | Lær de grundlæggende principper bag de fleste programmeringssprog og om software, der hjælper professionelle udviklere i deres arbejde | [Introduktion til programmeringssprog og værktøjer](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Kom godt i gang | Grundlæggende om GitHub, inklusiv teamwork | Hvordan man bruger GitHub i dit projekt, og hvordan man samarbejder med andre om en kodebase | [Introduktion til GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Kom godt i gang | Tilgængelighed | Lær det grundlæggende om webtilgængelighed | [Grundlæggende tilgængelighed](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS Grundlæggende | JavaScript Datatyper | Det grundlæggende om JavaScript-datatyper | [Datatyper](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS Grundlæggende | Funktioner og metoder | Lær om funktioner og metoder til at styre en applikations logikflow | [Funktioner og metoder](./2-js-basics/2-functions-methods/README.md) | Jasmine og Christopher |
| 06 | JS Grundlæggende | Beslutningstagning med JS | Lær hvordan man skaber betingelser i din kode ved hjælp af beslutningstagende metoder | [Beslutningstagning](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS Grundlæggende | Arrays og loops | Arbejd med data ved hjælp af arrays og loops i JavaScript | [Arrays og loops](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML i praksis | Byg HTML for at skabe et online terrarium med fokus på at bygge et layout | [Introduktion til HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS i praksis | Byg CSS for at style det online terrarium med fokus på det grundlæggende i CSS, inklusiv at gøre siden responsiv | [Introduktion til CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | JavaScript Closures, DOM-manipulation | Byg JavaScript for at få terrariet til at fungere som en drag/drop-grænseflade med fokus på closures og DOM-manipulation | [JavaScript Closures, DOM-manipulation](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typing Game](./4-typing-game/solution/README.md) | Byg et skrive-spil | Lær hvordan man bruger tastaturbegivenheder til at styre logikken i din JavaScript-app | [Event-drevet programmering](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Arbejde med browsere | Lær hvordan browsere fungerer, deres historie, og hvordan man opbygger de første elementer i en browserudvidelse | [Om browsere](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Bygge en formular, kalde en API og gemme variabler i lokal storage | Byg JavaScript-elementerne i din browserudvidelse for at kalde en API ved hjælp af variabler gemt i lokal storage | [APIs, formularer og lokal storage](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Baggrundsprocesser i browseren, webperformance | Brug browserens baggrundsprocesser til at administrere udvidelsens ikon; lær om webperformance og nogle optimeringer | [Baggrundsopgaver og performance](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | Mere avanceret spiludvikling med JavaScript | Lær om arv ved hjælp af både klasser og komposition samt Pub/Sub-mønsteret som forberedelse til at bygge et spil | [Introduktion til avanceret spiludvikling](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Tegning på canvas | Lær om Canvas API, som bruges til at tegne elementer på en skærm | [Tegning på canvas](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Flytte elementer rundt på skærmen | Opdag hvordan elementer kan få bevægelse ved hjælp af kartesiske koordinater og Canvas API | [Flytte elementer rundt](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Kollisionsdetektion | Få elementer til at kollidere og reagere på hinanden ved hjælp af tastetryk og tilføj en cooldown-funktion for at sikre performance | [Kollisionsdetektion](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Holde styr på point | Udfør matematiske beregninger baseret på spillets status og performance | [Holde styr på point](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Afslutte og genstarte spillet | Lær om at afslutte og genstarte spillet, inklusiv oprydning af aktiver og nulstilling af variabelværdier | [Afslutningsbetingelse](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Banking App](./7-bank-project/solution/README.md) | HTML-skabeloner og ruter i en webapp | Lær hvordan man opbygger strukturen af en multipages hjemmesidearkitektur ved hjælp af routing og HTML-skabeloner | [HTML-skabeloner og ruter](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Banking App](./7-bank-project/solution/README.md) | Bygge en login- og registreringsformular | Lær om at bygge formularer og håndtere valideringsrutiner | [Formularer](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Banking App](./7-bank-project/solution/README.md) | Metoder til at hente og bruge data | Hvordan data flyder ind og ud af din app, hvordan man henter det, gemmer det og bortskaffer det | [Data](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Banking App](./7-bank-project/solution/README.md) | Begreber om tilstandsadministration | Lær hvordan din app bevarer tilstand og hvordan man administrerer det programmatisk | [Tilstandsadministration](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Browser/VScode Code](../../8-code-editor) | Arbejde med VScode | Lær hvordan man bruger en kodeeditor | [Brug VScode Code Editor](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Assistants](./9-chat-project/README.md) | Arbejde med AI | Lær hvordan man bygger sin egen AI-assistent | [AI-assistentprojekt](./9-chat-project/README.md) | Chris |
## 🏫 Pædagogik
Vores pensum er designet med to centrale pædagogiske principper:
Vores pensum er designet med to centrale pædagogiske principper i tankerne:
* projektbaseret læring
* hyppige quizzer
Programmet underviser i grundlæggende JavaScript, HTML og CSS samt de nyeste værktøjer og teknikker, som moderne webudviklere bruger. Studerende får mulighed for at opbygge praktisk erfaring ved at udvikle et typingspil, et virtuelt terrarium, en miljøvenlig browserudvidelse, et space-invader-lignende spil og en bankapp til virksomheder. Ved afslutningen af serien vil de studerende have opnået en solid forståelse af webudvikling.
Programmet underviser i grundlæggende JavaScript, HTML og CSS samt de nyeste værktøjer og teknikker, som moderne webudviklere bruger. Studerende får mulighed for at opbygge praktisk erfaring ved at bygge et skrive-spil, et virtuelt terrarium, en miljøvenlig browserudvidelse, et space-invader-lignende spil og en bankapp til virksomheder. Ved slutningen af serien vil de studerende have opnået en solid forståelse af webudvikling.
> 🎓 Du kan tage de første par lektioner i dette pensum som en [Learn Path](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) på Microsoft Learn!
Ved at sikre, at indholdet er projektorienteret, bliver processen mere engagerende for de studerende, og konceptforståelsen vil blive styrket. Vi har også skrevet flere introduktionslektioner i JavaScript-grundlæggende for at introducere begreber, ledsaget af en video fra "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)"-samlingen af videotutorials, hvor nogle af forfatterne har bidraget til dette pensum.
Ved at sikre, at indholdet er knyttet til projekter, bliver processen mere engagerende for de studerende, og fastholdelsen af begreber vil blive forbedret. Vi har også skrevet flere introduktionslektioner i JavaScript-grundlæggende for at introducere begreber, parret med en video fra "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)"-samlingen af videotutorials, hvor nogle af forfatterne har bidraget til dette pensum.
Derudover sætter en lav-stress quiz før en klasse fokus på emnet for de studerende, mens en anden quiz efter klassen sikrer yderligere fastholdelse. Dette pensum er designet til at være fleksibelt og sjovt og kan tages helt eller delvist. Projekterne starter små og bliver gradvist mere komplekse i løbet af den 12-ugers cyklus.
Derudover sætter en lav-stress quiz før en klasse intentionen hos den studerende mod at lære et emne, mens en anden quiz efter klassen sikrer yderligere fastholdelse. Dette pensum er designet til at være fleksibelt og sjovt og kan tages helt eller delvist. Projekterne starter små og bliver gradvist mere komplekse ved slutningen af den 12-ugers cyklus.
Selvom vi bevidst har undgået at introducere JavaScript-frameworks for at koncentrere os om de grundlæggende færdigheder, der er nødvendige som webudvikler, før man adopterer et framework, ville et godt næste skridt efter at have gennemført dette pensum være at lære om Node.js via en anden samling af videoer: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
Mens vi bevidst har undgået at introducere JavaScript-frameworks for at koncentrere os om de grundlæggende færdigheder, der er nødvendige som webudvikler, før man adopterer et framework, ville et godt næste skridt efter at have gennemført dette pensum være at lære om Node.js via en anden samling af videoer: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
> Besøg vores [Code of Conduct](CODE_OF_CONDUCT.md) og [Contributing](CONTRIBUTING.md)-retningslinjer. Vi modtager gerne din konstruktive feedback!
> Besøg vores [Code of Conduct](CODE_OF_CONDUCT.md) og [Contributing](CONTRIBUTING.md) retningslinjer. Vi værdsætter din konstruktive feedback!
## 🧭 Offline adgang
Du kan køre denne dokumentation offline ved at bruge [Docsify](https://docsify.js.org/#/). Fork denne repo, [installer Docsify](https://docsify.js.org/#/quickstart) på din lokale maskine, og skriv derefter `docsify serve` i rodmappen af denne repo. Websitet vil blive serveret på port 3000 på din localhost: `localhost:3000`.
Du kan køre denne dokumentation offline ved hjælp af [Docsify](https://docsify.js.org/#/). Fork denne repo, [installer Docsify](https://docsify.js.org/#/quickstart) på din lokale maskine, og skriv derefter `docsify serve` i rodmappen af denne repo. Hjemmesiden vil blive serveret på port 3000 på din localhost: `localhost:3000`.
## 📘 PDF
@ -185,26 +197,26 @@ En PDF af alle lektionerne kan findes [her](https://microsoft.github.io/Web-Dev-
Vores team producerer andre kurser! Tjek:
- [Generative AI for Beginners](https://aka.ms/genai-beginners)
- [Generative AI for Beginners .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet)
- [Generative AI with JavaScript](https://github.com/microsoft/generative-ai-with-javascript)
- [Generative AI with Java](https://github.com/microsoft/Generative-AI-for-beginners-java)
- [AI for Beginners](https://aka.ms/ai-beginners)
- [Data Science for Beginners](https://aka.ms/datascience-beginners)
- [ML for Beginners](https://aka.ms/ml-beginners)
- [Cybersecurity for Beginners](https://github.com/microsoft/Security-101)
- [Web Dev for Beginners](https://aka.ms/webdev-beginners)
- [IoT for Beginners](https://aka.ms/iot-beginners)
- [XR Development for Beginners](https://github.com/microsoft/xr-development-for-beginners)
- [Mastering GitHub Copilot for Agentic use](https://github.com/microsoft/Mastering-GitHub-Copilot-for-Paired-Programming)
- [Mastering GitHub Copilot for C#/.NET Developers](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
- [Choose Your Own Copilot Adventure](https://github.com/microsoft/CopilotAdventures)
## Licens
Dette repository er licenseret under MIT-licensen. Se [LICENSE](../../LICENSE)-filen for mere information.
- [Generativ AI for begyndere](https://aka.ms/genai-beginners)
- [Generativ AI for begyndere .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet)
- [Generativ AI med JavaScript](https://github.com/microsoft/generative-ai-with-javascript)
- [Generativ AI med Java](https://github.com/microsoft/Generative-AI-for-beginners-java)
- [AI for begyndere](https://aka.ms/ai-beginners)
- [Data Science for begyndere](https://aka.ms/datascience-beginners)
- [ML for begyndere](https://aka.ms/ml-beginners)
- [Cybersikkerhed for begyndere](https://github.com/microsoft/Security-101)
- [Webudvikling for begyndere](https://aka.ms/webdev-beginners)
- [IoT for begyndere](https://aka.ms/iot-beginners)
- [XR-udvikling for begyndere](https://github.com/microsoft/xr-development-for-beginners)
- [Mestre GitHub Copilot til agentisk brug](https://github.com/microsoft/Mastering-GitHub-Copilot-for-Paired-Programming)
- [Mestre GitHub Copilot for C#/.NET-udviklere](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
- [Vælg dit eget Copilot-eventyr](https://github.com/microsoft/CopilotAdventures)
## Licens
Dette repository er licenseret under MIT-licensen. Se [LICENSE](../../LICENSE)-filen for mere information.
---
**Ansvarsfraskrivelse**:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi er ikke ansvarlige for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os intet ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse.

@ -1,50 +1,50 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "c63675cfaf1d223b37bb9fecbfe7c252",
"translation_date": "2025-08-26T22:21:46+00:00",
"original_hash": "2dcbb9259dee4f20a4f08d9a1aa2bd4c",
"translation_date": "2025-08-29T07:20:58+00:00",
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md",
"language_code": "el"
}
-->
# Εισαγωγή στις Γλώσσες Προγραμματισμού και τα Εργαλεία του Επαγγέλματος
# Εισαγωγή στις Γλώσσες Προγραμματισμού και Εργαλεία του Επαγγέλματος
Αυτό το μάθημα καλύπτει τις βασικές αρχές των γλωσσών προγραμματισμού. Τα θέματα που καλύπτονται εδώ ισχύουν για τις περισσότερες σύγχρονες γλώσσες προγραμματισμού. Στην ενότητα "Εργαλεία του Επαγγέλματος", θα μάθετε για χρήσιμο λογισμικό που σας βοηθά ως προγραμματιστή.
Αυτό το μάθημα καλύπτει τα βασικά των γλωσσών προγραμματισμού. Τα θέματα που καλύπτονται εδώ ισχύουν για τις περισσότερες σύγχρονες γλώσσες προγραμματισμού σήμερα. Στην ενότητα "Εργαλεία του Επαγγέλματος", θα μάθετε για χρήσιμο λογισμικό που σας βοηθά ως προγραμματιστή.
![Εισαγωγή στον Προγραμματισμό](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff0b27dcbf1c3f16c8ed46984866f2d29988929678b0058fde.el.png)
> Σκίτσο από την [Tomomi Imura](https://twitter.com/girlie_mac)
![Intro Programming](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff0b27dcbf1c3f16c8ed46984866f2d29988929678b0058fde.el.png)
> Σημειώσεις από [Tomomi Imura](https://twitter.com/girlie_mac)
## Ερωτηματολόγιο Πριν το Μάθημα
[Ερωτηματολόγιο Πριν το Μάθημα](https://forms.office.com/r/dru4TE0U9n?origin=lprLink)
## Ερωτηματολόγιο πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://forms.office.com/r/dru4TE0U9n?origin=lprLink)
## Εισαγωγή
Σε αυτό το μάθημα, θα καλύψουμε:
- Τι είναι ο προγραμματισμός;
- Τύποι γλωσσών προγραμματισμού
- Βασικά στοιχεία ενός προγράμματος
- Χρήσιμο λογισμικό και εργαλεία για τον επαγγελματία προγραμματιστή
- Τι είναι ο προγραμματισμός;
- Τύποι γλωσσών προγραμματισμού
- Βασικά στοιχεία ενός προγράμματος
- Χρήσιμο λογισμικό και εργαλεία για τον επαγγελματία προγραμματιστή
> Μπορείτε να παρακολουθήσετε αυτό το μάθημα στο [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/introduction-programming/?WT.mc_id=academic-77807-sagibbon)!
## Τι είναι ο Προγραμματισμός;
Ο προγραμματισμός (γνωστός και ως κωδικοποίηση) είναι η διαδικασία συγγραφής οδηγιών για μια συσκευή, όπως ένας υπολογιστής ή μια κινητή συσκευή. Γράφουμε αυτές τις οδηγίες με μια γλώσσα προγραμματισμού, η οποία στη συνέχεια ερμηνεύεται από τη συσκευή. Αυτά τα σύνολα οδηγιών μπορεί να αναφέρονται με διάφορα ονόματα, όπως *πρόγραμμα*, *υπολογιστικό πρόγραμμα*, *εφαρμογή (app)* και *εκτελέσιμο αρχείο*.
Ο προγραμματισμός (γνωστός και ως κωδικοποίηση) είναι η διαδικασία γραφής οδηγιών για μια συσκευή, όπως ένας υπολογιστής ή μια κινητή συσκευή. Γράφουμε αυτές τις οδηγίες με μια γλώσσα προγραμματισμού, η οποία στη συνέχεια ερμηνεύεται από τη συσκευή. Αυτά τα σύνολα οδηγιών μπορεί να αναφέρονται με διάφορα ονόματα, όπως *πρόγραμμα*, *πρόγραμμα υπολογιστή*, *εφαρμογή (app)* και *εκτελέσιμο*.
Ένα *πρόγραμμα* μπορεί να είναι οτιδήποτε έχει γραφτεί με κώδικα: ιστοσελίδες, παιχνίδια και εφαρμογές κινητών είναι προγράμματα. Αν και είναι δυνατό να δημιουργηθεί ένα πρόγραμμα χωρίς να γραφτεί κώδικας, η υποκείμενη λογική ερμηνεύεται από τη συσκευή και αυτή η λογική πιθανότατα έχει γραφτεί με κώδικα. Ένα πρόγραμμα που *τρέχει* ή *εκτελεί* κώδικα εκτελεί οδηγίες. Η συσκευή με την οποία διαβάζετε αυτό το μάθημα τρέχει ένα πρόγραμμα για να το εμφανίσει στην οθόνη σας.
Ένα *πρόγραμμα* μπορεί να είναι οτιδήποτε έχει γραφτεί με κώδικα: ιστοσελίδες, παιχνίδια και εφαρμογές κινητών είναι προγράμματα. Παρόλο που είναι δυνατό να δημιουργηθεί ένα πρόγραμμα χωρίς να γραφτεί κώδικας, η υποκείμενη λογική ερμηνεύεται από τη συσκευή και αυτή η λογική πιθανότατα έχει γραφτεί με κώδικα. Ένα πρόγραμμα που *τρέχει* ή *εκτελεί* κώδικα εκτελεί οδηγίες. Η συσκευή που χρησιμοποιείτε για να διαβάσετε αυτό το μάθημα τρέχει ένα πρόγραμμα για να το εμφανίσει στην οθόνη σας.
✅ Κάντε λίγη έρευνα: Ποιος θεωρείται ότι ήταν ο πρώτος προγραμματιστής υπολογιστών στον κόσμο;
✅ Κάντε λίγη έρευνα: ποιος θεωρείται ότι ήταν ο πρώτος προγραμματιστής υπολογιστών στον κόσμο;
## Γλώσσες Προγραμματισμού
Οι γλώσσες προγραμματισμού επιτρέπουν στους προγραμματιστές να γράφουν οδηγίες για μια συσκευή. Οι συσκευές μπορούν να κατανοήσουν μόνο δυαδικό κώδικα (1 και 0), και για *τους περισσότερους* προγραμματιστές αυτός δεν είναι ένας αποδοτικός τρόπος επικοινωνίας. Οι γλώσσες προγραμματισμού είναι το μέσο επικοινωνίας μεταξύ ανθρώπων και υπολογιστών.
Οι γλώσσες προγραμματισμού επιτρέπουν στους προγραμματιστές να γράφουν οδηγίες για μια συσκευή. Οι συσκευές μπορούν να κατανοήσουν μόνο δυαδικό (1s και 0s), και για *τους περισσότερους* προγραμματιστές αυτός δεν είναι ένας πολύ αποτελεσματικός τρόπος επικοινωνίας. Οι γλώσσες προγραμματισμού είναι το μέσο επικοινωνίας μεταξύ ανθρώπων και υπολογιστών.
Οι γλώσσες προγραμματισμού έχουν διαφορετικές μορφές και μπορεί να εξυπηρετούν διαφορετικούς σκοπούς. Για παράδειγμα, η JavaScript χρησιμοποιείται κυρίως για εφαρμογές ιστού, ενώ η Bash χρησιμοποιείται κυρίως για λειτουργικά συστήματα.
*Γλώσσες χαμηλού επιπέδου* συνήθως απαιτούν λιγότερα βήματα για να ερμηνεύσει μια συσκευή τις οδηγίες σε σύγκριση με *γλώσσες υψηλού επιπέδου*. Ωστόσο, αυτό που κάνει τις γλώσσες υψηλού επιπέδου δημοφιλείς είναι η αναγνωσιμότητα και η υποστήριξή τους. Η JavaScript θεωρείται γλώσσα υψηλού επιπέδου.
*Γλώσσες χαμηλού επιπέδου* συνήθως απαιτούν λιγότερα βήματα από *γλώσσες υψηλού επιπέδου* για να ερμηνεύσει μια συσκευή τις οδηγίες. Ωστόσο, αυτό που κάνει τις γλώσσες υψηλού επιπέδου δημοφιλείς είναι η αναγνωσιμότητα και η υποστήριξή τους. Η JavaScript θεωρείται γλώσσα υψηλού επιπέδου.
Ο παρακάτω κώδικας δείχνει τη διαφορά μεταξύ μιας γλώσσας υψηλού επιπέδου (JavaScript) και μιας γλώσσας χαμηλού επιπέδου (ARM assembly code).
Ο παρακάτω κώδικας δείχνει τη διαφορά μεταξύ μιας γλώσσας υψηλού επιπέδου με JavaScript και μιας γλώσσας χαμηλού επιπέδου με κώδικα ARM assembly.
```javascript
let number = 10
@ -89,64 +89,65 @@ back add r0,r1
## Στοιχεία ενός Προγράμματος
Μια μεμονωμένη οδηγία σε ένα πρόγραμμα ονομάζεται *δήλωση* και συνήθως έχει έναν χαρακτήρα ή διάστημα γραμμής που υποδεικνύει πού τελειώνει ή *τερματίζει*. Ο τρόπος τερματισμού ενός προγράμματος διαφέρει ανάλογα με τη γλώσσα.
Μια μεμονωμένη οδηγία σε ένα πρόγραμμα ονομάζεται *δήλωση* και συνήθως έχει έναν χαρακτήρα ή διάστημα γραμμής που υποδεικνύει πού τελειώνει ή *τερματίζει* η οδηγία. Ο τρόπος τερματισμού ενός προγράμματος διαφέρει ανάλογα με τη γλώσσα.
Οι δηλώσεις μέσα σε ένα πρόγραμμα μπορεί να βασίζονται σε δεδομένα που παρέχονται από έναν χρήστη ή από αλλού για να εκτελέσουν οδηγίες. Τα δεδομένα μπορούν να αλλάξουν τη συμπεριφορά ενός προγράμματος, γι' αυτό οι γλώσσες προγραμματισμού διαθέτουν έναν τρόπο προσωρινής αποθήκευσης δεδομένων για μελλοντική χρήση. Αυτά ονομάζονται *μεταβλητές*. Οι μεταβλητές είναι δηλώσεις που δίνουν εντολή σε μια συσκευή να αποθηκεύσει δεδομένα στη μνήμη της. Οι μεταβλητές στα προγράμματα είναι παρόμοιες με τις μεταβλητές στα μαθηματικά, όπου έχουν ένα μοναδικό όνομα και η τιμή τους μπορεί να αλλάξει με την πάροδο του χρόνου.
Οι δηλώσεις μέσα σε ένα πρόγραμμα μπορεί να βασίζονται σε δεδομένα που παρέχονται από έναν χρήστη ή από αλλού για να εκτελέσουν οδηγίες. Τα δεδομένα μπορούν να αλλάξουν τον τρόπο που συμπεριφέρεται ένα πρόγραμμα, γι' αυτό οι γλώσσες προγραμματισμού διαθέτουν έναν τρόπο προσωρινής αποθήκευσης δεδομένων ώστε να μπορούν να χρησιμοποιηθούν αργότερα. Αυτά ονομάζονται *μεταβλητές*. Οι μεταβλητές είναι δηλώσεις που δίνουν οδηγίες σε μια συσκευή να αποθηκεύσει δεδομένα στη μνήμη της. Οι μεταβλητές στα προγράμματα είναι παρόμοιες με τις μεταβλητές στην άλγεβρα, όπου έχουν ένα μοναδικό όνομα και η τιμή τους μπορεί να αλλάξει με την πάροδο του χρόνου.
Υπάρχει πιθανότητα ορισμένες δηλώσεις να μην εκτελεστούν από μια συσκευή. Αυτό συνήθως συμβαίνει σκόπιμα από τον προγραμματιστή ή κατά λάθος όταν προκύψει ένα απρόσμενο σφάλμα. Αυτός ο τύπος ελέγχου σε μια εφαρμογή την καθιστά πιο ανθεκτική και ευκολότερη στη συντήρηση. Συνήθως, αυτές οι αλλαγές στον έλεγχο συμβαίνουν όταν πληρούνται ορισμένες συνθήκες. Μια κοινή δήλωση που χρησιμοποιείται στον σύγχρονο προγραμματισμό για τον έλεγχο της εκτέλεσης ενός προγράμματος είναι η δήλωση `if..else`.
Υπάρχει πιθανότητα κάποιες δηλώσεις να μην εκτελεστούν από μια συσκευή. Αυτό συνήθως γίνεται σκόπιμα όταν γράφεται από τον προγραμματιστή ή κατά λάθος όταν προκύπτει ένα απρόσμενο σφάλμα. Αυτός ο τύπος ελέγχου πάνω σε μια εφαρμογή την καθιστά πιο ανθεκτική και ευκολότερη στη συντήρηση. Συνήθως, αυτές οι αλλαγές στον έλεγχο συμβαίνουν όταν πληρούνται ορισμένες συνθήκες. Μια κοινή δήλωση που χρησιμοποιείται στον σύγχρονο προγραμματισμό για τον έλεγχο του τρόπου λειτουργίας ενός προγράμματος είναι η δήλωση `if..else`.
✅ Θα μάθετε περισσότερα για αυτόν τον τύπο δήλωσης σε επόμενα μαθήματα.
## Εργαλεία του Επαγγέλματος
[![Εργαλεία του Επαγγέλματος](https://img.youtube.com/vi/69WJeXGBdxg/0.jpg)](https://youtube.com/watch?v=69WJeXGBdxg "Εργαλεία του Επαγγέλματος")
[![Tools of the Trade](https://img.youtube.com/vi/69WJeXGBdxg/0.jpg)](https://youtube.com/watch?v=69WJeXGBdxg "Tools of the Trade")
> 🎥 Κάντε κλικ στην παραπάνω εικόνα για ένα βίντεο σχετικά με τα εργαλεία
> 🎥 Κάντε κλικ στην εικόνα παραπάνω για ένα βίντεο σχετικά με τα εργαλεία
Σε αυτή την ενότητα, θα μάθετε για κάποιο λογισμικό που μπορεί να σας φανεί πολύ χρήσιμο καθώς ξεκινάτε το επαγγελματικό σας ταξίδι στον προγραμματισμό.
Σε αυτή την ενότητα, θα μάθετε για κάποιο λογισμικό που μπορεί να βρείτε πολύ χρήσιμο καθώς ξεκινάτε το επαγγελματικό σας ταξίδι στον προγραμματισμό.
Ένα **περιβάλλον ανάπτυξης** είναι ένα μοναδικό σύνολο εργαλείων και χαρακτηριστικών που χρησιμοποιεί συχνά ένας προγραμματιστής κατά τη συγγραφή λογισμικού. Μερικά από αυτά τα εργαλεία έχουν προσαρμοστεί για τις συγκεκριμένες ανάγκες ενός προγραμματιστή και μπορεί να αλλάξουν με την πάροδο του χρόνου αν ο προγραμματιστής αλλάξει προτεραιότητες στη δουλειά, στα προσωπικά του έργα ή όταν χρησιμοποιεί διαφορετική γλώσσα προγραμματισμού. Τα περιβάλλοντα ανάπτυξης είναι τόσο μοναδικά όσο και οι προγραμματιστές που τα χρησιμοποιούν.
Ένα **περιβάλλον ανάπτυξης** είναι ένα μοναδικό σύνολο εργαλείων και χαρακτηριστικών που χρησιμοποιεί συχνά ένας προγραμματιστής κατά τη συγγραφή λογισμικού. Ορισμένα από αυτά τα εργαλεία έχουν προσαρμοστεί για τις συγκεκριμένες ανάγκες ενός προγραμματιστή και μπορεί να αλλάξουν με την πάροδο του χρόνου αν ο προγραμματιστής αλλάξει προτεραιότητες στη δουλειά, στα προσωπικά του έργα ή όταν χρησιμοποιεί διαφορετική γλώσσα προγραμματισμού. Τα περιβάλλοντα ανάπτυξης είναι τόσο μοναδικά όσο και οι προγραμματιστές που τα χρησιμοποιούν.
### Επεξεργαστές Κώδικα
Ένα από τα πιο κρίσιμα εργαλεία για την ανάπτυξη λογισμικού είναι ο επεξεργαστής κώδικα. Οι επεξεργαστές είναι το μέρος όπου γράφετε τον κώδικά σας και μερικές φορές όπου τον εκτελείτε.
Ένα από τα πιο κρίσιμα εργαλεία για την ανάπτυξη λογισμικού είναι ο επεξεργαστής κώδικα. Οι επεξεργαστές είναι το μέρος όπου γράφετε τον κώδικά σας και μερικές φορές όπου εκτελείτε τον κώδικά σας.
Οι προγραμματιστές βασίζονται στους επεξεργαστές για μερικούς επιπλέον λόγους:
- Το *Debugging* βοηθά στον εντοπισμό σφαλμάτων και λαθών, εξετάζοντας τον κώδικα γραμμή προς γραμμή. Μερικοί επεξεργαστές διαθέτουν δυνατότητες debugging, οι οποίες μπορούν να προσαρμοστούν και να προστεθούν για συγκεκριμένες γλώσσες προγραμματισμού.
- Η *επισήμανση σύνταξης* προσθέτει χρώματα και μορφοποίηση κειμένου στον κώδικα, καθιστώντας τον πιο ευανάγνωστο. Οι περισσότεροι επεξεργαστές επιτρέπουν προσαρμοσμένη επισήμανση σύνταξης.
- Οι *επεκτάσεις και οι ενσωματώσεις* είναι εξειδικευμένα εργαλεία για προγραμματιστές, φτιαγμένα από προγραμματιστές. Αυτά τα εργαλεία δεν περιλαμβάνονται στον βασικό επεξεργαστή. Για παράδειγμα, πολλοί προγραμματιστές τεκμηριώνουν τον κώδικά τους για να εξηγήσουν πώς λειτουργεί. Μπορεί να εγκαταστήσουν μια επέκταση ορθογραφικού ελέγχου για να εντοπίσουν τυπογραφικά λάθη μέσα στην τεκμηρίωση. Οι περισσότερες επεκτάσεις προορίζονται για χρήση σε έναν συγκεκριμένο επεξεργαστή και οι περισσότεροι επεξεργαστές διαθέτουν έναν τρόπο αναζήτησης διαθέσιμων επεκτάσεων.
- Η ροσαρμογή* επιτρέπει στους προγραμματιστές να δημιουργήσουν ένα μοναδικό περιβάλλον ανάπτυξης που να ταιριάζει στις ανάγκες τους. Οι περισσότεροι επεξεργαστές είναι εξαιρετικά προσαρμόσιμοι και μπορεί επίσης να επιτρέπουν στους προγραμματιστές να δημιουργούν προσαρμοσμένες επεκτάσεις.
- *Εντοπισμός σφαλμάτων* βοηθά στην αποκάλυψη σφαλμάτων και λαθών περνώντας τον κώδικα γραμμή προς γραμμή. Ορισμένοι επεξεργαστές διαθέτουν δυνατότητες εντοπισμού σφαλμάτων που μπορούν να προσαρμοστούν και να προστεθούν για συγκεκριμένες γλώσσες προγραμματισμού.
- *Χρωματική επισήμανση σύνταξης* προσθέτει χρώματα και μορφοποίηση κειμένου στον κώδικα, καθιστώντας τον ευκολότερο στην ανάγνωση. Οι περισσότεροι επεξεργαστές επιτρέπουν προσαρμοσμένη χρωματική επισήμανση σύνταξης.
- *Επεκτάσεις και Ενσωματώσεις* είναι εξειδικευμένα εργαλεία για προγραμματιστές, από προγραμματιστές. Αυτά τα εργαλεία δεν περιλαμβάνονταν στον βασικό επεξεργαστή. Για παράδειγμα, πολλοί προγραμματιστές τεκμηριώνουν τον κώδικά τους για να εξηγήσουν πώς λειτουργεί. Μπορεί να εγκαταστήσουν μια επέκταση ορθογραφικού ελέγχου για να εντοπίσουν τυπογραφικά λάθη μέσα στην τεκμηρίωση. Οι περισσότερες επεκτάσεις προορίζονται για χρήση μέσα σε έναν συγκεκριμένο επεξεργαστή και οι περισσότεροι επεξεργαστές διαθέτουν έναν τρόπο αναζήτησης διαθέσιμων επεκτάσεων.
- ροσαρμογή* επιτρέπει στους προγραμματιστές να δημιουργήσουν ένα μοναδικό περιβάλλον ανάπτυξης που να ταιριάζει στις ανάγκες τους. Οι περισσότεροι επεξεργαστές είναι εξαιρετικά προσαρμόσιμοι και μπορεί επίσης να επιτρέπουν στους προγραμματιστές να δημιουργούν προσαρμοσμένες επεκτάσεις.
#### Δημοφιλείς Επεξεργαστές και Επεκτάσεις για Ανάπτυξη Ιστού
- [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon)
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
- [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare)
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
- [Atom](https://atom.io/)
- [spell-check](https://atom.io/packages/spell-check)
- [teletype](https://atom.io/packages/teletype)
- [atom-beautify](https://atom.io/packages/atom-beautify)
- [Sublimetext](https://www.sublimetext.com/)
- [emmet](https://emmet.io/)
- [SublimeLinter](http://www.sublimelinter.com/en/stable/)
- [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon)
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
- [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare)
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
- [Atom](https://atom.io/)
- [spell-check](https://atom.io/packages/spell-check)
- [teletype](https://atom.io/packages/teletype)
- [atom-beautify](https://atom.io/packages/atom-beautify)
- [Sublimetext](https://www.sublimetext.com/)
- [emmet](https://emmet.io/)
- [SublimeLinter](http://www.sublimelinter.com/en/stable/)
### Περιηγητές
Ένα άλλο κρίσιμο εργαλείο είναι ο περιηγητής. Οι προγραμματιστές ιστού βασίζονται στον περιηγητή για να δουν πώς εκτελείται ο κώδικάς τους στον ιστό. Χρησιμοποιείται επίσης για την εμφάνιση των οπτικών στοιχείων μιας ιστοσελίδας που έχουν γραφτεί στον επεξεργαστή, όπως το HTML.
Ένα άλλο κρίσιμο εργαλείο είναι ο περιηγητής. Οι προγραμματιστές ιστού βασίζονται στον περιηγητή για να δουν πώς τρέχει ο κώδικάς τους στο διαδίκτυο. Χρησιμοποιείται επίσης για την εμφάνιση των οπτικών στοιχείων μιας ιστοσελίδας που έχουν γραφτεί στον επεξεργαστή, όπως το HTML.
Πολλοί περιηγητές διαθέτουν *εργαλεία προγραμματιστή* (DevTools) που περιέχουν ένα σύνολο χρήσιμων χαρακτηριστικών και πληροφοριών για να βοηθήσουν τους προγραμματιστές να συλλέξουν και να καταγράψουν σημαντικές πληροφορίες σχετικά με την εφαρμογή τους. Για παράδειγμα: Εάν μια ιστοσελίδα έχει σφάλματα, είναι μερικές φορές χρήσιμο να γνωρίζουμε πότε συνέβησαν. Τα DevTools σε έναν περιηγητή μπορούν να ρυθμιστούν για να καταγράψουν αυτές τις πληροφορίες.
Πολλοί περιηγητές διαθέτουν *εργαλεία προγραμματιστή* (DevTools) που περιέχουν ένα σύνολο χρήσιμων χαρακτηριστικών και πληροφοριών για να βοηθήσουν τους προγραμματιστές να συλλέξουν και να καταγράψουν σημαντικές πληροφορίες σχετικά με την εφαρμογή τους. Για παράδειγμα: Εάν μια ιστοσελίδα έχει σφάλματα, είναι μερικές φορές χρήσιμο να γνωρίζουμε πότε συνέβησαν. Τα DevTools σε έναν περιηγητή μπορούν να ρυθμιστούν ώστε να καταγράφουν αυτές τις πληροφορίες.
#### Δημοφιλείς Περιηγητές και DevTools
- [Edge](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium/?WT.mc_id=academic-77807-sagibbon)
- [Chrome](https://developers.google.com/web/tools/chrome-devtools/)
- [Firefox](https://developer.mozilla.org/docs/Tools)
- [Edge](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium/?WT.mc_id=academic-77807-sagibbon)
- [Chrome](https://developers.google.com/web/tools/chrome-devtools/)
- [Firefox](https://developer.mozilla.org/docs/Tools)
### Εργαλεία Γραμμής Εντολών
Μερικοί προγραμματιστές προτιμούν μια λιγότερο γραφική προσέγγιση για τις καθημερινές τους εργασίες και βασίζονται στη γραμμή εντολών για να το πετύχουν αυτό. Η συγγραφή κώδικα απαιτεί σημαντική ποσότητα πληκτρολόγησης και μερικοί προγραμματιστές προτιμούν να μην διακόπτουν τη ροή τους στο πληκτρολόγιο. Χρησιμοποιούν συντομεύσεις πληκτρολογίου για να εναλλάσσονται μεταξύ παραθύρων επιφάνειας εργασίας, να εργάζονται σε διαφορετικά αρχεία και να χρησιμοποιούν εργαλεία. Οι περισσότερες εργασίες μπορούν να ολοκληρωθούν με το ποντίκι, αλλά ένα πλεονέκτημα της γραμμής εντολών είναι ότι πολλά μπορούν να γίνουν με εργαλεία γραμμής εντολών χωρίς την ανάγκη εναλλαγής μεταξύ ποντικιού και πληκτρολογίου. Ένα άλλο πλεονέκτημα της γραμμής εντολών είναι ότι είναι παραμετροποιήσιμη και μπορείτε να αποθηκεύσετε μια προσαρμοσμένη διαμόρφωση, να την αλλάξετε αργότερα και να την εισαγάγετε σε άλλες μηχανές ανάπτυξης. Επειδή τα περιβάλλοντα ανάπτυξης είναι τόσο μοναδικά για κάθε προγραμματιστή, μερικοί αποφεύγουν τη γραμμή εντολών, άλλοι βασίζονται αποκλειστικά σε αυτήν, ενώ άλλοι προτιμούν έναν συνδυασμό των δύο.
Ορισμένοι προγραμματιστές προτιμούν μια λιγότερο γραφική προβολή για τις καθημερινές τους εργασίες και βασίζονται στη γραμμή εντολών για να το πετύχουν αυτό. Η γραφή κώδικα απαιτεί σημαντική ποσότητα πληκτρολόγησης και ορισμένοι προγραμματιστές προτιμούν να μην διακόπτουν τη ροή τους στο πληκτρολόγιο. Χρησιμοποιούν συντομεύσεις πληκτρολογίου για να εναλλάσσονται μεταξύ παραθύρων επιφάνειας εργασίας, να εργάζονται σε διαφορετικά αρχεία και να χρησιμοποιούν εργαλεία. Οι περισσότερες εργασίες μπορούν να ολοκληρωθούν με το ποντίκι, αλλά ένα πλεονέκτημα της γραμμής εντολών είναι ότι πολλά μπορούν να γίνουν με εργαλεία γραμμής εντολών χωρίς την ανάγκη εναλλαγής μεταξύ ποντικιού και πληκτρολογίου. Ένα άλλο πλεονέκτημα της γραμμής εντολών είναι ότι είναι παραμετροποιήσιμη και μπορείτε να αποθηκεύσετε μια προσαρμοσμένη ρύθμιση, να την αλλάξετε αργότερα και να την εισαγάγετε σε άλλες μηχανές ανάπτυξης. Επειδή τα περιβάλλοντα ανάπτυξης είναι τόσο μοναδικά για κάθε προγραμματιστή, κάποιοι θα αποφύγουν τη χρήση της γραμμής εντολών, κάποιοι θα βασίζονται αποκλειστικά σε αυτήν και κάποιοι προτιμούν έναν συνδυασμό των δύο.
### Δημοφιλείς Επιλογές Γραμμής Εντολών
@ -156,40 +157,41 @@ back add r0,r1
#### Windows
- [Powershell](https://docs.microsoft.com/powershell/scripting/overview?view=powershell-7/?WT.mc_id=academic-77807-sagibbon) 💻
- [Command Line](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands/?WT.mc_id=academic-77807-sagibbon) (γνωστό και ως CMD) 💻
- [Windows Terminal](https://docs.microsoft.com/windows/terminal/?WT.mc_id=academic-77807-sagibbon)
- [mintty](https://mintty.github.io/)
- [Powershell](https://docs.microsoft.com/powershell/scripting/overview?view=powershell-7/?WT.mc_id=academic-77807-sagibbon) 💻
- [Command Line](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands/?WT.mc_id=academic-77807-sagibbon) (γνωστό και ως CMD) 💻
- [Windows Terminal](https://docs.microsoft.com/windows/terminal/?WT.mc_id=academic-77807-sagibbon)
- [mintty](https://mintty.github.io/)
#### MacOS
- [Terminal](https://support.apple.com/guide/terminal/open-or-quit-terminal-apd5265185d-f365-44cb-8b09-71a064a42125/mac) 💻
- [iTerm](https://iterm2.com/)
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
- [Terminal](https://support.apple.com/guide/terminal/open-or-quit-terminal-apd5265185d-f365-44cb-8b09-71a064a42125/mac) 💻
- [iTerm](https://iterm2.com/)
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
#### Linux
- [Bash](https://www.gnu.org/software/bash/manual/html_node/index.html) 💻
- [KDE Konsole](https://docs.kde.org/trunk5/en/konsole/konsole/index.html)
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
- [Bash](https://www.gnu.org/software/bash/manual/html_node/index.html) 💻
- [KDE Konsole](https://docs.kde.org/trunk5/en/konsole/konsole/index.html)
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
#### Δημοφιλή Εργαλεία Γραμμής Εντολών
- [Git](https://git-scm.com/) (💻 στα περισσότερα λειτουργικά συστήματα)
- [NPM](https://www.npmjs.com/)
- [Yarn](https://classic.yarnpkg.com/en/docs/cli/)
- [Git](https://git-scm.com/) (💻 στα περισσότερα λειτουργικά συστήματα)
- [NPM](https://www.npmjs.com/)
- [Yarn](https://classic.yarnpkg.com/en/docs/cli/)
### Τεκμηρίωση
Όταν ένας προγραμματιστής θέλει να μάθει κάτι νέο, πιθανότατα θα στραφεί στην τεκμηρίωση για να μάθει πώς να το χρησιμοποιεί. Οι προγραμματιστές συχνά βασίζονται στην τεκμηρίωση για να τους καθοδηγήσει σχετικά με τη σωστή χρήση εργαλείων και γλωσσών, αλλά και για να αποκτήσουν βαθύτερη γνώση για το πώς λειτουργούν.
Όταν ένας προγραμματιστής θέλει να μάθει κάτι νέο, πιθανότατα θα στραφεί στην τεκμηρίωση για να μάθει πώς να το χρησιμοποιήσει. Οι προγραμματιστές συχνά βασίζονται στην τεκμηρίωση για να τους καθοδηγήσει σχετικά με το πώς να χρησιμοποιούν εργαλεία και γλώσσες σωστά, καθώς και για να αποκτήσουν βαθύτερη γνώση του πώς λειτουργούν.
#### Δημοφιλείς Πηγές Τεκμηρίωσης για Ανάπτυξη Ιστού
- [Mozilla Developer Network (MDN)](https://developer.mozilla.org/docs/Web), από τη Mozilla, τους εκδότες του περιηγητή [Firefox](https://www.mozilla.org/firefox/)
- [Frontend Masters](https://frontendmasters.com/learn/)
- [Web.dev](https://web.dev), από τη Google, εκδότες του [Chrome](https://www
- [Mozilla Developer Network (MDN)](https://developer.mozilla.org/docs/Web), από τη Mozilla, τους εκδότες του περιηγητή [Firefox](https://www.mozilla.org/firefox/)
- [Frontend Masters](https://frontendmasters.com/learn/)
- [Web.dev](https://web.dev), από τη Google, εκδότες του [Chrome](https://www.google.com/chrome/)
- [Microsoft's own developer docs](https://docs.microsoft.com/microsoft-edge/#microsoft-edge-for-developers
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "05666cecb8983a72cf0ce1d18932b5b7",
"translation_date": "2025-08-26T22:11:38+00:00",
"original_hash": "361249da70432ddfd4741c917d1a6f50",
"translation_date": "2025-08-29T07:23:30+00:00",
"source_file": "1-getting-started-lessons/2-github-basics/README.md",
"language_code": "el"
}
@ -12,10 +12,10 @@ CO_OP_TRANSLATOR_METADATA:
Αυτό το μάθημα καλύπτει τα βασικά του GitHub, μιας πλατφόρμας για φιλοξενία και διαχείριση αλλαγών στον κώδικά σας.
![Εισαγωγή στο GitHub](../../../../translated_images/webdev101-github.8846d7971abef6f947909b4f9d343e2a23778aa716ca6b9d71df7174ee5009ac.el.png)
> Σκίτσο από [Tomomi Imura](https://twitter.com/girlie_mac)
> Σημειώσεις από [Tomomi Imura](https://twitter.com/girlie_mac)
## Ερωτηματολόγιο πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/3)
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app)
## Εισαγωγή
@ -96,7 +96,7 @@ CO_OP_TRANSLATOR_METADATA:
Συνήθως η εντολή `git status` σας λέει πράγματα όπως ποια αρχεία είναι έτοιμα να _αποθηκευτούν_ στο αποθετήριο ή έχουν αλλαγές που ίσως θέλετε να διατηρήσετε.
1. **Προσθήκη όλων των αρχείων για παρακολούθηση**
Αυτό ονομάζεται επίσης στάδιο αρχειοθέτησης/προσθήκη αρχείων στην περιοχή στάδιο.
Αυτό ονομάζεται επίσης στάδιο αρχείων/προσθήκη αρχείων στην περιοχή σταδιοποίησης.
```bash
git add .
@ -110,25 +110,25 @@ CO_OP_TRANSLATOR_METADATA:
git add [file or folder name]
```
Αυτό μας βοηθά να προσθέσουμε μόνο επιλεγμένα αρχεία στην περιοχή στάδιο όταν δεν θέλουμε να κάνουμε commit όλα τα αρχεία ταυτόχρονα.
Αυτό μας βοηθά να προσθέσουμε μόνο επιλεγμένα αρχεία στην περιοχή σταδιοποίησης όταν δεν θέλουμε να κάνουμε commit όλα τα αρχεία ταυτόχρονα.
1. **Αφαίρεση όλων των αρχείων από το στάδιο**
1. **Αφαίρεση όλων των αρχείων από τη σταδιοποίηση**
```bash
git reset
```
Αυτή η εντολή μας βοηθά να αφαιρέσουμε όλα τα αρχεία από το στάδιο ταυτόχρονα.
Αυτή η εντολή μας βοηθά να αφαιρέσουμε όλα τα αρχεία από τη σταδιοποίηση ταυτόχρονα.
1. **Αφαίρεση ενός συγκεκριμένου αρχείου από το στάδιο**
1. **Αφαίρεση ενός συγκεκριμένου αρχείου από τη σταδιοποίηση**
```bash
git reset [file or folder name]
```
Αυτή η εντολή μας βοηθά να αφαιρέσουμε μόνο ένα συγκεκριμένο αρχείο από το στάδιο που δεν θέλουμε να συμπεριλάβουμε στο επόμενο commit.
Αυτή η εντολή μας βοηθά να αφαιρέσουμε μόνο ένα συγκεκριμένο αρχείο από τη σταδιοποίηση που δεν θέλουμε να συμπεριλάβουμε στο επόμενο commit.
1. **Διατήρηση της δουλειάς σας**. Σε αυτό το σημείο έχετε προσθέσει τα αρχεία σε μια λεγόμενη _περιοχή στάδιο_. Ένας χώρος όπου το Git παρακολουθεί τα αρχεία σας. Για να κάνετε την αλλαγή μόνιμη, πρέπει να _κάνετε commit_ τα αρχεία. Για να το κάνετε αυτό, δημιουργείτε ένα _commit_ με την εντολή `git commit`. Ένα _commit_ αντιπροσωπεύει ένα σημείο αποθήκευσης στην ιστορία του αποθετηρίου σας. Πληκτρολογήστε το εξής για να δημιουργήσετε ένα _commit_:
1. **Διατήρηση της δουλειάς σας**. Σε αυτό το σημείο έχετε προσθέσει τα αρχεία σε μια λεγόμενη _περιοχή σταδιοποίησης_. Ένα μέρος όπου το Git παρακολουθεί τα αρχεία σας. Για να κάνετε την αλλαγή μόνιμη, πρέπει να _κάνετε commit_ τα αρχεία. Για να το κάνετε αυτό, δημιουργείτε ένα _commit_ με την εντολή `git commit`. Ένα _commit_ αντιπροσωπεύει ένα σημείο αποθήκευσης στην ιστορία του αποθετηρίου σας. Πληκτρολογήστε το εξής για να δημιουργήσετε ένα _commit_:
```bash
git commit -m "first commit"
@ -138,15 +138,15 @@ CO_OP_TRANSLATOR_METADATA:
1. **Σύνδεση του τοπικού αποθετηρίου Git με το GitHub**. Ένα αποθετήριο Git είναι καλό στον υπολογιστή σας, αλλά κάποια στιγμή θα θέλετε να έχετε αντίγραφο ασφαλείας των αρχείων σας κάπου και επίσης να προσκαλέσετε άλλους να συνεργαστούν μαζί σας στο αποθετήριο σας. Ένα εξαιρετικό μέρος για να το κάνετε αυτό είναι το GitHub. Θυμηθείτε ότι έχουμε ήδη δημιουργήσει ένα αποθετήριο στο GitHub, οπότε το μόνο που χρειάζεται να κάνουμε είναι να συνδέσουμε το τοπικό αποθετήριο Git με το GitHub. Η εντολή `git remote add` θα το κάνει αυτό. Πληκτρολογήστε την παρακάτω εντολή:
> Σημείωση, πριν πληκτρολογήσετε την εντολή, μεταβείτε στη σελίδα του αποθετηρίου σας στο GitHub για να βρείτε το URL του αποθετηρίου. Θα το χρησιμοποιήσετε στην παρακάτω εντολή. Αντικαταστήστε ```https://github.com/username/repository_name.git``` με το URL του GitHub σας.
> Σημείωση, πριν πληκτρολογήσετε την εντολή, μεταβείτε στη σελίδα του αποθετηρίου σας στο GitHub για να βρείτε το URL του αποθετηρίου. Θα το χρησιμοποιήσετε στην παρακάτω εντολή. Αντικαταστήστε το ```https://github.com/username/repository_name.git``` με το URL του GitHub σας.
```bash
git remote add origin https://github.com/username/repository_name.git
```
Αυτό δημιουργεί μια _απομακρυσμένη σύνδεση_, ή σύνδεση, με το όνομα "origin" που δείχνει στο αποθετήριο GitHub που δημιουργήσατε νωρίτερα.
Αυτό δημιουργεί μια _απομακρυσμένη σύνδεση_, που ονομάζεται "origin", η οποία δείχνει στο αποθετήριο GitHub που δημιουργήσατε νωρίτερα.
1. **Αποστολή τοπικών αρχείων στο GitHub**. Μέχρι στιγμής έχετε δημιουργήσει μια _σύνδεση_ μεταξύ του τοπικού αποθετηρίου και του αποθετηρίου GitHub. Ας στείλουμε αυτά τα αρχεία στο GitHub με την παρακάτω εντολή `git push`, όπως:
1. **Αποστολή τοπικών αρχείων στο GitHub**. Μέχρι στιγμής έχετε δημιουργήσει μια _σύνδεση_ μεταξύ του τοπικού αποθετηρίου και του αποθετηρίου GitHub. Ας στείλουμε αυτά τα αρχεία στο GitHub με την παρακάτω εντολή `git push`, όπως εξής:
> Σημείωση, το όνομα του branch σας μπορεί να είναι διαφορετικό από το ```main```.
@ -168,10 +168,10 @@ CO_OP_TRANSLATOR_METADATA:
#### Μηνύματα commit
Ένα εξαιρετικό θέμα γραμμής μηνύματος commit στο Git ολοκληρώνει την παρακάτω πρόταση:
Ένα εξαιρετικό θέμα γραμμής μηνύματος commit ολοκληρώνει την παρακάτω πρόταση:
Αν εφαρμοστεί, αυτό το commit θα <το θέμα της γραμμής σας εδώ>
Για το θέμα χρησιμοποιήστε την προστακτική, ενεστώτα: "αλλάζω" αντί για "άλλαξα" ή "αλλαγές".
Για το θέμα, χρησιμοποιήστε την προστακτική, ενεστώτα: "αλλάξτε" αντί για "αλλαγμένο" ή "αλλαγές".
Όπως στο θέμα, στο σώμα (προαιρετικό) χρησιμοποιήστε επίσης την προστακτική, ενεστώτα. Το σώμα θα πρέπει να περιλαμβάνει το κίνητρο για την αλλαγή και να το συγκρίνει με την προηγούμενη συμπεριφορά. Εξηγείτε το `γιατί`, όχι το `πώς`.
✅ Αφιερώστε λίγα λεπτά για να περιηγηθείτε στο GitHub. Μπορείτε να βρείτε ένα πραγματικά εξαιρετικό μήνυμα commit; Μπορείτε να βρείτε ένα πραγματικά ελάχιστο; Ποιες πληροφορίες πιστεύετε ότι είναι οι πιο σημαντικές και χρήσιμες για να μεταδοθούν σε ένα μήνυμα commit;
@ -186,29 +186,29 @@ CO_OP_TRANSLATOR_METADATA:
>
> [![Βίντεο βασικών του Git και GitHub](https://img.youtube.com/vi/bFCM-PC3cu8/0.jpg)](https://www.youtube.com/watch?v=bFCM-PC3cu8)
Στο αποθετήριο σας, μεταβείτε στο `Insights > Community` για να δείτε πώς συγκρίνεται το έργο σας με τα προτεινόμενα πρότυπα κοινότητας.
Στο αποθετήριό σας, μεταβείτε στο `Insights > Community` για να δείτε πώς συγκρίνεται το έργο σας με τα προτεινόμενα πρότυπα κοινότητας.
Εδώ είναι μερικά πράγματα που μπορούν να βελτιώσουν το αποθετήριο σας στο GitHub:
- **Περιγραφή**. Προσθέσατε περιγραφή για το έργο σας;
- **README**. Προσθέσατε ένα README; Το GitHub παρέχει καθοδήγηση για τη συγγραφή ενός [README](https://docs.github.com/articles/about-readmes/?WT.mc_id=academic-77807-sagibbon).
- **Οδηγίες συνεισφοράς**. Έχει το έργο σας [οδηγίες συνεισφοράς](https://docs.github.com/articles/setting-guidelines-for-repository-contributors/?WT.mc_id=academic-77807-sagibbon);
- **Κώδικας Δεοντολογίας**. Ένας [Κώδικας Δεοντολογίας](https://docs.github.com/articles/adding-a-code-of-conduct-to-your-project/);
- **Άδεια χρήσης**. Ίσως πιο σημαντικά, μια [άδεια χρήσης](https://docs.github.com/articles/adding-a-license-to-a-repository/);
- **Άδεια Χρήσης**. Ίσως το πιο σημαντικό, μια [άδεια χρήσης](https://docs.github.com/articles/adding-a-license-to-a-repository/).
Όλοι αυτοί οι πόροι θα ωφελήσουν την ένταξη νέων μελών στην ομάδα. Και αυτά είναι συνήθως τα πράγματα που οι νέοι συνεισφέροντες κοιτάζουν πριν καν δουν τον κώδικά σας, για να διαπιστώσουν αν το έργο σας είναι το κατάλληλο μέρος για να αφιερώσουν τον χρόνο τους.
Όλοι αυτοί οι πόροι θα ωφελήσουν την ένταξη νέων μελών στην ομάδα. Και αυτά είναι συνήθως τα πράγματα που οι νέοι συνεισφέροντες εξετάζουν πριν καν κοιτάξουν τον κώδικά σας, για να δουν αν το έργο σας είναι το κατάλληλο μέρος για να αφιερώσουν τον χρόνο τους.
Τα αρχεία README, παρόλο που απαιτούν χρόνο για να προετοιμαστούν, συχνά παραμελούνται από πολυάσχολους συντηρητές. Μπορείτε να βρείτε ένα παράδειγμα ενός ιδιαίτερα περιγραφικού; Σημείωση: υπάρχουν μερικά [εργαλεία για τη δημιουργία καλών README](https://www.makeareadme.com/) που ίσως θέλετε να δοκιμάσετε.
Τα αρχεία README, αν και απαιτούν χρόνο για να προετοιμαστούν, συχνά παραμελούνται από πολυάσχολους συντηρητές. Μπορείτε να βρείτε ένα παράδειγμα ενός ιδιαίτερα περιγραφικού; Σημείωση: υπάρχουν μερικά [εργαλεία για τη δημιουργία καλών README](https://www.makeareadme.com/) που ίσως θέλετε να δοκιμάσετε.
### Εργασία: Συγχώνευση κώδικα
Τα έγγραφα συνεισφοράς βοηθούν τους ανθρώπους να συνεισφέρουν στο έργο. Εξηγεί τι είδους συνεισφορές αναζητάτε και πώς λειτουργεί η διαδικασία. Οι συνεισφέροντες θα χρειαστεί να περάσουν από μια σειρά βημάτων για να μπορέσουν να συνεισφέρουν στο αποθετήριο σας στο GitHub:
Τα έγγραφα συνεισφοράς βοηθούν τους ανθρώπους να συνεισφέρουν στο έργο. Εξηγούν τι είδους συνεισφορές αναζητάτε και πώς λειτουργεί η διαδικασία. Οι συνεισφέροντες θα χρειαστεί να περάσουν από μια σειρά βημάτων για να μπορέσουν να συνεισφέρουν στο αποθετήριο σας στο GitHub:
1. **Δημιουργία αντιγράφου του αποθετηρίου σας**. Πιθανότατα θα θέλετε οι άνθρωποι να _δημιουργήσουν αντίγραφο_ του έργου σας. Η δημιουργία αντιγράφου σημαίνει τη δημιουργία ενός αντιγράφου του αποθετηρίου σας στο προφίλ τους στο GitHub.
1. **Κλωνοποίηση**. Από εκεί θα κλωνοποιήσουν το έργο στον τοπικό τους υπολογιστή.
1. **Δημιουργία branch**. Θα θέλετε να τους ζητήσετε να δημιουργήσουν ένα _branch_ για τη δουλειά τους.
1. **Εστίαση της αλλαγής σε μία περιοχή**. Ζητήστε από τους συνεισφέροντες να επικεντρώσουν τις συνεισφορές τους σε ένα πράγμα τη φορά - έτσι οι πιθανότητες να _συγχωνεύσετε_ τη δουλειά τους είναι μεγαλύτερες. Φανταστείτε ότι γράφουν μια διόρθωση σφάλματος, προσθέτουν μια νέα λειτουργία και ενημερώνουν αρκετές δοκιμές - τι γίνεται αν θέλετε ή μπορείτε να εφαρμόσετε μόνο 2 από τις 3 ή 1 από τις 3 αλλαγές;
✅ Φανταστείτε μια κατάσταση όπου τα branches είναι ιδιαίτερα κρίσιμα για τη συγγραφή και αποστολή καλού κώδικα. Ποιες περιπτώσεις χρήσης μπορείτε να σκεφτείτε;
✅ Φανταστείτε μια κατάσταση όπου τα branches είναι ιδιαίτερα κρίσιμα για τη συγγραφή και την αποστολή καλού κώδικα. Ποιες περιπτώσεις χρήσης μπορείτε να σκεφτείτε;
> Σημείωση, γίνετε η αλλαγή που θέλετε να δείτε στον κόσμο και δημιουργήστε branches για τη δική σας δουλειά επίσης. Οποιαδήποτε commits κάνετε θα γίνουν στο branch που έχετε "επιλέξει". Χρησιμοποιήστε `git status` για να δείτε ποιο branch είναι αυτό.
@ -226,7 +226,7 @@ CO_OP_TRANSLATOR_METADATA:
git switch [branch-name]
```
1. **Εργασία**. Σε αυτό το σημείο θέλετε να προσθέσετε τις αλλαγές σας. Μην ξεχάσετε να ενημερώσετε το Git γι' αυτό με τις παρακάτω εντολές:
1. **Εργασία**. Σε αυτό το σημείο θέλετε να προσθέσετε τις αλλαγές σας. Μην ξεχάσετε να ενημερώσετε το Git γι' αυτές με τις παρακάτω εντολές:
```bash
git add .
@ -242,75 +242,73 @@ CO_OP_TRANSLATOR_METADATA:
git pull
```
Σε αυτό το σημείο θέλετε να βεβαιωθείτε ότι τυχόν _συγκρούσεις_, κατα
Βεβαιωθείτε ότι πηγαίνετε στη σελίδα GitHub για το forked repo και αφαιρέστε τον απομακρυσμένο κλάδο που μόλις σπρώξατε σε αυτό.
Σε αυτό το σημείο θέλετε να βεβαιωθείτε ότι τυχόν _συγκρούσεις_, καταστάσεις όπου το Git
`Pull request` φαίνεται σαν ένας αστείος όρος, γιατί στην πραγματικότητα θέλεις να σπρώξεις (push) τις αλλαγές σου στο έργο. Ωστόσο, ο συντηρητής (ιδιοκτήτης του έργου) ή η βασική ομάδα πρέπει να εξετάσουν τις αλλαγές σου πριν τις συγχωνεύσουν με τον "κύριο" κλάδο του έργου, οπότε ουσιαστικά ζητάς απόφαση αλλαγής από έναν συντηρητή.
Ο όρος `Pull request` φαίνεται λίγο αστείος, γιατί στην πραγματικότητα θέλετε να σπρώξετε τις αλλαγές σας στο έργο. Αλλά ο υπεύθυνος (ιδιοκτήτης του έργου) ή η βασική ομάδα πρέπει να εξετάσουν τις αλλαγές σας πριν τις συγχωνεύσουν με τον "κύριο" κλάδο του έργου, οπότε στην πραγματικότητα ζητάτε μια απόφαση αλλαγής από έναν υπεύθυνο.
Ένα pull request είναι ο χώρος όπου συγκρίνεις και συζητάς τις διαφορές που εισάγονται σε έναν κλάδο, με κριτικές, σχόλια, ενσωματωμένα τεστ και άλλα. Ένα καλό pull request ακολουθεί περίπου τους ίδιους κανόνες με ένα μήνυμα commit. Μπορείς να προσθέσεις μια αναφορά σε ένα ζήτημα στον ιχνηλάτη ζητημάτων, όταν για παράδειγμα η δουλειά σου διορθώνει ένα ζήτημα. Αυτό γίνεται χρησιμοποιώντας το `#` ακολουθούμενο από τον αριθμό του ζητήματος. Για παράδειγμα, `#97`.
Ένα pull request είναι το μέρος όπου συγκρίνετε και συζητάτε τις διαφορές που εισάγονται σε έναν κλάδο με κριτικές, σχόλια, ενσωματωμένα τεστ και άλλα. Ένα καλό pull request ακολουθεί περίπου τους ίδιους κανόνες με ένα μήνυμα commit. Μπορείτε να προσθέσετε μια αναφορά σε ένα ζήτημα στον παρακολουθητή ζητημάτων, όταν η εργασία σας, για παράδειγμα, διορθώνει ένα ζήτημα. Αυτό γίνεται χρησιμοποιώντας ένα `#` ακολουθούμενο από τον αριθμό του ζητήματος σας. Για παράδειγμα `#97`.
🤞Ελπίζουμε να περάσουν όλοι οι έλεγχοι και οι ιδιοκτήτες του έργου να συγχωνεύσουν τις αλλαγές σου στο έργο🤞
🤞Ελπίζουμε ότι όλα τα τεστ θα περάσουν και οι ιδιοκτήτες του έργου θα συγχωνεύσουν τις αλλαγές σας στο έργο🤞
Ενημερώστε τον τρέχοντα τοπικό κλάδο εργασίας σας με όλα τα νέα commits από τον αντίστοιχο απομακρυσμένο κλάδο στο GitHub:
Ενημέρωσε τον τρέχοντα τοπικό κλάδο εργασίας σου με όλα τα νέα commits από τον αντίστοιχο απομακρυσμένο κλάδο στο GitHub:
`git pull`
## Πώς να συνεισφέρετε σε ανοιχτό λογισμικό
## Πώς να συνεισφέρεις σε ανοιχτό κώδικα
Πρώτα, ας βρούμε ένα αποθετήριο (ή **repo**) στο GitHub που σας ενδιαφέρει και στο οποίο θέλετε να συνεισφέρετε μια αλλαγή. Θα θέλετε να αντιγράψετε το περιεχόμενό του στον υπολογιστή σας.
Αρχικά, ας βρούμε ένα αποθετήριο (ή **repo**) στο GitHub που σε ενδιαφέρει και στο οποίο θέλεις να συνεισφέρεις μια αλλαγή. Θα χρειαστεί να αντιγράψεις το περιεχόμενό του στον υπολογιστή σου.
✅ Ένας καλός τρόπος για να βρείτε αποθετήρια φιλικά προς αρχάριους είναι να [αναζητήσετε με την ετικέτα 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
✅ Ένας καλός τρόπος να βρεις αποθετήρια φιλικά για αρχάριους είναι να [αναζητήσεις με την ετικέτα 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
![Αντιγραφή ενός repo τοπικά](../../../../translated_images/clone_repo.5085c48d666ead57664f050d806e325d7f883be6838c821e08bc823ab7c66665.el.png)
![Αντιγραφή ενός αποθετηρίου τοπικά](../../../../translated_images/clone_repo.5085c48d666ead57664f050d806e325d7f883be6838c821e08bc823ab7c66665.el.png)
Υπάρχουν διάφοροι τρόποι αντιγραφής κώδικα. Ένας τρόπος είναι να "κλωνοποιήσετε" το περιεχόμενο του αποθετηρίου, χρησιμοποιώντας HTTPS, SSH ή το GitHub CLI (Command Line Interface).
Υπάρχουν διάφοροι τρόποι αντιγραφής κώδικα. Ένας τρόπος είναι να "κλωνοποιήσεις" το περιεχόμενο του αποθετηρίου, χρησιμοποιώντας HTTPS, SSH ή το GitHub CLI (Command Line Interface).
Ανοίξτε το τερματικό σας και κλωνοποιήστε το αποθετήριο όπως παρακάτω:
Άνοιξε το τερματικό σου και κλωνοποίησε το αποθετήριο ως εξής:
`git clone https://github.com/ProjectURL`
Για να εργαστείτε στο έργο, μεταβείτε στον σωστό φάκελο:
Για να δουλέψεις στο έργο, άλλαξε στον σωστό φάκελο:
`cd ProjectURL`
Μπορείτε επίσης να ανοίξετε ολόκληρο το έργο χρησιμοποιώντας [Codespaces](https://github.com/features/codespaces), τον ενσωματωμένο επεξεργαστή κώδικα / περιβάλλον ανάπτυξης cloud του GitHub, ή το [GitHub Desktop](https://desktop.github.com/).
Μπορείς επίσης να ανοίξεις ολόκληρο το έργο χρησιμοποιώντας το [Codespaces](https://github.com/features/codespaces), τον ενσωματωμένο επεξεργαστή κώδικα / περιβάλλον ανάπτυξης στο cloud του GitHub, ή το [GitHub Desktop](https://desktop.github.com/).
Τέλος, μπορείτε να κατεβάσετε τον κώδικα σε έναν συμπιεσμένο φάκελο.
Τέλος, μπορείς να κατεβάσεις τον κώδικα σε έναν συμπιεσμένο φάκελο.
### Μερικά ακόμη ενδιαφέροντα πράγματα για το GitHub
### Μερικά ακόμα ενδιαφέροντα πράγματα για το GitHub
Μπορείτε να κάνετε star, watch και/ή "fork" οποιοδήποτε δημόσιο αποθετήριο στο GitHub. Μπορείτε να βρείτε τα αποθετήρια που έχετε κάνει star στο αναπτυσσόμενο μενού πάνω δεξιά. Είναι σαν να κάνετε bookmarking, αλλά για κώδικα.
Μπορείς να κάνεις star, watch και/ή "fork" οποιοδήποτε δημόσιο αποθετήριο στο GitHub. Μπορείς να βρεις τα αποθετήρια που έχεις κάνει star στο αναδυόμενο μενού πάνω δεξιά. Είναι σαν να κάνεις σελιδοδείκτη, αλλά για κώδικα.
Τα έργα έχουν έναν παρακολουθητή ζητημάτων, κυρίως στο GitHub στην καρτέλα "Issues", εκτός αν αναφέρεται διαφορετικά, όπου οι άνθρωποι συζητούν ζητήματα που σχετίζονται με το έργο. Και η καρτέλα Pull Requests είναι όπου οι άνθρωποι συζητούν και αξιολογούν αλλαγές που βρίσκονται σε εξέλιξη.
Τα έργα έχουν έναν ιχνηλάτη ζητημάτων, συνήθως στο GitHub στην καρτέλα "Issues", εκτός αν αναφέρεται διαφορετικά, όπου οι άνθρωποι συζητούν ζητήματα που σχετίζονται με το έργο. Και η καρτέλα Pull Requests είναι εκεί όπου οι άνθρωποι συζητούν και αξιολογούν αλλαγές που βρίσκονται σε εξέλιξη.
Τα έργα μπορεί επίσης να έχουν συζητήσεις σε φόρουμ, λίστες αλληλογραφίας ή κανάλια συνομιλίας όπως Slack, Discord ή IRC.
✅ Ρίξτε μια ματιά στο νέο σας αποθετήριο GitHub και δοκιμάστε μερικά πράγματα, όπως να επεξεργαστείτε ρυθμίσεις, να προσθέσετε πληροφορίες στο repo σας και να δημιουργήσετε ένα έργο (όπως έναν πίνακα Kanban). Υπάρχουν πολλά που μπορείτε να κάνετε!
✅ Ρίξε μια ματιά στο νέο σου αποθετήριο GitHub και δοκίμασε μερικά πράγματα, όπως να επεξεργαστείς ρυθμίσεις, να προσθέσεις πληροφορίες στο αποθετήριο σου και να δημιουργήσεις ένα έργο (όπως έναν πίνακα Kanban). Υπάρχουν πολλά που μπορείς να κάνεις!
---
## 🚀 Πρόκληση
Συνεργαστείτε με έναν φίλο για να εργαστείτε στον κώδικα του άλλου. Δημιουργήστε ένα έργο συνεργατικά, κάντε fork τον κώδικα, δημιουργήστε κλάδους και συγχωνεύστε αλλαγές.
Συνεργάσου με έναν φίλο για να δουλέψετε στον κώδικα του άλλου. Δημιουργήστε ένα έργο συνεργατικά, κάντε fork κώδικα, δημιουργήστε κλάδους και συγχωνεύστε αλλαγές.
## Κουίζ μετά το μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/4)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/en/)
## Ανασκόπηση & Αυτομελέτη
Διαβάστε περισσότερα για [τη συνεισφορά σε λογισμικό ανοιχτού κώδικα](https://opensource.guide/how-to-contribute/#how-to-submit-a-contribution).
Διάβασε περισσότερα για το [πώς να συνεισφέρεις σε λογισμικό ανοιχτού κώδικα](https://opensource.guide/how-to-contribute/#how-to-submit-a-contribution).
[Git cheatsheet](https://training.github.com/downloads/github-git-cheat-sheet/).
Εξασκηθείτε, εξασκηθείτε, εξασκηθείτε. Το GitHub διαθέτει εξαιρετικά μονοπάτια μάθησης μέσω [skills.github.com](https://skills.github.com):
Εξάσκηση, εξάσκηση, εξάσκηση. Το GitHub έχει εξαιρετικά μονοπάτια μάθησης διαθέσιμα μέσω του [skills.github.com](https://skills.github.com):
- [Πρώτη Εβδομάδα στο GitHub](https://skills.github.com/#first-week-on-github)
Θα βρείτε επίσης πιο προχωρημένα μαθήματα.
Θα βρεις επίσης πιο προχωρημένα μαθήματα.
## Εργασία
Ολοκληρώστε [το μάθημα Πρώτη Εβδομάδα στο GitHub](https://skills.github.com/#first-week-on-github)
Ολοκλήρωσε το μάθημα [Πρώτη Εβδομάδα στο GitHub](https://skills.github.com/#first-week-on-github)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e4cd5b1faed4adab5acf720f82798003",
"translation_date": "2025-08-26T22:16:52+00:00",
"original_hash": "f0c88c3e2cefa8952d356f802b1e47ca",
"translation_date": "2025-08-29T07:22:42+00:00",
"source_file": "1-getting-started-lessons/3-accessibility/README.md",
"language_code": "el"
}
@ -13,13 +13,13 @@ CO_OP_TRANSLATOR_METADATA:
> Σκίτσο από [Tomomi Imura](https://twitter.com/girlie_mac)
## Ερωτηματολόγιο πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/5)
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/)
> Η δύναμη του Ιστού βρίσκεται στην καθολικότητά του. Η πρόσβαση από όλους, ανεξαρτήτως αναπηρίας, είναι μια ουσιώδης πτυχή.
>
> \- Sir Timothy Berners-Lee, Διευθυντής του W3C και εφευρέτης του Παγκόσμιου Ιστού
Αυτό το απόφθεγμα υπογραμμίζει τέλεια τη σημασία της δημιουργίας προσβάσιμων ιστοσελίδων. Μια εφαρμογή που δεν είναι προσβάσιμη από όλους είναι εξ ορισμού αποκλειστική. Ως προγραμματιστές ιστού, πρέπει πάντα να έχουμε την προσβασιμότητα στο μυαλό μας. Εστιάζοντας σε αυτήν από την αρχή, θα είστε σε καλό δρόμο για να διασφαλίσετε ότι όλοι μπορούν να έχουν πρόσβαση στις σελίδες που δημιουργείτε. Σε αυτό το μάθημα, θα μάθετε για τα εργαλεία που μπορούν να σας βοηθήσουν να διασφαλίσετε ότι τα στοιχεία του ιστού σας είναι προσβάσιμα και πώς να δημιουργείτε με γνώμονα την προσβασιμότητα.
Αυτό το απόφθεγμα υπογραμμίζει τέλεια τη σημασία της δημιουργίας προσβάσιμων ιστοσελίδων. Μια εφαρμογή που δεν είναι προσβάσιμη από όλους είναι εξ ορισμού αποκλειστική. Ως προγραμματιστές ιστού, πρέπει πάντα να έχουμε την προσβασιμότητα στο μυαλό μας. Εστιάζοντας σε αυτό από την αρχή, θα είστε σε καλό δρόμο για να διασφαλίσετε ότι όλοι μπορούν να έχουν πρόσβαση στις σελίδες που δημιουργείτε. Σε αυτό το μάθημα, θα μάθετε για τα εργαλεία που μπορούν να σας βοηθήσουν να διασφαλίσετε ότι τα διαδικτυακά σας στοιχεία είναι προσβάσιμα και πώς να δημιουργείτε με γνώμονα την προσβασιμότητα.
> Μπορείτε να παρακολουθήσετε αυτό το μάθημα στο [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/accessibility/?WT.mc_id=academic-77807-sagibbon)!
@ -31,13 +31,13 @@ CO_OP_TRANSLATOR_METADATA:
[Οι αναγνώστες οθόνης](https://en.wikipedia.org/wiki/Screen_reader) είναι συνήθως χρησιμοποιούμενοι πελάτες από άτομα με προβλήματα όρασης. Όπως αφιερώνουμε χρόνο για να διασφαλίσουμε ότι ένας περιηγητής μεταφέρει σωστά τις πληροφορίες που θέλουμε να μοιραστούμε, πρέπει επίσης να διασφαλίσουμε ότι ένας αναγνώστης οθόνης κάνει το ίδιο.
Στην πιο βασική του μορφή, ένας αναγνώστης οθόνης θα διαβάσει μια σελίδα από πάνω προς τα κάτω ακουστικά. Εάν η σελίδα σας είναι όλο κείμενο, ο αναγνώστης θα μεταφέρει τις πληροφορίες με παρόμοιο τρόπο με έναν περιηγητή. Φυσικά, οι ιστοσελίδες σπάνια είναι καθαρά κείμενο· περιέχουν συνδέσμους, γραφικά, χρώματα και άλλα οπτικά στοιχεία. Πρέπει να ληφθεί μέριμνα ώστε αυτές οι πληροφορίες να διαβάζονται σωστά από έναν αναγνώστη οθόνης.
Στην πιο βασική του μορφή, ένας αναγνώστης οθόνης θα διαβάσει μια σελίδα από πάνω προς τα κάτω ακουστικά. Αν η σελίδα σας είναι μόνο κείμενο, ο αναγνώστης θα μεταφέρει τις πληροφορίες με παρόμοιο τρόπο όπως ένας περιηγητής. Φυσικά, οι ιστοσελίδες σπάνια είναι καθαρά κείμενο· περιέχουν συνδέσμους, γραφικά, χρώματα και άλλα οπτικά στοιχεία. Πρέπει να ληφθεί μέριμνα ώστε αυτές οι πληροφορίες να διαβάζονται σωστά από έναν αναγνώστη οθόνης.
Κάθε προγραμματιστής ιστού πρέπει να εξοικειωθεί με έναν αναγνώστη οθόνης. Όπως τονίστηκε παραπάνω, είναι ο πελάτης που θα χρησιμοποιήσουν οι χρήστες σας. Με τον ίδιο τρόπο που είστε εξοικειωμένοι με τη λειτουργία ενός περιηγητή, πρέπει να μάθετε πώς λειτουργεί ένας αναγνώστης οθόνης. Ευτυχώς, οι αναγνώστες οθόνης είναι ενσωματωμένοι στα περισσότερα λειτουργικά συστήματα.
Ορισμένοι περιηγητές διαθέτουν επίσης ενσωματωμένα εργαλεία και επεκτάσεις που μπορούν να διαβάσουν κείμενο δυνατά ή ακόμα και να παρέχουν βασικές λειτουργίες πλοήγησης, όπως [αυτά τα εργαλεία προσβασιμότητας του περιηγητή Edge](https://support.microsoft.com/help/4000734/microsoft-edge-accessibility-features). Αυτά είναι επίσης σημαντικά εργαλεία προσβασιμότητας, αλλά λειτουργούν πολύ διαφορετικά από τους αναγνώστες οθόνης και δεν πρέπει να θεωρούνται εργαλεία δοκιμής αναγνωστών οθόνης.
Ορισμένοι περιηγητές διαθέτουν επίσης ενσωματωμένα εργαλεία και επεκτάσεις που μπορούν να διαβάσουν κείμενο δυνατά ή ακόμα και να παρέχουν κάποιες βασικές λειτουργίες πλοήγησης, όπως [αυτά τα εργαλεία προσβασιμότητας του περιηγητή Edge](https://support.microsoft.com/help/4000734/microsoft-edge-accessibility-features). Αυτά είναι επίσης σημαντικά εργαλεία προσβασιμότητας, αλλά λειτουργούν πολύ διαφορετικά από τους αναγνώστες οθόνης και δεν πρέπει να συγχέονται με εργαλεία δοκιμής αναγνωστών οθόνης.
✅ Δοκιμάστε έναν αναγνώστη οθόνης και έναν αναγνώστη κειμένου περιηγητή. Στα Windows, το [Narrator](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon) περιλαμβάνεται από προεπιλογή, ενώ το [JAWS](https://webaim.org/articles/jaws/) και το [NVDA](https://www.nvaccess.org/about-nvda/) μπορούν επίσης να εγκατασταθούν. Στο macOS και το iOS, το [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10) είναι εγκατεστημένο από προεπιλογή.
✅ Δοκιμάστε έναν αναγνώστη οθόνης και έναν περιηγητή που διαβάζει κείμενο. Στα Windows, το [Narrator](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon) περιλαμβάνεται από προεπιλογή, ενώ το [JAWS](https://webaim.org/articles/jaws/) και το [NVDA](https://www.nvaccess.org/about-nvda/) μπορούν επίσης να εγκατασταθούν. Στο macOS και το iOS, το [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10) είναι εγκατεστημένο από προεπιλογή.
### Μεγέθυνση
@ -49,7 +49,7 @@ CO_OP_TRANSLATOR_METADATA:
Τα χρώματα στις ιστοσελίδες πρέπει να επιλέγονται προσεκτικά για να καλύπτουν τις ανάγκες των χρηστών με αχρωματοψία ή ατόμων που δυσκολεύονται να δουν χρώματα χαμηλής αντίθεσης.
✅ Δοκιμάστε μια ιστοσελίδα που σας αρέσει για τη χρήση χρωμάτων με μια επέκταση περιηγητή όπως ο [ελεγκτής χρωματικής αντίθεσης του WCAG](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US&WT.mc_id=academic-77807-sagibbon). Τι μαθαίνετε;
✅ Δοκιμάστε μια ιστοσελίδα που σας αρέσει για τη χρήση χρωμάτων με μια επέκταση περιηγητή όπως [ο ελεγκτής χρωματικής αντίθεσης του WCAG](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US&WT.mc_id=academic-77807-sagibbon). Τι μαθαίνετε;
### Lighthouse
@ -63,13 +63,13 @@ CO_OP_TRANSLATOR_METADATA:
- [Accessible U - Πανεπιστήμιο της Μινεσότα](https://accessibility.umn.edu/your-role/web-developers)
Παρόλο που δεν θα μπορέσουμε να καλύψουμε κάθε πτυχή της δημιουργίας προσβάσιμων ιστοσελίδων, παρακάτω παρατίθενται μερικές από τις βασικές αρχές που θα θέλετε να εφαρμόσετε. Ο σχεδιασμός μιας προσβάσιμης σελίδας από την αρχή είναι **πάντα** ευκολότερος από το να επιστρέψετε σε μια υπάρχουσα σελίδα για να την κάνετε προσβάσιμη.
Παρόλο που δεν θα μπορέσουμε να καλύψουμε κάθε πτυχή της δημιουργίας προσβάσιμων ιστοσελίδων, παρακάτω παρατίθενται ορισμένες βασικές αρχές που θα θέλετε να εφαρμόσετε. Ο σχεδιασμός μιας προσβάσιμης σελίδας από την αρχή είναι **πάντα** ευκολότερος από το να επιστρέψετε σε μια υπάρχουσα σελίδα για να την κάνετε προσβάσιμη.
## Καλές αρχές εμφάνισης
### Ασφαλείς παλέτες χρωμάτων
Οι άνθρωποι βλέπουν τον κόσμο με διαφορετικούς τρόπους, και αυτό περιλαμβάνει τα χρώματα. Όταν επιλέγετε ένα χρωματικό σχήμα για την ιστοσελίδα σας, πρέπει να διασφαλίσετε ότι είναι προσβάσιμο σε όλους. Ένα εξαιρετικό [εργαλείο για τη δημιουργία χρωματικών παλετών είναι το Color Safe](http://colorsafe.co/).
Οι άνθρωποι βλέπουν τον κόσμο με διαφορετικούς τρόπους, και αυτό περιλαμβάνει τα χρώματα. Όταν επιλέγετε ένα χρωματικό σχήμα για την ιστοσελίδα σας, πρέπει να διασφαλίσετε ότι είναι προσβάσιμο σε όλους. Ένα εξαιρετικό [εργαλείο για τη δημιουργία παλετών χρωμάτων είναι το Color Safe](http://colorsafe.co/).
✅ Εντοπίστε μια ιστοσελίδα που είναι πολύ προβληματική στη χρήση χρωμάτων. Γιατί;
@ -93,23 +93,23 @@ CO_OP_TRANSLATOR_METADATA:
### Αναγνώστες οθόνης και σύνδεσμοι
Όπως θα περιμένατε, οι αναγνώστες οθόνης διαβάζουν το κείμενο των συνδέσμων με τον ίδιο τρόπο που θα διάβαζαν οποιοδήποτε άλλο κείμενο στη σελίδα. Με αυτό κατά νου, το κείμενο που φαίνεται παρακάτω μπορεί να φαίνεται απολύτως αποδεκτό.
Όπως θα περιμένατε, οι αναγνώστες οθόνης διαβάζουν το κείμενο των συνδέσμων με τον ίδιο τρόπο που θα διάβαζαν οποιοδήποτε άλλο κείμενο στη σελίδα. Με αυτό στο μυαλό, το κείμενο που φαίνεται παρακάτω μπορεί να φαίνεται απολύτως αποδεκτό.
> Ο μικρός πιγκουίνος, γνωστός και ως νεραϊδοπιγκουίνος, είναι ο μικρότερος πιγκουίνος στον κόσμο. [Κάντε κλικ εδώ](https://en.wikipedia.org/wiki/Little_penguin) για περισσότερες πληροφορίες.
> Ο μικρός πιγκουίνος, γνωστός και ως νεραϊδοπιγκουίνος, είναι ο μικρότερος πιγκουίνος στον κόσμο. Επισκεφθείτε https://en.wikipedia.org/wiki/Little_penguin για περισσότερες πληροφορίες.
> **NOTE** Όπως πρόκειται να διαβάσετε, δεν πρέπει **ποτέ** να δημιουργείτε συνδέσμους που μοιάζουν με τα παραπάνω.
> **NOTE** Όπως πρόκειται να διαβάσετε, δεν πρέπει **ποτέ** να δημιουργείτε συνδέσμους που μοιάζουν με τους παραπάνω.
Θυμηθείτε, οι αναγνώστες οθόνης είναι μια διαφορετική διεπαφή από τους περιηγητές με διαφορετικό σύνολο λειτουργιών.
### Το πρόβλημα με τη χρήση της διεύθυνσης URL
Οι αναγνώστες οθόνης διαβάζουν το κείμενο. Εάν μια διεύθυνση URL εμφανίζεται στο κείμενο, ο αναγνώστης οθόνης θα διαβάσει τη διεύθυνση URL. Γενικά, η διεύθυνση URL δεν μεταφέρει ουσιαστικές πληροφορίες και μπορεί να ακούγεται ενοχλητική. Ίσως το έχετε βιώσει αν το τηλέφωνό σας έχει διαβάσει δυνατά ένα μήνυμα κειμένου με μια διεύθυνση URL.
Οι αναγνώστες οθόνης διαβάζουν το κείμενο. Αν μια διεύθυνση URL εμφανίζεται στο κείμενο, ο αναγνώστης οθόνης θα διαβάσει τη διεύθυνση URL. Γενικά, η διεύθυνση URL δεν μεταφέρει ουσιαστικές πληροφορίες και μπορεί να ακούγεται ενοχλητική. Ίσως το έχετε βιώσει αν το τηλέφωνό σας έχει διαβάσει δυνατά ένα μήνυμα κειμένου με μια διεύθυνση URL.
### Το πρόβλημα με το "κάντε κλικ εδώ"
Οι αναγνώστες οθόνης έχουν επίσης τη δυνατότητα να διαβάζουν μόνο τους υπερσυνδέσμους σε μια σελίδα, όπως ακριβώς ένας βλέποντας χρήστης θα σάρωσε μια σελίδα για συνδέσμους. Εάν το κείμενο του συνδέσμου είναι πάντα "κάντε κλικ εδώ", το μόνο που θα ακούσει ο χρήστης είναι "κάντε κλικ εδώ, κάντε κλικ εδώ, κάντε κλικ εδώ, κάντε κλικ εδώ, κάντε κλικ εδώ, ..." Όλοι οι σύνδεσμοι είναι πλέον αδιάκριτοι μεταξύ τους.
Οι αναγνώστες οθόνης έχουν επίσης τη δυνατότητα να διαβάζουν μόνο τους υπερσυνδέσμους σε μια σελίδα, όπως ακριβώς ένας βλέποντας χρήστης θα σάρωσε μια σελίδα για συνδέσμους. Αν το κείμενο των συνδέσμων είναι πάντα "κάντε κλικ εδώ", το μόνο που θα ακούσει ο χρήστης είναι "κάντε κλικ εδώ, κάντε κλικ εδώ, κάντε κλικ εδώ, κάντε κλικ εδώ, κάντε κλικ εδώ, ..." Όλοι οι σύνδεσμοι είναι πλέον αδιάκριτοι μεταξύ τους.
### Καλό κείμενο συνδέσμων
@ -121,7 +121,7 @@ CO_OP_TRANSLATOR_METADATA:
#### Σημειώσεις για τις μηχανές αναζήτησης
Ως πρόσθετο πλεονέκτημα για τη διασφάλιση ότι η ιστοσελίδα σας είναι προσβάσιμη σε όλους, θα βοηθήσετε τις μηχανές αναζήτησης να πλοηγηθούν στην ιστοσελίδα σας. Οι μηχανές αναζήτησης χρησιμοποιούν το κείμενο συνδέσμων για να μάθουν τα θέματα των σελίδων. Έτσι, η χρήση καλού κειμένου συνδέσμων βοηθάει όλους!
Ως πρόσθετο πλεονέκτημα για τη διασφάλιση ότι η ιστοσελίδα σας είναι προσβάσιμη σε όλους, θα βοηθήσετε τις μηχανές αναζήτησης να πλοηγηθούν στην ιστοσελίδα σας επίσης. Οι μηχανές αναζήτησης χρησιμοποιούν το κείμενο των συνδέσμων για να μάθουν τα θέματα των σελίδων. Έτσι, η χρήση καλού κειμένου συνδέσμων βοηθάει όλους!
### ARIA
@ -132,18 +132,18 @@ CO_OP_TRANSLATOR_METADATA:
| Widget | [Περιγραφή](../../../../1-getting-started-lessons/3-accessibility/') | [Παραγγελία](../../../../1-getting-started-lessons/3-accessibility/') |
| Super widget | [Περιγραφή](../../../../1-getting-started-lessons/3-accessibility/') | [Παραγγελία](../../../../1-getting-started-lessons/3-accessibility/') |
Σε αυτό το παράδειγμα, η επανάληψη του κειμένου περιγραφής και παραγγελίας έχει νόημα για κάποιον που χρησιμοποιεί περιηγητή. Ωστόσο, κάποιος που χρησιμοποιεί αναγνώστη οθόνης θα ακούσει μόνο τις λέξεις *περιγραφή* και *παραγγελία* επαναλαμβανόμενες χωρίς πλαίσιο.
Σε αυτό το παράδειγμα, η επανάληψη του κειμένου "περιγραφή" και "παραγγελία" έχει νόημα για κάποιον που χρησιμοποιεί περιηγητή. Ωστόσο, κάποιος που χρησιμοποιεί αναγνώστη οθόνης θα ακούσει μόνο τις λέξεις *περιγραφή* και *παραγγελία* επαναλαμβανόμενες χωρίς πλαίσιο.
Για να υποστηρίξετε αυτούς τους τύπους σεναρίων, το HTML υποστηρίζει ένα σύνολο χαρακτηριστικών γνωστό ως [Accessible Rich Internet Applications (ARIA)](https://developer.mozilla.org/docs
Για να υποστηρίξετε αυτούς τους τύπους σεναρίων, το HTML υποστηρίζει ένα σύνολο χαρακτηριστικών γνωστό ως [Accessible Rich Internet Applications (ARIA)](https://developer.mozilla.org/docs/Web/Accessibility/ARIA
Πολλές κυβερνήσεις έχουν νόμους σχετικά με τις απαιτήσεις προσβασιμότητας. Ενημερωθείτε για τους νόμους προσβασιμότητας της χώρας σας. Τι καλύπτεται και τι όχι; Ένα παράδειγμα είναι [αυτός ο κυβερνητικός ιστότοπος](https://accessibility.blog.gov.uk/).
## Ανάθεση
[Αναλύστε έναν μη προσβάσιμο ιστότοπο](assignment.md)
Πιστώσεις: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) από την Instrument
Πιστώσεις: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) από Instrument
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,19 +1,19 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "fc6aef8ecfdd5b0ad2afa6e6ba52bfde",
"translation_date": "2025-08-26T21:47:48+00:00",
"original_hash": "b95fdd8310ef467305015ece1b0f9411",
"translation_date": "2025-08-29T07:14:07+00:00",
"source_file": "2-js-basics/1-data-types/README.md",
"language_code": "el"
}
-->
# Βασικά στοιχεία JavaScript: Τύποι Δεδομένων
# Βασικά Στοιχεία JavaScript: Τύποι Δεδομένων
![Βασικά στοιχεία JavaScript - Τύποι δεδομένων](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.el.png)
> Σημειώσεις από [Tomomi Imura](https://twitter.com/girlie_mac)
![Βασικά Στοιχεία JavaScript - Τύποι Δεδομένων](../../../../translated_images/webdev101-js-datatypes.4cc470179730702c756480d3ffa46507f746e5975ebf80f99fdaaf1cff09a7f4.el.png)
> Σκίτσο από την [Tomomi Imura](https://twitter.com/girlie_mac)
## Ερωτήσεις πριν το μάθημα
[Ερωτήσεις πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/7)
## Κουίζ Πριν το Μάθημα
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/)
Αυτό το μάθημα καλύπτει τα βασικά της JavaScript, της γλώσσας που προσφέρει διαδραστικότητα στον ιστό.
@ -23,22 +23,22 @@ CO_OP_TRANSLATOR_METADATA:
[![Τύποι Δεδομένων στη JavaScript](https://img.youtube.com/vi/AWfA95eLdq8/0.jpg)](https://youtube.com/watch?v=AWfA95eLdq8 "Τύποι Δεδομένων στη JavaScript")
> 🎥 Κάντε κλικ στις παραπάνω εικόνες για βίντεο σχετικά με τις μεταβλητές και τους τύπους δεδομένων
> 🎥 Κάντε κλικ στις παραπάνω εικόνες για βίντεο σχετικά με τις μεταβλητές και τους τύπους δεδομένων.
Ας ξεκινήσουμε με τις μεταβλητές και τους τύπους δεδομένων που τις γεμίζουν!
## Μεταβλητές
Οι μεταβλητές αποθηκεύουν τιμές που μπορούν να χρησιμοποιηθούν και να αλλάξουν καθ' όλη τη διάρκεια του κώδικα σας.
Οι μεταβλητές αποθηκεύουν τιμές που μπορούν να χρησιμοποιηθούν και να αλλάξουν σε όλο τον κώδικά σας.
Η δημιουργία και **δήλωση** μιας μεταβλητής έχει την εξής σύνταξη **[λέξη-κλειδί] [όνομα]**. Αποτελείται από δύο μέρη:
Η δημιουργία και η **δήλωση** μιας μεταβλητής έχει την εξής σύνταξη **[λέξη-κλειδί] [όνομα]**. Αποτελείται από δύο μέρη:
- **Λέξη-κλειδί**. Οι λέξεις-κλειδιά μπορεί να είναι `let` ή `var`.
Η λέξη-κλειδί `let` εισήχθη στην ES6 και δίνει στη μεταβλητή σας μια λεγόμενη _block scope_. Συνιστάται να χρησιμοποιείτε `let` αντί για `var`. Θα καλύψουμε το block scope πιο αναλυτικά σε επόμενα μέρη.
Η λέξη-κλειδί `let` εισήχθη στην ES6 και δίνει στη μεταβλητή σας το λεγόμενο _block scope_. Συνιστάται να χρησιμοποιείτε το `let` αντί για το `var`. Θα καλύψουμε τα block scopes πιο αναλυτικά σε επόμενα μέρη.
- **Το όνομα της μεταβλητής**, το οποίο επιλέγετε εσείς.
### Εργασία - Εργασία με μεταβλητές
### Εργασία - Εργασία με Μεταβλητές
1. **Δηλώστε μια μεταβλητή**. Ας δηλώσουμε μια μεταβλητή χρησιμοποιώντας τη λέξη-κλειδί `let`:
@ -46,7 +46,7 @@ CO_OP_TRANSLATOR_METADATA:
let myVariable;
```
Η `myVariable` έχει τώρα δηλωθεί χρησιμοποιώντας τη λέξη-κλειδί `let`. Προς το παρόν δεν έχει τιμή.
Η `myVariable` έχει πλέον δηλωθεί χρησιμοποιώντας τη λέξη-κλειδί `let`. Προς το παρόν δεν έχει τιμή.
1. **Αναθέστε μια τιμή**. Αποθηκεύστε μια τιμή σε μια μεταβλητή με τον τελεστή `=`, ακολουθούμενο από την αναμενόμενη τιμή.
@ -54,17 +54,17 @@ CO_OP_TRANSLATOR_METADATA:
myVariable = 123;
```
> Σημείωση: η χρήση του `=` σε αυτό το μάθημα σημαίνει ότι κάνουμε χρήση ενός "τελεστή ανάθεσης", που χρησιμοποιείται για να θέσει μια τιμή σε μια μεταβλητή. Δεν δηλώνει ισότητα.
> Σημείωση: η χρήση του `=` σε αυτό το μάθημα σημαίνει ότι χρησιμοποιούμε έναν "τελεστή ανάθεσης", που χρησιμοποιείται για να ορίσει μια τιμή σε μια μεταβλητή. Δεν δηλώνει ισότητα.
Η `myVariable` έχει τώρα *αρχικοποιηθεί* με την τιμή 123.
Η `myVariable` έχει πλέον *αρχικοποιηθεί* με την τιμή 123.
1. **Αναδιαμορφώστε**. Αντικαταστήστε τον κώδικα σας με την παρακάτω δήλωση.
1. **Αναδιαμορφώστε**. Αντικαταστήστε τον κώδικά σας με την παρακάτω δήλωση.
```javascript
let myVariable = 123;
```
Το παραπάνω ονομάζεται _ρητή αρχικοποίηση_ όταν μια μεταβλητή δηλώνεται και της ανατίθεται μια τιμή ταυτόχρονα.
Το παραπάνω ονομάζεται _ρητή αρχικοποίηση_, όταν μια μεταβλητή δηλώνεται και της ανατίθεται μια τιμή ταυτόχρονα.
1. **Αλλάξτε την τιμή της μεταβλητής**. Αλλάξτε την τιμή της μεταβλητής με τον εξής τρόπο:
@ -72,13 +72,13 @@ CO_OP_TRANSLATOR_METADATA:
myVariable = 321;
```
Μόλις δηλωθεί μια μεταβλητή, μπορείτε να αλλάξετε την τιμή της οποιαδήποτε στιγμή στον κώδικα σας με τον τελεστή `=` και τη νέα τιμή.
Μόλις δηλωθεί μια μεταβλητή, μπορείτε να αλλάξετε την τιμή της οποιαδήποτε στιγμή στον κώδικά σας με τον τελεστή `=` και τη νέα τιμή.
✅ Δοκιμάστε το! Μπορείτε να γράψετε JavaScript απευθείας στον περιηγητή σας. Ανοίξτε ένα παράθυρο περιηγητή και πλοηγηθείτε στα Εργαλεία Προγραμματιστή. Στην κονσόλα, θα βρείτε μια προτροπή. Πληκτρολογήστε `let myVariable = 123`, πατήστε επιστροφή και στη συνέχεια πληκτρολογήστε `myVariable`. Τι συμβαίνει; Σημειώστε ότι θα μάθετε περισσότερα για αυτές τις έννοιες σε επόμενα μαθήματα.
✅ Δοκιμάστε το! Μπορείτε να γράψετε JavaScript απευθείας στον περιηγητή σας. Ανοίξτε ένα παράθυρο περιηγητή και μεταβείτε στα Εργαλεία Προγραμματιστή. Στην κονσόλα, θα βρείτε μια προτροπή. Πληκτρολογήστε `let myVariable = 123`, πατήστε επιστροφή και στη συνέχεια πληκτρολογήστε `myVariable`. Τι συμβαίνει; Σημειώστε ότι θα μάθετε περισσότερα για αυτές τις έννοιες σε επόμενα μαθήματα.
## Σταθερές
Η δήλωση και η αρχικοποίηση μιας σταθεράς ακολουθεί τις ίδιες έννοιες με μια μεταβλητή, με την εξαίρεση της λέξης-κλειδί `const`. Οι σταθερές συνήθως δηλώνονται με όλα τα γράμματα κεφαλαία.
Η δήλωση και η αρχικοποίηση μιας σταθεράς ακολουθεί τις ίδιες έννοιες με μια μεταβλητή, με την εξαίρεση της λέξης-κλειδί `const`. Οι σταθερές δηλώνονται συνήθως με κεφαλαία γράμματα.
```javascript
const MY_VARIABLE = 123;
@ -86,7 +86,7 @@ const MY_VARIABLE = 123;
Οι σταθερές είναι παρόμοιες με τις μεταβλητές, με δύο εξαιρέσεις:
- **Πρέπει να έχουν τιμή**. Οι σταθερές πρέπει να αρχικοποιηθούν, αλλιώς θα προκύψει σφάλμα κατά την εκτέλεση του κώδικα.
- **Πρέπει να έχουν τιμή**. Οι σταθερές πρέπει να αρχικοποιούνται, αλλιώς θα προκύψει σφάλμα κατά την εκτέλεση του κώδικα.
- **Η αναφορά δεν μπορεί να αλλάξει**. Η αναφορά μιας σταθεράς δεν μπορεί να αλλάξει μόλις αρχικοποιηθεί, αλλιώς θα προκύψει σφάλμα κατά την εκτέλεση του κώδικα. Ας δούμε δύο παραδείγματα:
- **Απλή τιμή**. Το παρακάτω ΔΕΝ επιτρέπεται:
@ -102,7 +102,7 @@ const MY_VARIABLE = 123;
obj = { b: 5 } // not allowed
```
- **Η τιμή του αντικειμένου δεν προστατεύεται**. Το παρακάτω ΕΠΙΤΡΕΠΕΤΑΙ:
- **Η τιμή αντικειμένου δεν προστατεύεται**. Το παρακάτω ΕΠΙΤΡΕΠΕΤΑΙ:
```javascript
const obj = { a: 3 };
@ -111,51 +111,51 @@ const MY_VARIABLE = 123;
Στο παραπάνω αλλάζετε την τιμή του αντικειμένου αλλά όχι την ίδια την αναφορά, κάτι που το καθιστά επιτρεπτό.
> Σημείωση, ένα `const` σημαίνει ότι η αναφορά προστατεύεται από επαναπροσδιορισμό. Η τιμή όμως δεν είναι _αμετάβλητη_ και μπορεί να αλλάξει, ειδικά αν είναι μια σύνθετη δομή όπως ένα αντικείμενο.
> Σημείωση: μια `const` σημαίνει ότι η αναφορά προστατεύεται από επαναπροσδιορισμό. Ωστόσο, η τιμή δεν είναι _αμετάβλητη_ και μπορεί να αλλάξει, ειδικά αν είναι μια σύνθετη δομή όπως ένα αντικείμενο.
## Τύποι Δεδομένων
Οι μεταβλητές μπορούν να αποθηκεύουν πολλούς διαφορετικούς τύπους τιμών, όπως αριθμούς και κείμενο. Αυτοί οι διάφοροι τύποι τιμών είναι γνωστοί ως **τύποι δεδομένων**. Οι τύποι δεδομένων είναι ένα σημαντικό μέρος της ανάπτυξης λογισμικού, καθώς βοηθούν τους προγραμματιστές να λαμβάνουν αποφάσεις για το πώς πρέπει να γραφτεί ο κώδικας και πώς πρέπει να λειτουργεί το λογισμικό. Επιπλέον, ορισμένοι τύποι δεδομένων έχουν μοναδικά χαρακτηριστικά που βοηθούν στη μετατροπή ή την εξαγωγή πρόσθετων πληροφοριών από μια τιμή.
Οι μεταβλητές μπορούν να αποθηκεύουν πολλούς διαφορετικούς τύπους τιμών, όπως αριθμούς και κείμενο. Αυτοί οι διάφοροι τύποι τιμών είναι γνωστοί ως **τύποι δεδομένων**. Οι τύποι δεδομένων είναι ένα σημαντικό μέρος της ανάπτυξης λογισμικού, καθώς βοηθούν τους προγραμματιστές να αποφασίσουν πώς πρέπει να γραφτεί ο κώδικας και πώς πρέπει να λειτουργεί το λογισμικό. Επιπλέον, ορισμένοι τύποι δεδομένων έχουν μοναδικά χαρακτηριστικά που βοηθούν στη μετατροπή ή την εξαγωγή πρόσθετων πληροφοριών από μια τιμή.
Οι τύποι δεδομένων αναφέρονται επίσης ως πρωτόγονα δεδομένα της JavaScript, καθώς είναι οι χαμηλότερου επιπέδου τύποι δεδομένων που παρέχονται από τη γλώσσα. Υπάρχουν 7 πρωτόγονοι τύποι δεδομένων: string, number, bigint, boolean, undefined, null και symbol. Αφιερώστε ένα λεπτό για να οπτικοποιήσετε τι μπορεί να αντιπροσωπεύει κάθε ένας από αυτούς τους πρωτόγονους τύπους. Τι είναι ένα `zebra`; Τι γίνεται με το `0`; `true`;
Οι τύποι δεδομένων αναφέρονται επίσης ως πρωτόγονοι τύποι δεδομένων της JavaScript, καθώς είναι οι βασικότεροι τύποι δεδομένων που παρέχονται από τη γλώσσα. Υπάρχουν 7 πρωτόγονοι τύποι δεδομένων: string, number, bigint, boolean, undefined, null και symbol. Αφιερώστε ένα λεπτό για να οπτικοποιήσετε τι μπορεί να αντιπροσωπεύει ο καθένας από αυτούς τους τύπους. Τι είναι ένα `zebra`; Τι γίνεται με το `0`; Το `true`;
### Αριθμοί
Στην προηγούμενη ενότητα, η τιμή της `myVariable` ήταν ένας τύπος δεδομένων αριθμού.
Στην προηγούμενη ενότητα, η τιμή της `myVariable` ήταν τύπου δεδομένων αριθμός.
`let myVariable = 123;`
Οι μεταβλητές μπορούν να αποθηκεύουν όλους τους τύπους αριθμών, συμπεριλαμβανομένων των δεκαδικών ή των αρνητικών αριθμών. Οι αριθμοί μπορούν επίσης να χρησιμοποιηθούν με αριθμητικούς τελεστές, που καλύπτονται στην [επόμενη ενότητα](../../../../2-js-basics/1-data-types).
Οι μεταβλητές μπορούν να αποθηκεύουν όλους τους τύπους αριθμών, συμπεριλαμβανομένων δεκαδικών ή αρνητικών αριθμών. Οι αριθμοί μπορούν επίσης να χρησιμοποιηθούν με αριθμητικούς τελεστές, που καλύπτονται στην [επόμενη ενότητα](../../../../2-js-basics/1-data-types).
### Αριθμητικοί Τελεστές
Υπάρχουν διάφοροι τύποι τελεστών για χρήση κατά την εκτέλεση αριθμητικών λειτουργιών, και μερικοί παρατίθενται εδώ:
Υπάρχουν διάφοροι τύποι τελεστών για τη χρήση αριθμητικών λειτουργιών, και μερικοί από αυτούς παρατίθενται εδώ:
| Σύμβολο | Περιγραφή | Παράδειγμα |
| ------ | ------------------------------------------------------------------------ | -------------------------------- |
| `+` | **Πρόσθεση**: Υπολογίζει το άθροισμα δύο αριθμών | `1 + 2 //αναμενόμενη απάντηση είναι 3` |
| `-` | **Αφαίρεση**: Υπολογίζει τη διαφορά δύο αριθμών | `1 - 2 //αναμενόμενη απάντηση είναι -1` |
| `*` | **Πολλαπλασιασμός**: Υπολογίζει το γινόμενο δύο αριθμών | `1 * 2 //αναμενόμενη απάντηση είναι 2` |
| `/` | **Διαίρεση**: Υπολογίζει το πηλίκο δύο αριθμών | `1 / 2 //αναμενόμενη απάντηση είναι 0.5` |
| `%` | **Υπόλοιπο**: Υπολογίζει το υπόλοιπο από τη διαίρεση δύο αριθμών | `1 % 2 //αναμενόμενη απάντηση είναι 1` |
| ------ | --------------------------------------------------------------------- | ----------------------------------- |
| `+` | **Πρόσθεση**: Υπολογίζει το άθροισμα δύο αριθμών | `1 + 2 //αναμενόμενη απάντηση είναι 3` |
| `-` | **Αφαίρεση**: Υπολογίζει τη διαφορά δύο αριθμών | `1 - 2 //αναμενόμενη απάντηση είναι -1` |
| `*` | **Πολλαπλασιασμός**: Υπολογίζει το γινόμενο δύο αριθμών | `1 * 2 //αναμενόμενη απάντηση είναι 2` |
| `/` | **Διαίρεση**: Υπολογίζει το πηλίκο δύο αριθμών | `1 / 2 //αναμενόμενη απάντηση είναι 0.5` |
| `%` | **Υπόλοιπο**: Υπολογίζει το υπόλοιπο από τη διαίρεση δύο αριθμών | `1 % 2 //αναμενόμενη απάντηση είναι 1` |
✅ Δοκιμάστε το! Δοκιμάστε μια αριθμητική πράξη στην κονσόλα του περιηγητή σας. Σας εκπλήσσουν τα αποτελέσματα;
### Strings
### Συμβολοσειρές
Τα strings είναι σύνολα χαρακτήρων που βρίσκονται ανάμεσα σε μονά ή διπλά εισαγωγικά.
Οι συμβολοσειρές είναι σύνολα χαρακτήρων που βρίσκονται ανάμεσα σε μονά ή διπλά εισαγωγικά.
- `'Αυτό είναι ένα string'`
- `"Αυτό είναι επίσης ένα string"`
- `let myString = 'Αυτή είναι μια τιμή string αποθηκευμένη σε μια μεταβλητή';`
- `'Αυτή είναι μια συμβολοσειρά'`
- `"Αυτή είναι επίσης μια συμβολοσειρά"`
- `let myString = 'Αυτή είναι μια τιμή συμβολοσειράς αποθηκευμένη σε μια μεταβλητή';`
Θυμηθείτε να χρησιμοποιείτε εισαγωγικά όταν γράφετε ένα string, αλλιώς η JavaScript θα υποθέσει ότι είναι όνομα μεταβλητής.
Θυμηθείτε να χρησιμοποιείτε εισαγωγικά όταν γράφετε μια συμβολοσειρά, αλλιώς η JavaScript θα υποθέσει ότι είναι όνομα μεταβλητής.
### Μορφοποίηση Strings
### Μορφοποίηση Συμβολοσειρών
Τα strings είναι κείμενα και θα απαιτήσουν μορφοποίηση κατά καιρούς.
Οι συμβολοσειρές είναι κειμενικές και θα χρειαστούν μορφοποίηση κατά καιρούς.
Για να **συνενώσετε** δύο ή περισσότερα strings, ή να τα ενώσετε, χρησιμοποιήστε τον τελεστή `+`.
Για να **συνενώσετε** δύο ή περισσότερες συμβολοσειρές, ή να τις ενώσετε, χρησιμοποιήστε τον τελεστή `+`.
```javascript
let myString1 = "Hello";
@ -169,7 +169,7 @@ myString1 + ", " + myString2 + "!"; //Hello, World!
✅ Γιατί το `1 + 1 = 2` στη JavaScript, αλλά το `'1' + '1' = 11`; Σκεφτείτε το. Τι γίνεται με το `'1' + 1`;
**Template literals** είναι ένας άλλος τρόπος μορφοποίησης strings, εκτός από τα εισαγωγικά, χρησιμοποιείται το backtick. Οτιδήποτε δεν είναι απλό κείμενο πρέπει να τοποθετηθεί μέσα σε placeholders `${ }`. Αυτό περιλαμβάνει οποιεσδήποτε μεταβλητές που μπορεί να είναι strings.
**Template literals** είναι ένας άλλος τρόπος μορφοποίησης συμβολοσειρών, εκτός από τα εισαγωγικά, χρησιμοποιώντας το backtick. Οτιδήποτε δεν είναι απλό κείμενο πρέπει να τοποθετείται μέσα σε placeholders `${ }`. Αυτό περιλαμβάνει οποιεσδήποτε μεταβλητές που μπορεί να είναι συμβολοσειρές.
```javascript
let myString1 = "Hello";
@ -179,27 +179,27 @@ let myString2 = "World";
`${myString1}, ${myString2}!` //Hello, World!
```
Μπορείτε να επιτύχετε τους στόχους μορφοποίησης σας με οποιαδήποτε μέθοδο, αλλά τα template literals θα σεβαστούν τυχόν κενά και αλλαγές γραμμής.
Μπορείτε να επιτύχετε τους στόχους μορφοποίησής σας με οποιαδήποτε μέθοδο, αλλά τα template literals θα διατηρήσουν τυχόν κενά και αλλαγές γραμμής.
✅ Πότε θα χρησιμοποιούσατε ένα template literal αντί για ένα απλό string;
✅ Πότε θα χρησιμοποιούσατε ένα template literal αντί για μια απλή συμβολοσειρά;
### Booleans
Τα Booleans μπορούν να έχουν μόνο δύο τιμές: `true` ή `false`. Τα Booleans μπορούν να βοηθήσουν στη λήψη αποφάσεων για το ποιες γραμμές κώδικα πρέπει να εκτελεστούν όταν πληρούνται ορισμένες συνθήκες. Σε πολλές περιπτώσεις, οι [τελεστές](../../../../2-js-basics/1-data-types) βοηθούν στον καθορισμό της τιμής ενός Boolean και συχνά θα παρατηρήσετε και θα γράψετε μεταβλητές που αρχικοποιούνται ή οι τιμές τους ενημερώνονται με έναν τελεστή.
Τα Booleans μπορούν να έχουν μόνο δύο τιμές: `true` ή `false`. Τα Booleans μπορούν να βοηθήσουν στη λήψη αποφάσεων σχετικά με το ποιες γραμμές κώδικα πρέπει να εκτελούνται όταν πληρούνται ορισμένες συνθήκες. Σε πολλές περιπτώσεις, οι [τελεστές](../../../../2-js-basics/1-data-types) βοηθούν στον καθορισμό της τιμής ενός Boolean και συχνά θα παρατηρήσετε και θα γράφετε μεταβλητές που αρχικοποιούνται ή των οποίων οι τιμές ενημερώνονται με έναν τελεστή.
- `let myTrueBool = true`
- `let myFalseBool = false`
Μια μεταβλητή μπορεί να θεωρηθεί 'truthy' αν αξιολογείται ως boolean `true`. Ενδιαφέρον είναι ότι στη JavaScript, [όλες οι τιμές είναι truthy εκτός αν οριστούν ως falsy](https://developer.mozilla.org/docs/Glossary/Truthy).
Μια μεταβλητή μπορεί να θεωρηθεί 'truthy' αν αξιολογείται ως boolean `true`. Ενδιαφέρον είναι ότι στη JavaScript, [όλες οι τιμές είναι truthy εκτός αν ορίζονται ως falsy](https://developer.mozilla.org/docs/Glossary/Truthy).
---
## 🚀 Πρόκληση
Η JavaScript είναι γνωστή για τους εκπληκτικούς τρόπους χειρισμού των τύπων δεδομένων κατά καιρούς. Κάντε λίγη έρευνα για αυτά τα 'παγίδες'. Για παράδειγμα: η ευαισθησία σε πεζά-κεφαλαία μπορεί να σας μπερδέψει! Δοκιμάστε αυτό στην κονσόλα σας: `let age = 1; let Age = 2; age == Age` (αποδίδει `false` -- γιατί;). Τι άλλες παγίδες μπορείτε να βρείτε;
Η JavaScript είναι γνωστή για τους εκπληκτικούς τρόπους με τους οποίους χειρίζεται τους τύπους δεδομένων κατά καιρούς. Κάντε λίγη έρευνα για αυτά τα 'παγίδες'. Για παράδειγμα: η ευαισθησία πεζών-κεφαλαίων μπορεί να σας μπερδέψει! Δοκιμάστε αυτό στην κονσόλα σας: `let age = 1; let Age = 2; age == Age` (αποδίδει `false` -- γιατί;). Τι άλλες παγίδες μπορείτε να βρείτε;
## Ερωτήσεις μετά το μάθημα
[Ερωτήσεις μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/8)
## Κουίζ Μετά το Μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app)
## Ανασκόπηση & Αυτομελέτη
@ -207,7 +207,7 @@ let myString2 = "World";
## Εργασία
[Εξάσκηση στους Τύπους Δεδομένων](assignment.md)
[Άσκηση Τύπων Δεδομένων](assignment.md)
---

@ -1,23 +1,23 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "b4612bbb9ace984f374fcc80e3e035ad",
"translation_date": "2025-08-26T21:42:34+00:00",
"original_hash": "92e136090efc4341b1d51c37924c1802",
"translation_date": "2025-08-29T07:12:37+00:00",
"source_file": "2-js-basics/2-functions-methods/README.md",
"language_code": "el"
}
-->
# Βασικά στοιχεία JavaScript: Μέθοδοι και Συναρτήσεις
![JavaScript Basics - Functions](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b7605c36330ac42eeb5cd8ed02bcdd60fdac778174d6cb865.el.png)
![Βασικά στοιχεία JavaScript - Συναρτήσεις](../../../../translated_images/webdev101-js-functions.be049c4726e94f8b7605c36330ac42eeb5cd8ed02bcdd60fdac778174d6cb865.el.png)
> Σημειώσεις από [Tomomi Imura](https://twitter.com/girlie_mac)
## Ερωτηματολόγιο πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/9)
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app)
Όταν σκεφτόμαστε να γράψουμε κώδικα, θέλουμε πάντα να διασφαλίσουμε ότι είναι ευανάγνωστος. Παρόλο που αυτό μπορεί να ακούγεται αντιφατικό, ο κώδικας διαβάζεται πολύ περισσότερες φορές από όσες γράφεται. Ένα βασικό εργαλείο στο "οπλοστάσιο" ενός προγραμματιστή για να διασφαλίσει ότι ο κώδικας είναι συντηρήσιμος είναι η **συνάρτηση**.
Όταν σκεφτόμαστε να γράψουμε κώδικα, θέλουμε πάντα να διασφαλίσουμε ότι είναι ευανάγνωστος. Παρόλο που αυτό ακούγεται αντιφατικό, ο κώδικας διαβάζεται πολύ περισσότερες φορές από όσες γράφεται. Ένα βασικό εργαλείο στο οπλοστάσιο ενός προγραμματιστή για να διασφαλίσει ότι ο κώδικας είναι συντηρήσιμος είναι η **συνάρτηση**.
[![Methods and Functions](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Methods and Functions")
[![Μέθοδοι και Συναρτήσεις](https://img.youtube.com/vi/XgKsD6Zwvlc/0.jpg)](https://youtube.com/watch?v=XgKsD6Zwvlc "Μέθοδοι και Συναρτήσεις")
> 🎥 Κάντε κλικ στην εικόνα παραπάνω για ένα βίντεο σχετικά με τις μεθόδους και τις συναρτήσεις.
@ -27,7 +27,7 @@ CO_OP_TRANSLATOR_METADATA:
Στον πυρήνα της, μια συνάρτηση είναι ένα μπλοκ κώδικα που μπορούμε να εκτελέσουμε κατά παραγγελία. Αυτό είναι ιδανικό για σενάρια όπου χρειάζεται να εκτελέσουμε την ίδια εργασία πολλές φορές. Αντί να αντιγράφουμε τη λογική σε πολλαπλές τοποθεσίες (κάτι που θα δυσκόλευε την ενημέρωση όταν έρθει η ώρα), μπορούμε να την κεντροποιήσουμε σε μία τοποθεσία και να την καλούμε όποτε χρειάζεται να εκτελεστεί η λειτουργία - μπορούμε ακόμη και να καλούμε συναρτήσεις από άλλες συναρτήσεις!
Εξίσου σημαντική είναι η δυνατότητα να δώσουμε όνομα σε μια συνάρτηση. Παρόλο που αυτό μπορεί να φαίνεται ασήμαντο, το όνομα παρέχει έναν γρήγορο τρόπο τεκμηρίωσης ενός τμήματος κώδικα. Μπορείτε να το σκεφτείτε σαν μια ετικέτα σε ένα κουμπί. Αν κάνω κλικ σε ένα κουμπί που γράφει "Ακύρωση χρονομέτρησης", ξέρω ότι θα σταματήσει να τρέχει το χρονόμετρο.
Εξίσου σημαντική είναι η δυνατότητα να δώσουμε όνομα σε μια συνάρτηση. Παρόλο που αυτό μπορεί να φαίνεται ασήμαντο, το όνομα παρέχει έναν γρήγορο τρόπο τεκμηρίωσης ενός τμήματος του κώδικα. Μπορείτε να το σκεφτείτε σαν μια ετικέτα σε ένα κουμπί. Αν κάνω κλικ σε ένα κουμπί που γράφει "Ακύρωση χρονομέτρησης", ξέρω ότι θα σταματήσει να τρέχει το χρονόμετρο.
## Δημιουργία και κλήση συνάρτησης
@ -47,28 +47,28 @@ function displayGreeting() {
}
```
Όποτε θέλουμε να καλέσουμε (ή να ενεργοποιήσουμε) τη συνάρτηση μας, χρησιμοποιούμε το όνομα της συνάρτησης ακολουθούμενο από `()`. Αξίζει να σημειωθεί ότι η συνάρτηση μας μπορεί να οριστεί πριν ή μετά την απόφαση να την καλέσουμε. Ο μεταγλωττιστής της JavaScript θα την βρει για εσάς.
Όποτε θέλουμε να καλέσουμε (ή να ενεργοποιήσουμε) τη συνάρτησή μας, χρησιμοποιούμε το όνομα της συνάρτησης ακολουθούμενο από `()`. Αξίζει να σημειωθεί ότι η συνάρτησή μας μπορεί να οριστεί πριν ή μετά την απόφαση να την καλέσουμε. Ο μεταγλωττιστής της JavaScript θα την βρει για εσάς.
```javascript
// calling our function
displayGreeting();
```
> **NOTE:** Υπάρχει ένας ειδικός τύπος συνάρτησης γνωστός ως **μέθοδος**, τον οποίο ήδη χρησιμοποιείτε! Στην πραγματικότητα, το είδαμε στο παράδειγμα μας παραπάνω όταν χρησιμοποιήσαμε `console.log`. Αυτό που διαφοροποιεί μια μέθοδο από μια συνάρτηση είναι ότι η μέθοδος συνδέεται με ένα αντικείμενο (`console` στο παράδειγμα μας), ενώ η συνάρτηση είναι ανεξάρτητη. Θα ακούσετε πολλούς προγραμματιστές να χρησιμοποιούν αυτούς τους όρους εναλλακτικά.
> **NOTE:** Υπάρχει ένας ειδικός τύπος συνάρτησης γνωστός ως **μέθοδος**, τον οποίο ήδη χρησιμοποιείτε! Στην πραγματικότητα, το είδαμε στο παράδειγμά μας παραπάνω όταν χρησιμοποιήσαμε `console.log`. Αυτό που διαφοροποιεί μια μέθοδο από μια συνάρτηση είναι ότι η μέθοδος συνδέεται με ένα αντικείμενο (`console` στο παράδειγμά μας), ενώ η συνάρτηση είναι ανεξάρτητη. Θα ακούσετε πολλούς προγραμματιστές να χρησιμοποιούν αυτούς τους όρους εναλλακτικά.
### Καλές πρακτικές για συναρτήσεις
Υπάρχουν μερικές καλές πρακτικές που πρέπει να έχετε υπόψη όταν δημιουργείτε συναρτήσεις:
- Όπως πάντα, χρησιμοποιήστε περιγραφικά ονόματα ώστε να ξέρετε τι θα κάνει η συνάρτηση.
- Χρησιμοποιήστε **camelCasing** για να συνδυάσετε λέξεις.
- Κρατήστε τις συναρτήσεις σας επικεντρωμένες σε μια συγκεκριμένη εργασία.
- Όπως πάντα, χρησιμοποιήστε περιγραφικά ονόματα ώστε να ξέρετε τι κάνει η συνάρτηση
- Χρησιμοποιήστε **camelCasing** για να συνδυάσετε λέξεις
- Κρατήστε τις συναρτήσεις σας επικεντρωμένες σε μια συγκεκριμένη εργασία
## Μεταβίβαση πληροφοριών σε μια συνάρτηση
Για να κάνετε μια συνάρτηση πιο επαναχρησιμοποιήσιμη, συχνά θέλετε να της μεταβιβάσετε πληροφορίες. Αν σκεφτούμε το παράδειγμα `displayGreeting` παραπάνω, θα εμφανίζει μόνο **Hello, world!**. Δεν είναι η πιο χρήσιμη συνάρτηση που θα μπορούσε να δημιουργηθεί. Αν θέλουμε να την κάνουμε λίγο πιο ευέλικτη, όπως να επιτρέψουμε σε κάποιον να καθορίσει το όνομα του ατόμου που θα χαιρετήσει, μπορούμε να προσθέσουμε μια **παράμετρο**. Μια παράμετρος (που μερικές φορές ονομάζεται και **όρισμα**) είναι πρόσθετες πληροφορίες που στέλνονται σε μια συνάρτηση.
Για να κάνετε μια συνάρτηση πιο επαναχρησιμοποιήσιμη, συχνά θέλετε να της μεταβιβάσετε πληροφορίες. Αν εξετάσουμε το παράδειγμα `displayGreeting` παραπάνω, θα εμφανίζει μόνο **Hello, world!**. Όχι και η πιο χρήσιμη συνάρτηση που θα μπορούσε να δημιουργηθεί. Αν θέλουμε να την κάνουμε λίγο πιο ευέλικτη, όπως να επιτρέψουμε σε κάποιον να καθορίσει το όνομα του ατόμου που θα χαιρετήσει, μπορούμε να προσθέσουμε μια **παράμετρο**. Μια παράμετρος (που μερικές φορές ονομάζεται και **όρισμα**) είναι πρόσθετες πληροφορίες που στέλνονται σε μια συνάρτηση.
Οι παράμετροι αναφέρονται στο τμήμα ορισμού μέσα σε παρενθέσεις και χωρίζονται με κόμμα όπως φαίνεται παρακάτω:
Οι παράμετροι αναφέρονται στο τμήμα ορισμού μέσα σε παρενθέσεις και χωρίζονται με κόμμα, όπως φαίνεται παρακάτω:
```javascript
function name(param, param2, param3) {
@ -85,7 +85,7 @@ function displayGreeting(name) {
}
```
Όταν θέλουμε να καλέσουμε τη συνάρτηση μας και να περάσουμε την παράμετρο, την καθορίζουμε μέσα στις παρενθέσεις.
Όταν θέλουμε να καλέσουμε τη συνάρτηση και να περάσουμε την παράμετρο, την καθορίζουμε μέσα στις παρενθέσεις.
```javascript
displayGreeting('Christopher');
@ -94,7 +94,7 @@ displayGreeting('Christopher');
## Προεπιλεγμένες τιμές
Μπορούμε να κάνουμε τη συνάρτηση μας ακόμη πιο ευέλικτη προσθέτοντας περισσότερες παραμέτρους. Αλλά τι γίνεται αν δεν θέλουμε να απαιτείται κάθε τιμή να καθορίζεται; Συνεχίζοντας με το παράδειγμα του χαιρετισμού, θα μπορούσαμε να αφήσουμε το όνομα ως απαραίτητο (χρειαζόμαστε να ξέρουμε ποιον χαιρετάμε), αλλά να επιτρέψουμε ο χαιρετισμός να προσαρμόζεται όπως επιθυμεί κάποιος. Αν κάποιος δεν θέλει να τον προσαρμόσει, παρέχουμε μια προεπιλεγμένη τιμή. Για να παρέχουμε μια προεπιλεγμένη τιμή σε μια παράμετρο, την ορίζουμε με τον ίδιο τρόπο που ορίζουμε μια τιμή για μια μεταβλητή - `parameterName = 'defaultValue'`. Για να δείτε ένα πλήρες παράδειγμα:
Μπορούμε να κάνουμε τη συνάρτησή μας ακόμη πιο ευέλικτη προσθέτοντας περισσότερες παραμέτρους. Αλλά τι γίνεται αν δεν θέλουμε να απαιτείται κάθε τιμή να καθορίζεται; Συνεχίζοντας με το παράδειγμα του χαιρετισμού, θα μπορούσαμε να αφήσουμε το όνομα ως απαραίτητο (χρειαζόμαστε να ξέρουμε ποιον χαιρετάμε), αλλά να επιτρέψουμε ο χαιρετισμός να προσαρμόζεται όπως επιθυμεί κάποιος. Αν κάποιος δεν θέλει να τον προσαρμόσει, παρέχουμε μια προεπιλεγμένη τιμή. Για να παρέχουμε μια προεπιλεγμένη τιμή σε μια παράμετρο, την ορίζουμε όπως ακριβώς ορίζουμε μια τιμή για μια μεταβλητή - `parameterName = 'defaultValue'`. Για να δείτε ένα πλήρες παράδειγμα:
```javascript
function displayGreeting(name, salutation='Hello') {
@ -116,15 +116,15 @@ displayGreeting('Christopher', 'Hi');
Μέχρι τώρα, η συνάρτηση που δημιουργήσαμε θα εμφανίζει πάντα αποτελέσματα στην [κονσόλα](https://developer.mozilla.org/docs/Web/API/console). Μερικές φορές αυτό μπορεί να είναι ακριβώς αυτό που ψάχνουμε, ειδικά όταν δημιουργούμε συναρτήσεις που θα καλούν άλλες υπηρεσίες. Αλλά τι γίνεται αν θέλω να δημιουργήσω μια βοηθητική συνάρτηση για να εκτελέσω έναν υπολογισμό και να παρέχω την τιμή πίσω ώστε να μπορώ να τη χρησιμοποιήσω αλλού;
Μπορούμε να το κάνουμε αυτό χρησιμοποιώντας μια **τιμή επιστροφής**. Μια τιμή επιστροφής επιστρέφεται από τη συνάρτηση και μπορεί να αποθηκευτεί σε μια μεταβλητή με τον ίδιο τρόπο που θα μπορούσαμε να αποθηκεύσουμε μια στατική τιμή όπως μια συμβολοσειρά ή έναν αριθμό.
Μπορούμε να το κάνουμε αυτό χρησιμοποιώντας μια **τιμή επιστροφής**. Μια τιμή επιστροφής επιστρέφεται από τη συνάρτηση και μπορεί να αποθηκευτεί σε μια μεταβλητή όπως ακριβώς θα μπορούσαμε να αποθηκεύσουμε μια στατική τιμή, όπως μια συμβολοσειρά ή έναν αριθμό.
Αν μια συνάρτηση επιστρέφει κάτι, τότε χρησιμοποιείται η λέξη-κλειδί `return`. Η λέξη-κλειδί `return` αναμένει μια τιμή ή αναφορά αυτού που επιστρέφεται όπως φαίνεται παρακάτω:
Αν μια συνάρτηση επιστρέφει κάτι, τότε χρησιμοποιείται η λέξη-κλειδί `return`. Η λέξη-κλειδί `return` αναμένει μια τιμή ή αναφορά αυτού που επιστρέφεται, όπως φαίνεται παρακάτω:
```javascript
return myVariable;
```
Μπορούμε να δημιουργήσουμε μια συνάρτηση για να δημιουργήσουμε ένα μήνυμα χαιρετισμού και να επιστρέψουμε την τιμή πίσω στον καλούντα.
Θα μπορούσαμε να δημιουργήσουμε μια συνάρτηση για να δημιουργήσουμε ένα μήνυμα χαιρετισμού και να επιστρέψουμε την τιμή πίσω στον καλούντα.
```javascript
function createGreetingMessage(name) {
@ -157,7 +157,7 @@ setTimeout(displayDone, 3000);
### Ανώνυμες συναρτήσεις
Ας ρίξουμε μια άλλη ματιά σε αυτό που έχουμε δημιουργήσει. Δημιουργούμε μια συνάρτηση με ένα όνομα που θα χρησιμοποιηθεί μόνο μία φορά. Καθώς η εφαρμογή μας γίνεται πιο περίπλοκη, μπορούμε να δούμε ότι δημιουργούμε πολλές συναρτήσεις που θα καλούνται μόνο μία φορά. Αυτό δεν είναι ιδανικό. Όπως αποδεικνύεται, δεν χρειάζεται πάντα να δώσουμε ένα όνομα!
Ας ρίξουμε μια άλλη ματιά σε αυτό που έχουμε δημιουργήσει. Δημιουργούμε μια συνάρτηση με ένα όνομα που θα χρησιμοποιηθεί μία φορά. Καθώς η εφαρμογή μας γίνεται πιο περίπλοκη, μπορούμε να δούμε ότι δημιουργούμε πολλές συναρτήσεις που θα καλούνται μόνο μία φορά. Αυτό δεν είναι ιδανικό. Όπως αποδεικνύεται, δεν χρειάζεται πάντα να παρέχουμε ένα όνομα!
Όταν περνάμε μια συνάρτηση ως παράμετρο, μπορούμε να παρακάμψουμε τη δημιουργία της εκ των προτέρων και να την κατασκευάσουμε ως μέρος της παραμέτρου. Χρησιμοποιούμε την ίδια λέξη-κλειδί `function`, αλλά την κατασκευάζουμε ως παράμετρο.
@ -173,7 +173,7 @@ setTimeout(function() {
### Συναρτήσεις με βέλη (Fat arrow functions)
Ένα σύντομο κόλπο που είναι κοινό σε πολλές γλώσσες προγραμματισμού (συμπεριλαμβανομένης της JavaScript) είναι η δυνατότητα χρήσης αυτού που ονομάζεται **arrow** ή **fat arrow** συνάρτηση. Χρησιμοποιεί έναν ειδικό δείκτη `=>`, που μοιάζει με βέλος - εξού και το όνομα! Χρησιμοποιώντας το `=>`, μπορούμε να παραλείψουμε τη λέξη-κλειδί `function`.
Ένα σύντομο κόλπο που είναι κοινό σε πολλές γλώσσες προγραμματισμού (συμπεριλαμβανομένης της JavaScript) είναι η δυνατότητα χρήσης αυτού που ονομάζεται **arrow** ή **fat arrow** συνάρτηση. Χρησιμοποιεί έναν ειδικό δείκτη `=>`, που μοιάζει με βέλος - εξ ου και το όνομα! Χρησιμοποιώντας το `=>`, μπορούμε να παραλείψουμε τη λέξη-κλειδί `function`.
Ας ξαναγράψουμε τον κώδικα μας μία ακόμη φορά για να χρησιμοποιήσουμε μια συνάρτηση με βέλος:
@ -185,7 +185,7 @@ setTimeout(() => {
### Πότε να χρησιμοποιείτε κάθε στρατηγική
Τώρα έχετε δει ότι έχουμε τρεις τρόπους να περάσουμε μια συνάρτηση ως παράμετρο και ίσως αναρωτιέστε πότε να χρησιμοποιήσετε τον καθένα. Αν ξέρετε ότι θα χρησιμοποιείτε τη συνάρτηση περισσότερες από μία φορές, δημιουργήστε την κανονικά. Αν θα τη χρησιμοποιείτε μόνο για μία τοποθεσία, είναι γενικά καλύτερο να χρησιμοποιείτε μια ανώνυμη συνάρτηση. Το αν θα χρησιμοποιήσετε μια συνάρτηση με βέλος ή τη πιο παραδοσιακή σύνταξη `function` εξαρτάται από εσάς, αλλά θα παρατηρήσετε ότι οι περισσότεροι σύγχρονοι προγραμματιστές προτιμούν το `=>`.
Τώρα έχετε δει ότι έχουμε τρεις τρόπους να περάσουμε μια συνάρτηση ως παράμετρο και ίσως αναρωτιέστε πότε να χρησιμοποιείτε τον καθένα. Αν ξέρετε ότι θα χρησιμοποιείτε τη συνάρτηση περισσότερες από μία φορές, δημιουργήστε την κανονικά. Αν θα τη χρησιμοποιείτε μόνο για μία τοποθεσία, είναι γενικά καλύτερο να χρησιμοποιείτε μια ανώνυμη συνάρτηση. Το αν θα χρησιμοποιήσετε μια συνάρτηση με βέλος ή την πιο παραδοσιακή σύνταξη `function` εξαρτάται από εσάς, αλλά θα παρατηρήσετε ότι οι περισσότεροι σύγχρονοι προγραμματιστές προτιμούν το `=>`.
---
@ -194,11 +194,11 @@ setTimeout(() => {
Μπορείτε να εξηγήσετε με μία πρόταση τη διαφορά μεταξύ συναρτήσεων και μεθόδων; Δοκιμάστε το!
## Ερωτηματολόγιο μετά το μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/10)
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app)
## Ανασκόπηση & Αυτομελέτη
Αξίζει να [διαβάσετε λίγο περισσότερο για τις συναρτήσεις με βέλη](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), καθώς χρησιμοποιούνται όλο και περισσότερο σε βάσεις κώδικα. Εξασκηθείτε γράφοντας μια συνάρτηση και στη συνέχεια ξαναγράψτε την με αυτή τη σύνταξη.
Αξίζει [να διαβάσετε λίγο περισσότερο για τις συναρτήσεις με βέλη](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), καθώς χρησιμοποιούνται όλο και περισσότερο σε βάσεις κώδικα. Εξασκηθείτε γράφοντας μια συνάρτηση και στη συνέχεια ξαναγράψτε την με αυτή τη σύνταξη.
## Εργασία
@ -206,5 +206,5 @@ setTimeout(() => {
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,59 +1,59 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "888609c48329c280ca2477d2df40f2e5",
"translation_date": "2025-08-26T21:39:51+00:00",
"original_hash": "f7009631b73556168ca435120a231c98",
"translation_date": "2025-08-29T07:13:28+00:00",
"source_file": "2-js-basics/3-making-decisions/README.md",
"language_code": "el"
}
-->
# Βασικά στοιχεία JavaScript: Λήψη αποφάσεων
# Βασικά Στοιχεία JavaScript: Λήψη Αποφάσεων
![Βασικά στοιχεία JavaScript - Λήψη αποφάσεων](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0b1cb2f8adaff3ed2a77c4f91db96d8a0594132a353fa189a.el.png)
![Βασικά Στοιχεία JavaScript - Λήψη Αποφάσεων](../../../../translated_images/webdev101-js-decisions.69e1b20f272dd1f0b1cb2f8adaff3ed2a77c4f91db96d8a0594132a353fa189a.el.png)
> Σημειώσεις από [Tomomi Imura](https://twitter.com/girlie_mac)
> Σκίτσο από την [Tomomi Imura](https://twitter.com/girlie_mac)
## Ερωτηματολόγιο πριν το μάθημα
## Κουίζ Πριν το Μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/11)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/11)
Η λήψη αποφάσεων και ο έλεγχος της σειράς εκτέλεσης του κώδικα καθιστούν τον κώδικα επαναχρησιμοποιήσιμο και ανθεκτικό. Αυτή η ενότητα καλύπτει τη σύνταξη για τον έλεγχο της ροής δεδομένων στη JavaScript και τη σημασία της όταν χρησιμοποιείται με τύπους δεδομένων Boolean.
Η λήψη αποφάσεων και ο έλεγχος της σειράς εκτέλεσης του κώδικά σας καθιστούν τον κώδικα επαναχρησιμοποιήσιμο και ανθεκτικό. Αυτή η ενότητα καλύπτει τη σύνταξη για τον έλεγχο της ροής δεδομένων στη JavaScript και τη σημασία της όταν χρησιμοποιείται με Boolean τύπους δεδομένων.
[![Λήψη αποφάσεων](https://img.youtube.com/vi/SxTp8j-fMMY/0.jpg)](https://youtube.com/watch?v=SxTp8j-fMMY "Λήψη αποφάσεων")
[![Λήψη Αποφάσεων](https://img.youtube.com/vi/SxTp8j-fMMY/0.jpg)](https://youtube.com/watch?v=SxTp8j-fMMY "Λήψη Αποφάσεων")
> 🎥 Κάντε κλικ στην εικόνα παραπάνω για ένα βίντεο σχετικά με τη λήψη αποφάσεων.
> 🎥 Κάντε κλικ στην παραπάνω εικόνα για ένα βίντεο σχετικά με τη λήψη αποφάσεων.
> Μπορείτε να παρακολουθήσετε αυτό το μάθημα στο [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-if-else/?WT.mc_id=academic-77807-sagibbon)!
## Σύντομη ανακεφαλαίωση για τα Booleans
## Μια Σύντομη Ανακεφαλαίωση για τα Booleans
Τα Booleans μπορούν να έχουν μόνο δύο τιμές: `true` ή `false`. Τα Booleans βοηθούν στη λήψη αποφάσεων σχετικά με το ποιες γραμμές κώδικα πρέπει να εκτελεστούν όταν πληρούνται ορισμένες συνθήκες.
Τα Booleans μπορούν να έχουν μόνο δύο τιμές: `true` ή `false`. Τα Booleans βοηθούν στη λήψη αποφάσεων για το ποιες γραμμές κώδικα θα εκτελεστούν όταν πληρούνται ορισμένες συνθήκες.
Ορίστε το Boolean σας ως true ή false όπως παρακάτω:
Ορίστε το boolean σας ως true ή false όπως παρακάτω:
`let myTrueBool = true`
`let myFalseBool = false`
Τα Booleans πήραν το όνομά τους από τον Άγγλο μαθηματικό, φιλόσοφο και λογικό George Boole (18151864).
## Τελεστές σύγκρισης και Booleans
## Τελεστές Σύγκρισης και Booleans
Οι τελεστές χρησιμοποιούνται για την αξιολόγηση συνθηκών μέσω συγκρίσεων που δημιουργούν μια Boolean τιμή. Ακολουθεί μια λίστα με τελεστές που χρησιμοποιούνται συχνά.
Οι τελεστές χρησιμοποιούνται για την αξιολόγηση συνθηκών κάνοντας συγκρίσεις που θα δημιουργήσουν μια Boolean τιμή. Ακολουθεί μια λίστα με τελεστές που χρησιμοποιούνται συχνά.
| Σύμβολο | Περιγραφή | Παράδειγμα |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `<` | **Μικρότερο από**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μικρότερη από την τιμή στα δεξιά | `5 < 6 // true` |
| `<=` | **Μικρότερο ή ίσο με**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μικρότερη ή ίση με την τιμή στα δεξιά | `5 <= 6 // true` |
| `>` | **Μεγαλύτερο από**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μεγαλύτερη από την τιμή στα δεξιά | `5 > 6 // false` |
| `>=` | **Μεγαλύτερο ή ίσο με**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μεγαλύτερη ή ίση με την τιμή στα δεξιά | `5 >= 6 // false` |
| `===` | **Αυστηρή ισότητα**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν οι τιμές στα δεξιά και αριστερά είναι ίσες ΚΑΙ του ίδιου τύπου δεδομένων | `5 === 6 // false` |
| `!==` | **Ανισότητα**: Συγκρίνει δύο τιμές και επιστρέφει την αντίθετη Boolean τιμή από αυτή που θα επέστρεφε ο τελεστής αυστηρής ισότητας | `5 !== 6 // true` |
| `<` | **Μικρότερο από**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μικρότερη από τη δεξιά | `5 < 6 // true` |
| `<=` | **Μικρότερο ή ίσο με**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μικρότερη ή ίση με τη δεξιά | `5 <= 6 // true` |
| `>` | **Μεγαλύτερο από**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μεγαλύτερη από τη δεξιά | `5 > 6 // false` |
| `>=` | **Μεγαλύτερο ή ίσο με**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν η τιμή στα αριστερά είναι μεγαλύτερη ή ίση με τη δεξιά | `5 >= 6 // false` |
| `===` | **Αυστηρή ισότητα**: Συγκρίνει δύο τιμές και επιστρέφει την Boolean τιμή `true` αν οι τιμές στα δεξιά και αριστερά είναι ίσες ΚΑΙ είναι του ίδιου τύπου δεδομένων | `5 === 6 // false` |
| `!==` | **Ανισότητα**: Συγκρίνει δύο τιμές και επιστρέφει την αντίθετη Boolean τιμή από αυτή που θα επέστρεφε ο τελεστής αυστηρής ισότητας | `5 !== 6 // true` |
✅ Ελέγξτε τις γνώσεις σας γράφοντας κάποιες συγκρίσεις στην κονσόλα του προγράμματος περιήγησης. Σας εκπλήσσει κάποιο από τα δεδομένα που επιστρέφονται;
✅ Ελέγξτε τις γνώσεις σας γράφοντας μερικές συγκρίσεις στην κονσόλα του προγράμματος περιήγησής σας. Σας εκπλήσσει κάποιο από τα δεδομένα που επιστρέφονται;
## Δήλωση If
Η δήλωση if θα εκτελέσει τον κώδικα που βρίσκεται μέσα στα μπλοκ της αν η συνθήκη είναι αληθής.
Η δήλωση if θα εκτελέσει τον κώδικα που βρίσκεται ανάμεσα στα μπλοκ της αν η συνθήκη είναι true.
```javascript
if (condition) {
@ -75,7 +75,7 @@ if (currentMoney >= laptopPrice) {
## Δήλωση If..Else
Η δήλωση `else` θα εκτελέσει τον κώδικα που βρίσκεται μέσα στα μπλοκ της όταν η συνθήκη είναι ψευδής. Είναι προαιρετική με μια δήλωση `if`.
Η δήλωση `else` θα εκτελέσει τον κώδικα που βρίσκεται ανάμεσα στα μπλοκ της όταν η συνθήκη είναι false. Είναι προαιρετική με μια δήλωση `if`.
```javascript
let currentMoney;
@ -90,7 +90,7 @@ if (currentMoney >= laptopPrice) {
}
```
Ελέγξτε την κατανόησή σας για αυτόν τον κώδικα και τον παρακάτω κώδικα εκτελώντας τον στην κονσόλα του προγράμματος περιήγησης. Αλλάξτε τις τιμές των μεταβλητών currentMoney και laptopPrice για να αλλάξετε το αποτέλεσμα του `console.log()`.
Δοκιμάστε την κατανόησή σας για αυτόν τον κώδικα και τον παρακάτω κώδικα εκτελώντας τον στην κονσόλα ενός προγράμματος περιήγησης. Αλλάξτε τις τιμές των μεταβλητών currentMoney και laptopPrice για να αλλάξετε το αποτέλεσμα του `console.log()`.
## Δήλωση Switch
@ -127,19 +127,19 @@ switch (a) {
console.log(`The value is ${a}`);
```
Ελέγξτε την κατανόησή σας για αυτόν τον κώδικα και τον παρακάτω κώδικα εκτελώντας τον στην κονσόλα του προγράμματος περιήγησης. Αλλάξτε τις τιμές της μεταβλητής a για να αλλάξετε το αποτέλεσμα του `console.log()`.
Δοκιμάστε την κατανόησή σας για αυτόν τον κώδικα και τον παρακάτω κώδικα εκτελώντας τον στην κονσόλα ενός προγράμματος περιήγησης. Αλλάξτε τις τιμές της μεταβλητής a για να αλλάξετε το αποτέλεσμα του `console.log()`.
## Λογικοί τελεστές και Booleans
## Λογικοί Τελεστές και Booleans
Οι αποφάσεις μπορεί να απαιτούν περισσότερες από μία συγκρίσεις και μπορούν να συνδυαστούν με λογικούς τελεστές για να παράγουν μια Boolean τιμή.
Οι αποφάσεις μπορεί να απαιτούν περισσότερες από μία συγκρίσεις και μπορούν να συνδυαστούν με λογικούς τελεστές για να παραχθεί μια Boolean τιμή.
| Σύμβολο | Περιγραφή | Παράδειγμα |
| ------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `&&` | **Λογικό AND**: Συγκρίνει δύο Boolean εκφράσεις. Επιστρέφει true **μόνο** αν και οι δύο πλευρές είναι αληθείς | `(5 > 6) && (5 < 6 ) //Μία πλευρά είναι ψευδής, η άλλη αληθής. Επιστρέφει false` |
| `\|\|` | **Λογικό OR**: Συγκρίνει δύο Boolean εκφράσεις. Επιστρέφει true αν τουλάχιστον μία πλευρά είναι αληθής | `(5 > 6) \|\| (5 < 6) //Μία πλευρά είναι ψευδής, η άλλη αληθής. Επιστρέφει true` |
| `!` | **Λογικό NOT**: Επιστρέφει την αντίθετη τιμή μιας Boolean έκφρασης | `!(5 > 6) // 5 δεν είναι μεγαλύτερο από 6, αλλά το "!" θα επιστρέψει true` |
| `&&` | **Λογικό AND**: Συγκρίνει δύο Boolean εκφράσεις. Επιστρέφει true **μόνο** αν και οι δύο πλευρές είναι true | `(5 > 6) && (5 < 6 ) //Μία πλευρά είναι false, η άλλη είναι true. Επιστρέφει false` |
| `\|\|` | **Λογικό OR**: Συγκρίνει δύο Boolean εκφράσεις. Επιστρέφει true αν τουλάχιστον μία πλευρά είναι true | `(5 > 6) \|\| (5 < 6) //Μία πλευρά είναι false, η άλλη είναι true. Επιστρέφει true` |
| `!` | **Λογικό NOT**: Επιστρέφει την αντίθετη τιμή μιας Boolean έκφρασης | `!(5 > 6) // 5 δεν είναι μεγαλύτερο από 6, αλλά το "!" θα επιστρέψει true` |
## Συνθήκες και αποφάσεις με λογικούς τελεστές
## Συνθήκες και Αποφάσεις με Λογικούς Τελεστές
Οι λογικοί τελεστές μπορούν να χρησιμοποιηθούν για τη δημιουργία συνθηκών σε δηλώσεις if..else.
@ -157,9 +157,9 @@ if (currentMoney >= laptopPrice || currentMoney >= laptopDiscountPrice) {
}
```
### Τελεστής άρνησης
### Τελεστής Άρνησης
Έχετε δει μέχρι τώρα πώς μπορείτε να χρησιμοποιήσετε μια δήλωση `if...else` για να δημιουργήσετε λογική συνθηκών. Οτιδήποτε μπαίνει σε μια δήλωση `if` πρέπει να αξιολογείται ως true/false. Χρησιμοποιώντας τον τελεστή `!` μπορείτε να _αρνηθείτε_ την έκφραση. Θα μοιάζει κάπως έτσι:
Μέχρι τώρα έχετε δει πώς μπορείτε να χρησιμοποιήσετε μια δήλωση `if...else` για να δημιουργήσετε λογική συνθηκών. Οτιδήποτε εισάγεται σε μια δήλωση `if` πρέπει να αξιολογείται ως true/false. Χρησιμοποιώντας τον τελεστή `!` μπορείτε να _αντιστρέψετε_ την έκφραση. Θα μοιάζει κάπως έτσι:
```javascript
if (!condition) {
@ -169,9 +169,9 @@ if (!condition) {
}
```
### Τριαδικές εκφράσεις
### Τριαδικές Εκφράσεις
Η δήλωση `if...else` δεν είναι ο μόνος τρόπος για να εκφράσετε λογική αποφάσεων. Μπορείτε επίσης να χρησιμοποιήσετε κάτι που ονομάζεται τριαδικός τελεστής. Η σύνταξή του μοιάζει με την εξής:
Η δήλωση `if...else` δεν είναι ο μόνος τρόπος για να εκφράσετε λογική αποφάσεων. Μπορείτε επίσης να χρησιμοποιήσετε κάτι που ονομάζεται τριαδικός τελεστής. Η σύνταξή του μοιάζει κάπως έτσι:
```javascript
let variable = condition ? <return this if true> : <return this if false>
@ -212,15 +212,15 @@ if (firstNumber > secondNumber) {
---
## Ερωτηματολόγιο μετά το μάθημα
## Κουίζ Μετά το Μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/12)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/12)
## Ανασκόπηση & Αυτομελέτη
Διαβάστε περισσότερα για τους πολλούς διαθέσιμους τελεστές [στο MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Διαβάστε περισσότερα για τους πολλούς τελεστές που είναι διαθέσιμοι στον χρήστη [στο MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Δείτε το υπέροχο [operator lookup](https://joshwcomeau.com/operator-lookup/) του Josh Comeau!
Δείτε τον υπέροχο [οδηγό τελεστών](https://joshwcomeau.com/operator-lookup/) του Josh Comeau!
## Εργασία
@ -228,5 +228,5 @@ if (firstNumber > secondNumber) {
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "3f7f87871312cf6cc12662da7d973182",
"translation_date": "2025-08-26T21:45:32+00:00",
"original_hash": "9029f96b0e034839c1799f4595e4bb66",
"translation_date": "2025-08-29T07:14:51+00:00",
"source_file": "2-js-basics/4-arrays-loops/README.md",
"language_code": "el"
}
@ -12,7 +12,7 @@ CO_OP_TRANSLATOR_METADATA:
![JavaScript Basics - Arrays](../../../../translated_images/webdev101-js-arrays.439d7528b8a294558d0e4302e448d193f8ad7495cc407539cc81f1afe904b470.el.png)
> Σκίτσο από την [Tomomi Imura](https://twitter.com/girlie_mac)
## Κουίζ πριν το μάθημα
## Κουίζ Πριν το Μάθημα
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/13)
Αυτό το μάθημα καλύπτει τα βασικά της JavaScript, της γλώσσας που προσφέρει διαδραστικότητα στον ιστό. Σε αυτό το μάθημα, θα μάθετε για τους πίνακες και τους βρόχους, που χρησιμοποιούνται για τη διαχείριση δεδομένων.
@ -27,11 +27,11 @@ CO_OP_TRANSLATOR_METADATA:
## Πίνακες
Η εργασία με δεδομένα είναι μια συνηθισμένη εργασία για κάθε γλώσσα, και γίνεται πολύ πιο εύκολη όταν τα δεδομένα είναι οργανωμένα σε μια δομή, όπως οι πίνακες. Με τους πίνακες, τα δεδομένα αποθηκεύονται σε μια δομή παρόμοια με λίστα. Ένα μεγάλο πλεονέκτημα των πινάκων είναι ότι μπορείτε να αποθηκεύσετε διαφορετικούς τύπους δεδομένων σε έναν πίνακα.
Η εργασία με δεδομένα είναι μια συνηθισμένη εργασία για κάθε γλώσσα, και γίνεται πολύ πιο εύκολη όταν τα δεδομένα είναι οργανωμένα σε μια δομημένη μορφή, όπως οι πίνακες. Με τους πίνακες, τα δεδομένα αποθηκεύονται σε μια δομή παρόμοια με λίστα. Ένα μεγάλο πλεονέκτημα των πινάκων είναι ότι μπορείτε να αποθηκεύσετε διαφορετικούς τύπους δεδομένων σε έναν πίνακα.
Οι πίνακες είναι παντού γύρω μας! Μπορείτε να σκεφτείτε ένα παράδειγμα πίνακα από την καθημερινή ζωή, όπως μια σειρά από ηλιακούς συλλέκτες;
Οι πίνακες είναι παντού γύρω μας! Μπορείτε να σκεφτείτε ένα παράδειγμα από την καθημερινή ζωή, όπως μια σειρά από ηλιακούς συλλέκτες;
Η σύνταξη για έναν πίνακα είναι ένα ζευγάρι αγκύλες.
Η σύνταξη για έναν πίνακα είναι ένα ζεύγος αγκυλών.
```javascript
let myArray = [];
@ -73,11 +73,11 @@ let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky
iceCreamFlavors.length; //5
```
✅ Δοκιμάστε το μόνοι σας! Χρησιμοποιήστε την κονσόλα του προγράμματος περιήγησής σας για να δημιουργήσετε και να διαχειριστείτε έναν πίνακα της δικής σας δημιουργίας.
✅ Δοκιμάστε το μόνοι σας! Χρησιμοποιήστε την κονσόλα του προγράμματος περιήγησης για να δημιουργήσετε και να διαχειριστείτε έναν πίνακα της δικής σας δημιουργίας.
## Βρόχοι
Οι βρόχοι μας επιτρέπουν να εκτελούμε επαναλαμβανόμενες ή **επανειλημμένες** εργασίες, εξοικονομώντας χρόνο και κώδικα. Κάθε επανάληψη μπορεί να διαφέρει στις μεταβλητές, τις τιμές και τις συνθήκες της. Υπάρχουν διαφορετικοί τύποι βρόχων στη JavaScript, και όλοι έχουν μικρές διαφορές, αλλά ουσιαστικά κάνουν το ίδιο πράγμα: επαναλαμβάνουν δεδομένα.
Οι βρόχοι μας επιτρέπουν να εκτελούμε επαναλαμβανόμενες ή **επικαλυπτόμενες** εργασίες, και μπορούν να εξοικονομήσουν πολύ χρόνο και κώδικα. Κάθε επανάληψη μπορεί να διαφέρει στις μεταβλητές, τις τιμές και τις συνθήκες της. Υπάρχουν διαφορετικοί τύποι βρόχων στη JavaScript, και όλοι έχουν μικρές διαφορές, αλλά ουσιαστικά κάνουν το ίδιο πράγμα: επαναλαμβάνουν δεδομένα.
### Βρόχος For
@ -108,7 +108,7 @@ while (i < 10) {
}
```
✅ Γιατί θα επιλέγατε έναν βρόχο for αντί για έναν βρόχο while; 17.000 χρήστες είχαν την ίδια ερώτηση στο StackOverflow, και μερικές από τις απόψεις [μπορεί να σας φανούν ενδιαφέρουσες](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
✅ Γιατί θα επιλέγατε έναν βρόχο for αντί για έναν βρόχο while; 17.000 χρήστες είχαν την ίδια ερώτηση στο StackOverflow, και ορισμένες από τις απόψεις [μπορεί να σας ενδιαφέρουν](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
## Βρόχοι και Πίνακες
@ -130,7 +130,7 @@ for (let i = 0; i < iceCreamFlavors.length; i++) {
Υπάρχουν και άλλοι τρόποι επανάληψης πινάκων εκτός από τους βρόχους for και while. Υπάρχουν οι [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). Ξαναγράψτε τον βρόχο του πίνακά σας χρησιμοποιώντας μία από αυτές τις τεχνικές.
## Κουίζ μετά το μάθημα
## Κουίζ Μετά το Μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/14)
## Ανασκόπηση & Αυτομελέτη
@ -139,9 +139,9 @@ for (let i = 0; i < iceCreamFlavors.length; i++) {
## Εργασία
[Επανάληψη ενός Πίνακα](assignment.md)
[Επανάληψη Πίνακα](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "46a0639e719b9cf1dfd062aa24cad639",
"translation_date": "2025-08-26T21:28:38+00:00",
"original_hash": "89f7f9f800ce7c9f149e98baaae8491a",
"translation_date": "2025-08-29T07:15:20+00:00",
"source_file": "3-terrarium/1-intro-to-html/README.md",
"language_code": "el"
}
@ -16,6 +16,7 @@ CO_OP_TRANSLATOR_METADATA:
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/15)
> Δείτε το βίντεο
>
@ -29,7 +30,7 @@ CO_OP_TRANSLATOR_METADATA:
### Εργασία
Στον υπολογιστή σας, δημιουργήστε έναν φάκελο με όνομα 'terrarium' και μέσα σε αυτόν ένα αρχείο με όνομα 'index.html'. Μπορείτε να το κάνετε αυτό στο Visual Studio Code αφού δημιουργήσετε τον φάκελο terrarium, ανοίγοντας ένα νέο παράθυρο του VS Code, κάνοντας κλικ στο 'open folder' και πηγαίνοντας στον νέο σας φάκελο. Κάντε κλικ στο μικρό κουμπί 'file' στον πίνακα Explorer και δημιουργήστε το νέο αρχείο:
Στον υπολογιστή σας, δημιουργήστε έναν φάκελο που ονομάζεται 'terrarium' και μέσα σε αυτόν ένα αρχείο που ονομάζεται 'index.html'. Μπορείτε να το κάνετε αυτό στο Visual Studio Code αφού δημιουργήσετε τον φάκελο terrarium, ανοίγοντας ένα νέο παράθυρο του VS Code, κάνοντας κλικ στο 'open folder' και πλοηγούμενοι στον νέο σας φάκελο. Κάντε κλικ στο μικρό κουμπί 'file' στον πίνακα Explorer και δημιουργήστε το νέο αρχείο:
![explorer στο VS Code](../../../../translated_images/vs-code-index.e2986cf919471eb984a0afef231380c8b132b000635105f2397bd2754d1b689c.el.png)
@ -41,13 +42,13 @@ CO_OP_TRANSLATOR_METADATA:
* `touch index.html`
* `code index.html` ή `nano index.html`
> Τα αρχεία index.html υποδεικνύουν σε έναν περιηγητή ότι είναι το προεπιλεγμένο αρχείο σε έναν φάκελο. URLs όπως `https://anysite.com/test` μπορεί να δημιουργούνται χρησιμοποιώντας μια δομή φακέλων που περιλαμβάνει έναν φάκελο με όνομα `test` και το `index.html` μέσα σε αυτόν. Το `index.html` δεν χρειάζεται να εμφανίζεται στο URL.
> Τα αρχεία index.html υποδεικνύουν σε έναν περιηγητή ότι είναι το προεπιλεγμένο αρχείο σε έναν φάκελο. URLs όπως `https://anysite.com/test` μπορεί να δημιουργούνται χρησιμοποιώντας μια δομή φακέλων που περιλαμβάνει έναν φάκελο που ονομάζεται `test` με `index.html` μέσα του. Το `index.html` δεν χρειάζεται να εμφανίζεται στο URL.
---
## Το DocType και οι ετικέτες html
Η πρώτη γραμμή ενός αρχείου HTML είναι το doctype του. Είναι λίγο παράξενο που πρέπει να υπάρχει αυτή η γραμμή στην κορυφή του αρχείου, αλλά ενημερώνει τους παλαιότερους περιηγητές ότι η σελίδα πρέπει να αποδοθεί σε τυπική λειτουργία, ακολουθώντας την τρέχουσα προδιαγραφή html.
Η πρώτη γραμμή ενός αρχείου HTML είναι το doctype. Είναι λίγο εκπληκτικό ότι πρέπει να έχετε αυτή τη γραμμή στην κορυφή του αρχείου, αλλά ενημερώνει τους παλαιότερους περιηγητές ότι πρέπει να αποδώσουν τη σελίδα σε τυπική λειτουργία, ακολουθώντας την τρέχουσα προδιαγραφή html.
> Συμβουλή: στο VS Code, μπορείτε να περάσετε το ποντίκι πάνω από μια ετικέτα και να λάβετε πληροφορίες για τη χρήση της από τους οδηγούς αναφοράς MDN.
@ -55,14 +56,14 @@ CO_OP_TRANSLATOR_METADATA:
### Εργασία
Προσθέστε αυτές τις γραμμές στην κορυφή του αρχείου `index.html`:
Προσθέστε αυτές τις γραμμές στην κορυφή του αρχείου `index.html` σας:
```HTML
<!DOCTYPE html>
<html></html>
```
✅ Υπάρχουν διάφορες λειτουργίες που μπορούν να καθοριστούν ορίζοντας το DocType με μια συμβολοσειρά ερωτήματος: [Λειτουργία Quirks και Λειτουργία Standards](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode). Αυτές οι λειτουργίες χρησιμοποιούνταν για την υποστήριξη πολύ παλιών περιηγητών που δεν χρησιμοποιούνται πλέον (Netscape Navigator 4 και Internet Explorer 5). Μπορείτε να παραμείνετε στη δήλωση του τυπικού doctype.
✅ Υπάρχουν μερικές διαφορετικές λειτουργίες που μπορούν να καθοριστούν ορίζοντας το DocType με μια συμβολοσειρά ερωτήματος: [Λειτουργία Quirks και Λειτουργία Standards](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode). Αυτές οι λειτουργίες χρησιμοποιούνταν για την υποστήριξη πολύ παλιών περιηγητών που δεν χρησιμοποιούνται πλέον (Netscape Navigator 4 και Internet Explorer 5). Μπορείτε να παραμείνετε στη δήλωση doctype standard.
---
@ -97,7 +98,7 @@ CO_OP_TRANSLATOR_METADATA:
### Ετικέτες HTML
Στο HTML, προσθέτετε ετικέτες στο αρχείο .html για να δημιουργήσετε στοιχεία μιας διαδικτυακής σελίδας. Κάθε ετικέτα συνήθως έχει μια ετικέτα που ανοίγει και μια που κλείνει, όπως αυτή: `<p>hello</p>` για να υποδείξετε μια παράγραφο. Δημιουργήστε το σώμα της διεπαφής σας προσθέτοντας ένα ζευγάρι ετικετών `<body>` μέσα στο ζευγάρι ετικετών `<html>`; η σήμανσή σας τώρα μοιάζει με αυτή:
Στο HTML, προσθέτετε ετικέτες στο αρχείο .html για να δημιουργήσετε στοιχεία μιας διαδικτυακής σελίδας. Κάθε ετικέτα συνήθως έχει μια ετικέτα που ανοίγει και μια που κλείνει, όπως αυτή: `<p>hello</p>` για να υποδείξετε μια παράγραφο. Δημιουργήστε το σώμα της διεπαφής σας προσθέτοντας ένα σύνολο ετικετών `<body>` μέσα στο ζεύγος ετικετών `<html>`; η σήμανσή σας τώρα μοιάζει με αυτή:
### Εργασία
@ -120,7 +121,7 @@ CO_OP_TRANSLATOR_METADATA:
Μια ετικέτα html που δεν χρειάζεται ετικέτα κλεισίματος είναι η ετικέτα `<img>`, επειδή έχει ένα στοιχείο `src` που περιέχει όλες τις πληροφορίες που χρειάζεται η σελίδα για να αποδώσει το αντικείμενο.
Δημιουργήστε έναν φάκελο στην εφαρμογή σας με όνομα `images` και προσθέστε εκεί όλες τις εικόνες από τον [φάκελο πηγαίου κώδικα](../../../../3-terrarium/solution/images); (υπάρχουν 14 εικόνες φυτών).
Δημιουργήστε έναν φάκελο στην εφαρμογή σας που ονομάζεται `images` και σε αυτόν προσθέστε όλες τις εικόνες από τον [φάκελο πηγαίου κώδικα](../../../../3-terrarium/solution/images); (υπάρχουν 14 εικόνες φυτών).
### Εργασία
@ -183,13 +184,13 @@ CO_OP_TRANSLATOR_METADATA:
Κάθε εικόνα έχει εναλλακτικό κείμενο που θα εμφανίζεται ακόμα και αν δεν μπορείτε να δείτε ή να αποδώσετε μια εικόνα. Αυτό είναι ένα σημαντικό χαρακτηριστικό για την προσβασιμότητα. Μάθετε περισσότερα για την προσβασιμότητα σε μελλοντικά μαθήματα. Προς το παρόν, θυμηθείτε ότι το χαρακτηριστικό alt παρέχει εναλλακτικές πληροφορίες για μια εικόνα αν ένας χρήστης για κάποιο λόγο δεν μπορεί να τη δει (λόγω αργής σύνδεσης, σφάλματος στο χαρακτηριστικό src ή αν ο χρήστης χρησιμοποιεί αναγνώστη οθόνης).
✅ Παρατηρήσατε ότι κάθε εικόνα έχει το ίδιο alt tag; Είναι αυτή καλή πρακτική; Γιατί ή γιατί όχι; Μπορείτε να βελτιώσετε αυτόν τον κώδικα;
✅ Παρατηρήσατε ότι κάθε εικόνα έχει την ίδια ετικέτα alt; Είναι αυτή καλή πρακτική; Γιατί ή γιατί όχι; Μπορείτε να βελτιώσετε αυτόν τον κώδικα;
---
## Σημαντική σήμανση
## Σημασιολογική σήμανση
Γενικά, είναι προτιμότερο να χρησιμοποιείτε ουσιαστική 'σημαντική' σήμανση όταν γράφετε HTML. Τι σημαίνει αυτό; Σημαίνει ότι χρησιμοποιείτε ετικέτες HTML για να αντιπροσωπεύσετε τον τύπο δεδομένων ή αλληλεπίδρασης για τον οποίο σχεδιάστηκαν. Για παράδειγμα, το κύριο κείμενο τίτλου σε μια σελίδα πρέπει να χρησιμοποιεί μια ετικέτα `<h1>`.
Γενικά, είναι προτιμότερο να χρησιμοποιείτε ουσιαστική 'σημασιολογία' όταν γράφετε HTML. Τι σημαίνει αυτό; Σημαίνει ότι χρησιμοποιείτε ετικέτες HTML για να αντιπροσωπεύσετε τον τύπο δεδομένων ή αλληλεπίδρασης για τον οποίο σχεδιάστηκαν. Για παράδειγμα, το κύριο κείμενο τίτλου σε μια σελίδα πρέπει να χρησιμοποιεί μια ετικέτα `<h1>`.
Προσθέστε την παρακάτω γραμμή ακριβώς κάτω από την ετικέτα `<body>` που ανοίγει:
@ -197,9 +198,9 @@ CO_OP_TRANSLATOR_METADATA:
<h1>My Terrarium</h1>
```
Η χρήση σημαντικής σήμανσης, όπως το να έχετε επικεφαλίδες `<h1>` και μη ταξινομημένες λίστες να αποδίδονται ως `<ul>`, βοηθά τους αναγνώστες οθόνης να πλοηγούνται σε μια σελίδα. Γενικά, τα κουμπιά πρέπει να γράφονται ως `<button>` και οι λίστες ως `<li>`. Ενώ είναι υνατό_ να χρησιμοποιήσετε ειδικά στυλιζαρισμένα στοιχεία `<span>` με χειριστές κλικ για να μιμηθείτε κουμπιά, είναι καλύτερο για τους χρήστες με αναπηρίες να χρησιμοποιούν τεχνολογίες για να προσδιορίσουν πού βρίσκεται ένα κουμπί σε μια σελίδα και να αλληλεπιδράσουν με αυτό, αν το στοιχείο εμφανίζεται ως κουμπί. Για αυτόν τον λόγο, προσπαθήστε να χρησιμοποιείτε σημαντική σήμανση όσο το δυνατόν περισσότερο.
Η χρήση σημασιολογικής σήμανσης, όπως το να είναι οι επικεφαλίδες `<h1>` και οι μη ταξινομημένες λίστες να αποδίδονται ως `<ul>`, βοηθά τους αναγνώστες οθόνης να πλοηγούνται σε μια σελίδα. Γενικά, τα κουμπιά πρέπει να γράφονται ως `<button>` και οι λίστες ως `<li>`. Ενώ είναι υνατό_ να χρησιμοποιήσετε ειδικά στυλιζαρισμένα στοιχεία `<span>` με χειριστές κλικ για να μιμηθείτε κουμπιά, είναι καλύτερο για τους χρήστες με αναπηρίες να χρησιμοποιούν τεχνολογίες για να προσδιορίσουν πού βρίσκεται ένα κουμπί σε μια σελίδα και να αλληλεπιδράσουν με αυτό, αν το στοιχείο εμφανίζεται ως κουμπί. Για αυτόν τον λόγο, προσπαθήστε να χρησιμοποιείτε σημασιολογική σήμανση όσο το δυνατόν περισσότερο.
✅ Ρίξτε μια ματιά σε έναν αναγνώστη οθόνης και [πώς αλληλεπιδρά με μια διαδικτυακή σελίδα](https://www.youtube.com/watch?v=OUDV1gqs9GA). Μπορείτε να δείτε γιατί η μη σημαντική σήμανση μπορεί να απογοητεύσει τον χρήστη;
✅ Ρίξτε μια ματιά σε έναν αναγνώστη οθόνης και [πώς αλληλεπιδρά με μια διαδικτυακή σελίδα](https://www.youtube.com/watch?v=OUDV1gqs9GA). Μπορείτε να δείτε γιατί η μη σημασιολογική σήμανση μπορεί να απογοητεύσει τον χρήστη;
## Το terrarium
@ -227,7 +228,7 @@ CO_OP_TRANSLATOR_METADATA:
## 🚀Πρόκληση
Υπάρχουν μερικές 'παλιές' ετικέτες στο HTML που είναι ακόμα διασκεδαστικές να πειραματιστείτε, αν και δεν πρέπει να χρησιμοποιείτε καταργημένες ετικέτες όπως [αυτές](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements) στη σήμανσή σας. Παρ' όλα αυτά, μπορείτε να χρησιμοποιήσετε την παλιά ετικέτα `<marquee>` για να κάνετε τον τίτλο h1 να κυλάει οριζόντια; (αν το κάνετε, μην ξεχάσετε να το αφαιρέσετε μετά)
Υπάρχουν μερικές 'παλιές' ετικέτες στο HTML που είναι ακόμα διασκεδαστικές να πειραματιστείτε, αν και δεν πρέπει να χρησιμοποιείτε καταργημένες ετικέτες όπως [αυτές οι ετικέτες](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements) στη σήμανσή σας. Παρ' όλα αυτά, μπορείτε να χρησιμοποιήσετε την παλιά ετικέτα `<marquee>` για να κάνετε τον τίτλο h1 να κυλάει οριζόντια; (αν το κάνετε, μην ξεχάσετε να το αφαιρέσετε μετά)
## Ερωτηματολόγιο μετά το μάθημα
@ -235,10 +236,11 @@ CO_OP_TRANSLATOR_METADATA:
## Ανασκόπηση & Αυτομελέτη
Το HTML είναι το 'δοκιμασμένο και αληθινό' σύστημα δομικών στοιχείων που έχει βοηθήσει να χτιστεί το διαδίκτυο όπως το γνωρίζουμε σήμερα. Μάθετε λίγα πράγματα για την ιστορία του μελετώντας μερικές παλιές και νέες ετικέτες. Μπορείτε να καταλάβετε γιατί κάποιες ετικέτες καταργήθηκαν και κάποιες προστέθηκαν; Ποιες ετικέτες μπορεί να εισαχθούν στο μέλλον;
Το HTML είναι το 'δοκιμασμένο και αληθινό' σύστημα δομικών στοιχείων που έχει βοηθήσει να χτιστεί το διαδίκτυο όπως το γνωρίζουμε σήμερα. Μάθετε λίγα για την ιστορία του μελετώντας μερικές παλιές και νέες ετικέτες. Μπορείτε να καταλάβετε γιατί κάποιες ετικέτες καταργήθηκαν και κάποιες προστέθηκαν; Ποιες ετικέτες μπορεί να εισαχθούν στο μέλλον;
Μάθετε περισσότερα για τη δημιουργία ιστοσελίδων για το διαδίκτυο και κινητές συσκευές στο [Microsoft Learn](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon).
## Εργασία
[Εξασκηθείτε στο HTML: Δημιουργήστε ένα mockup blog](assignment.md)

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e375c2aeb94e2407f2667633d39580bd",
"translation_date": "2025-08-26T21:35:41+00:00",
"original_hash": "acb5ae00cde004304296bb97da8ff4c3",
"translation_date": "2025-08-29T07:16:00+00:00",
"source_file": "3-terrarium/2-intro-to-css/README.md",
"language_code": "el"
}
@ -18,11 +18,11 @@ CO_OP_TRANSLATOR_METADATA:
### Εισαγωγή
Το CSS, ή Cascading Style Sheets, λύνει ένα σημαντικό πρόβλημα της ανάπτυξης ιστοσελίδων: πώς να κάνετε την ιστοσελίδα σας να φαίνεται όμορφη. Το να δώσετε στυλ στις εφαρμογές σας τις κάνει πιο χρηστικές και πιο ελκυστικές. Μπορείτε επίσης να χρησιμοποιήσετε το CSS για να δημιουργήσετε Responsive Web Design (RWD) - επιτρέποντας στις εφαρμογές σας να φαίνονται καλά ανεξάρτητα από το μέγεθος της οθόνης στην οποία εμφανίζονται. Το CSS δεν αφορά μόνο την αισθητική της εφαρμογής σας· η προδιαγραφή του περιλαμβάνει κινούμενα σχέδια και μετασχηματισμούς που μπορούν να επιτρέψουν εξελιγμένες αλληλεπιδράσεις για τις εφαρμογές σας. Η Ομάδα Εργασίας CSS βοηθά στη διατήρηση των τρεχουσών προδιαγραφών CSS· μπορείτε να παρακολουθήσετε τη δουλειά τους στον [ιστότοπο του World Wide Web Consortium](https://www.w3.org/Style/CSS/members).
Το CSS, ή Cascading Style Sheets, λύνει ένα σημαντικό πρόβλημα της ανάπτυξης ιστοσελίδων: πώς να κάνετε την ιστοσελίδα σας να φαίνεται όμορφη. Το να δώσετε στυλ στις εφαρμογές σας τις κάνει πιο χρηστικές και πιο ελκυστικές. Μπορείτε επίσης να χρησιμοποιήσετε το CSS για να δημιουργήσετε Responsive Web Design (RWD) - επιτρέποντας στις εφαρμογές σας να φαίνονται καλά ανεξάρτητα από το μέγεθος της οθόνης στην οποία εμφανίζονται. Το CSS δεν αφορά μόνο την εμφάνιση της εφαρμογής σας. Η προδιαγραφή του περιλαμβάνει κινούμενα σχέδια και μετασχηματισμούς που μπορούν να επιτρέψουν εξελιγμένες αλληλεπιδράσεις για τις εφαρμογές σας. Η Ομάδα Εργασίας CSS βοηθά στη διατήρηση των τρεχουσών προδιαγραφών CSS. Μπορείτε να παρακολουθήσετε τη δουλειά τους στον [ιστότοπο του World Wide Web Consortium](https://www.w3.org/Style/CSS/members).
> Σημείωση: Το CSS είναι μια γλώσσα που εξελίσσεται, όπως όλα στο διαδίκτυο, και δεν υποστηρίζουν όλοι οι περιηγητές τα νεότερα μέρη της προδιαγραφής. Πάντα να ελέγχετε τις υλοποιήσεις σας συμβουλευόμενοι το [CanIUse.com](https://caniuse.com).
Σε αυτό το μάθημα, θα προσθέσουμε στυλ στο online terrarium μας και θα μάθουμε περισσότερα για διάφορες έννοιες του CSS: την ιεραρχία, την κληρονομικότητα, τη χρήση επιλεγτών, τη θέση και τη χρήση του CSS για τη δημιουργία διατάξεων. Στη διαδικασία, θα διαμορφώσουμε το terrarium και θα δημιουργήσουμε το ίδιο το terrarium.
Σε αυτό το μάθημα, θα προσθέσουμε στυλ στο διαδικτυακό μας terrarium και θα μάθουμε περισσότερα για διάφορες έννοιες του CSS: την αλληλουχία, την κληρονομικότητα, τη χρήση επιλεγμένων στοιχείων, τη θέση και τη χρήση του CSS για τη δημιουργία διατάξεων. Στη διαδικασία, θα διαμορφώσουμε το terrarium και θα δημιουργήσουμε το ίδιο το terrarium.
### Προαπαιτούμενο
@ -43,9 +43,9 @@ CO_OP_TRANSLATOR_METADATA:
---
## Η Ιεραρχία
## Η Αλληλουχία
Τα Cascading Style Sheets ενσωματώνουν την ιδέα ότι τα στυλ "καταρρέουν" έτσι ώστε η εφαρμογή ενός στυλ να καθοδηγείται από την προτεραιότητά του. Τα στυλ που ορίζονται από τον δημιουργό της ιστοσελίδας έχουν προτεραιότητα έναντι αυτών που ορίζονται από τον περιηγητή. Τα στυλ που ορίζονται "inline" έχουν προτεραιότητα έναντι αυτών που ορίζονται σε εξωτερικό αρχείο στυλ.
Τα Cascading Style Sheets ενσωματώνουν την ιδέα ότι τα στυλ "αλληλουχούν", έτσι ώστε η εφαρμογή ενός στυλ να καθοδηγείται από την προτεραιότητά του. Τα στυλ που ορίζονται από τον δημιουργό της ιστοσελίδας έχουν προτεραιότητα έναντι αυτών που ορίζονται από τον περιηγητή. Τα στυλ που ορίζονται "inline" έχουν προτεραιότητα έναντι αυτών που ορίζονται σε εξωτερικό φύλλο στυλ.
### Εργασία
@ -55,7 +55,7 @@ CO_OP_TRANSLATOR_METADATA:
<h1 style="color: red">My Terrarium</h1>
```
Στη συνέχεια, προσθέστε τον παρακάτω κώδικα στο αρχείο `style.css`:
Στη συνέχεια, προσθέστε τον ακόλουθο κώδικα στο αρχείο `style.css`:
```CSS
h1 {
@ -69,7 +69,7 @@ h1 {
## Κληρονομικότητα
Τα στυλ κληρονομούνται από έναν πρόγονο σε έναν απόγονο, έτσι ώστε τα ενσωματωμένα στοιχεία να κληρονομούν τα στυλ των γονέων τους.
Τα στυλ κληρονομούνται από ένα στυλ προγόνου σε έναν απόγονο, έτσι ώστε τα ενσωματωμένα στοιχεία να κληρονομούν τα στυλ των γονέων τους.
### Εργασία
@ -89,11 +89,11 @@ body {
---
## Επιλέκτες CSS
## Επιλογείς CSS
### Ετικέτες
Μέχρι στιγμής, το αρχείο `style.css` σας έχει μόνο λίγες ετικέτες με στυλ, και η εφαρμογή φαίνεται αρκετά περίεργη:
Μέχρι στιγμής, το αρχείο `style.css` σας έχει μόνο λίγες ετικέτες στυλιζαρισμένες, και η εφαρμογή φαίνεται αρκετά περίεργη:
```CSS
body {
@ -106,7 +106,7 @@ h1 {
}
```
Αυτός ο τρόπος στυλιζαρίσματος μιας ετικέτας σας δίνει έλεγχο σε μοναδικά στοιχεία, αλλά χρειάζεστε να ελέγξετε τα στυλ πολλών φυτών στο terrarium σας. Για να το κάνετε αυτό, πρέπει να αξιοποιήσετε τους επιλέκτες CSS.
Αυτός ο τρόπος στυλιζαρίσματος μιας ετικέτας σας δίνει έλεγχο σε μοναδικά στοιχεία, αλλά χρειάζεστε να ελέγξετε τα στυλ πολλών φυτών στο terrarium σας. Για να το κάνετε αυτό, πρέπει να αξιοποιήσετε τους επιλογείς CSS.
### Ids
@ -144,7 +144,7 @@ h1 {
### Classes
Στο παραπάνω παράδειγμα, στυλιζάρατε δύο μοναδικά στοιχεία στην οθόνη. Αν θέλετε τα στυλ να εφαρμόζονται σε πολλά στοιχεία στην οθόνη, μπορείτε να χρησιμοποιήσετε CSS classes. Κάντε το για να διαμορφώσετε τα φυτά στα αριστερά και δεξιά δοχεία.
Στο παραπάνω παράδειγμα, στυλιζάρατε δύο μοναδικά στοιχεία στην οθόνη. Αν θέλετε τα στυλ να εφαρμόζονται σε πολλά στοιχεία στην οθόνη, μπορείτε να χρησιμοποιήσετε CSS classes. Κάντε το αυτό για να διαμορφώσετε τα φυτά στα αριστερά και δεξιά δοχεία.
Παρατηρήστε ότι κάθε φυτό στο HTML markup έχει έναν συνδυασμό ids και classes. Τα ids εδώ χρησιμοποιούνται από το JavaScript που θα προσθέσετε αργότερα για να χειριστείτε την τοποθέτηση των φυτών στο terrarium. Οι classes, ωστόσο, δίνουν σε όλα τα φυτά ένα συγκεκριμένο στυλ.
@ -154,7 +154,7 @@ h1 {
</div>
```
Προσθέστε τα παρακάτω στο αρχείο `style.css`:
Προσθέστε τον ακόλουθο κώδικα στο αρχείο `style.css`:
```CSS
.plant-holder {
@ -173,25 +173,25 @@ h1 {
Αξιοσημείωτο σε αυτό το απόσπασμα είναι το μείγμα σχετικής και απόλυτης θέσης, το οποίο θα καλύψουμε στην επόμενη ενότητα. Ρίξτε μια ματιά στον τρόπο με τον οποίο χειρίζονται τα ύψη με ποσοστά:
Ορίσατε το ύψος του δοχείου φυτών στο 13%, έναν καλό αριθμό για να διασφαλίσετε ότι όλα τα φυτά εμφανίζονται σε κάθε κάθετο δοχείο χωρίς να χρειάζεται κύλιση.
Ορίσατε το ύψος του φυτοδοχείου στο 13%, έναν καλό αριθμό για να διασφαλίσετε ότι όλα τα φυτά εμφανίζονται σε κάθε κάθετο δοχείο χωρίς να χρειάζεται κύλιση.
Ορίσατε το δοχείο φυτών να μετακινηθεί προς τα αριστερά ώστε τα φυτά να είναι πιο κεντραρισμένα μέσα στο δοχείο τους. Οι εικόνες έχουν μεγάλο ποσό διαφανούς φόντου για να είναι πιο εύκολα μετακινούμενες, οπότε πρέπει να μετακινηθούν προς τα αριστερά για να ταιριάζουν καλύτερα στην οθόνη.
Τοποθετήσατε το φυτοδοχείο να μετακινηθεί προς τα αριστερά ώστε τα φυτά να είναι πιο κεντραρισμένα μέσα στο δοχείο τους. Οι εικόνες έχουν μεγάλο ποσό διαφανούς φόντου ώστε να είναι πιο εύκολα μετακινούμενες, οπότε χρειάζεται να μετακινηθούν προς τα αριστερά για να ταιριάζουν καλύτερα στην οθόνη.
Στη συνέχεια, το ίδιο το φυτό έχει μέγιστο πλάτος 150%. Αυτό του επιτρέπει να μειώνεται καθώς μειώνεται το μέγεθος του περιηγητή. Δοκιμάστε να αλλάξετε το μέγεθος του περιηγητή σας· τα φυτά παραμένουν στα δοχεία τους αλλά μειώνονται για να ταιριάζουν.
Στη συνέχεια, το ίδιο το φυτό έχει μέγιστο πλάτος 150%. Αυτό του επιτρέπει να μειώνεται καθώς μειώνεται το μέγεθος του περιηγητή. Δοκιμάστε να αλλάξετε το μέγεθος του περιηγητή σας. Τα φυτά παραμένουν στα δοχεία τους αλλά μειώνονται για να ταιριάζουν.
Επίσης αξιοσημείωτη είναι η χρήση του z-index, που ελέγχει το σχετικό ύψος ενός στοιχείου (ώστε τα φυτά να κάθονται πάνω από το δοχείο και να φαίνονται μέσα στο terrarium).
✅ Γιατί χρειάζεστε τόσο έναν επιλέκτη CSS για το δοχείο φυτών όσο και για το φυτό;
✅ Γιατί χρειάζεστε τόσο έναν επιλογέα CSS για το φυτοδοχείο όσο και για το φυτό;
## Θέση CSS
Η ανάμειξη ιδιοτήτων θέσης (υπάρχουν static, relative, fixed, absolute και sticky θέσεις) μπορεί να είναι λίγο δύσκολη, αλλά όταν γίνεται σωστά σας δίνει καλό έλεγχο στα στοιχεία στις σελίδες σας.
Η ανάμειξη ιδιοτήτων θέσης (υπάρχουν στατική, σχετική, σταθερή, απόλυτη και κολλώδης θέση) μπορεί να είναι λίγο δύσκολη, αλλά όταν γίνεται σωστά σας δίνει καλό έλεγχο στα στοιχεία στις σελίδες σας.
Τα στοιχεία με απόλυτη θέση τοποθετούνται σε σχέση με τους πλησιέστερους τοποθετημένους προγόνους τους, και αν δεν υπάρχουν, τοποθετούνται σύμφωνα με το σώμα του εγγράφου.
Τα στοιχεία με σχετική θέση τοποθετούνται βάσει των οδηγιών του CSS για να προσαρμόσουν τη θέση τους μακριά από την αρχική τους θέση.
Στο παράδειγμά μας, το `plant-holder` είναι ένα στοιχείο με σχετική θέση που τοποθετείται μέσα σε ένα δοχείο με απόλυτη θέση. Η προκύπτουσα συμπεριφορά είναι ότι τα δοχεία της πλαϊνής μπάρας είναι καρφωμένα αριστερά και δεξιά, και το `plant-holder` είναι ενσωματωμένο, προσαρμόζοντας τον εαυτό του μέσα στις πλαϊνές μπάρες, δίνοντας χώρο για τα φυτά να τοποθετηθούν σε κάθετη σειρά.
Στο δείγμα μας, το `plant-holder` είναι ένα στοιχείο με σχετική θέση που τοποθετείται μέσα σε ένα δοχείο με απόλυτη θέση. Η προκύπτουσα συμπεριφορά είναι ότι τα δοχεία της πλαϊνής μπάρας είναι καρφωμένα αριστερά και δεξιά, και το `plant-holder` είναι ενσωματωμένο, προσαρμόζοντας τον εαυτό του μέσα στις πλαϊνές μπάρες, δίνοντας χώρο για τα φυτά να τοποθετηθούν σε κάθετη σειρά.
> Το ίδιο το `plant` έχει επίσης απόλυτη θέση, απαραίτητη για να είναι μετακινούμενο, όπως θα ανακαλύψετε στο επόμενο μάθημα.
@ -272,7 +272,7 @@ h1 {
## Ανασκόπηση & Αυτομελέτη
Το CSS φαίνεται απατηλά απλό, αλλά υπάρχουν πολλές προκλήσεις όταν προσπαθείτε να στυλιζάρετε μια εφαρμογή τέλεια για όλους τους περιηγητές και όλα τα μεγέθη οθόνης. Το CSS-Grid και το Flexbox είναι εργαλεία που έχουν αναπτυχθεί για να κάνουν τη δουλειά λίγο πιο δομημένη και πιο αξιόπιστη. Μάθετε για αυτά τα εργαλεία παίζοντας [Flexbox Froggy](https://flexboxfroggy.com/) και [Grid Garden](https://codepip.com/games/grid-garden/).
Το CSS φαίνεται παραπλανητικά απλό, αλλά υπάρχουν πολλές προκλήσεις όταν προσπαθείτε να στυλιζάρετε μια εφαρμογή τέλεια για όλους τους περιηγητές και όλα τα μεγέθη οθόνης. Το CSS-Grid και το Flexbox είναι εργαλεία που έχουν αναπτυχθεί για να κάνουν τη δουλειά λίγο πιο δομημένη και πιο αξιόπιστη. Μάθετε για αυτά τα εργαλεία παίζοντας [Flexbox Froggy](https://flexboxfroggy.com/) και [Grid Garden](https://codepip.com/games/grid-garden/).
## Εργασία
@ -281,4 +281,4 @@ h1 {
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε κάθε δυνατή προσπάθεια για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "30f8903a1f290e3d438dc2c70fe60259",
"translation_date": "2025-08-26T21:31:59+00:00",
"original_hash": "61c14b27044861e5e69db35dd52c4403",
"translation_date": "2025-08-29T07:16:44+00:00",
"source_file": "3-terrarium/3-intro-to-DOM-and-closures/README.md",
"language_code": "el"
}
@ -10,19 +10,19 @@ CO_OP_TRANSLATOR_METADATA:
# Έργο Terrarium Μέρος 3: Χειρισμός DOM και Κλείσιμο
![DOM και κλείσιμο](../../../../translated_images/webdev101-js.10280393044d7eaaec7e847574946add7ddae6be2b2194567d848b61d849334a.el.png)
> Σκίτσο από την [Tomomi Imura](https://twitter.com/girlie_mac)
> Σκίτσο από [Tomomi Imura](https://twitter.com/girlie_mac)
## Κουίζ Πριν το Μάθημα
## Ερωτηματολόγιο πριν το μάθημα
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/19)
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/19)
### Εισαγωγή
Ο χειρισμός του DOM, ή "Document Object Model", είναι μια βασική πτυχή της ανάπτυξης ιστοσελίδων. Σύμφωνα με το [MDN](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction), "Το Document Object Model (DOM) είναι η αναπαράσταση δεδομένων των αντικειμένων που αποτελούν τη δομή και το περιεχόμενο ενός εγγράφου στον ιστό." Οι προκλήσεις γύρω από τον χειρισμό του DOM στον ιστό συχνά αποτέλεσαν την αιτία για τη χρήση JavaScript frameworks αντί για απλή JavaScript για τη διαχείριση του DOM, αλλά εμείς θα τα καταφέρουμε μόνοι μας!
Ο χειρισμός του DOM, ή "Document Object Model", είναι ένα βασικό στοιχείο της ανάπτυξης ιστοσελίδων. Σύμφωνα με το [MDN](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction), "Το Document Object Model (DOM) είναι η αναπαράσταση δεδομένων των αντικειμένων που αποτελούν τη δομή και το περιεχόμενο ενός εγγράφου στον ιστό." Οι προκλήσεις γύρω από τον χειρισμό του DOM στον ιστό συχνά αποτέλεσαν την αιτία για τη χρήση JavaScript frameworks αντί για απλή JavaScript για τη διαχείριση του DOM, αλλά εμείς θα τα καταφέρουμε μόνοι μας!
Επιπλέον, αυτό το μάθημα θα εισαγάγει την ιδέα ενός [κλεισίματος JavaScript](https://developer.mozilla.org/docs/Web/JavaScript/Closures), το οποίο μπορείτε να σκεφτείτε ως μια συνάρτηση που περικλείεται από μια άλλη συνάρτηση, ώστε η εσωτερική συνάρτηση να έχει πρόσβαση στο πεδίο της εξωτερικής συνάρτησης.
Επιπλέον, αυτό το μάθημα θα εισαγάγει την ιδέα ενός [κλεισίματος JavaScript](https://developer.mozilla.org/docs/Web/JavaScript/Closures), το οποίο μπορείτε να σκεφτείτε ως μια συνάρτηση που περικλείεται από μια άλλη συνάρτηση, ώστε η εσωτερική συνάρτηση να έχει πρόσβαση στο scope της εξωτερικής συνάρτησης.
> Τα κλεισίματα JavaScript είναι ένα εκτενές και περίπλοκο θέμα. Αυτό το μάθημα αγγίζει την πιο βασική ιδέα ότι στον κώδικα αυτού του terrarium, θα βρείτε ένα κλείσιμο: μια εσωτερική συνάρτηση και μια εξωτερική συνάρτηση που έχουν κατασκευαστεί με τρόπο ώστε να επιτρέπουν στην εσωτερική συνάρτηση πρόσβαση στο πεδίο της εξωτερικής συνάρτησης. Για περισσότερες πληροφορίες σχετικά με το πώς λειτουργεί αυτό, επισκεφθείτε την [εκτενή τεκμηρίωση](https://developer.mozilla.org/docs/Web/JavaScript/Closures).
> Τα κλεισίματα JavaScript είναι ένα ευρύ και πολύπλοκο θέμα. Αυτό το μάθημα αγγίζει την πιο βασική ιδέα ότι στον κώδικα του terrarium, θα βρείτε ένα κλείσιμο: μια εσωτερική συνάρτηση και μια εξωτερική συνάρτηση κατασκευασμένες με τρόπο που επιτρέπει στην εσωτερική συνάρτηση να έχει πρόσβαση στο scope της εξωτερικής συνάρτησης. Για περισσότερες πληροφορίες σχετικά με το πώς λειτουργεί αυτό, επισκεφθείτε την [εκτενή τεκμηρίωση](https://developer.mozilla.org/docs/Web/JavaScript/Closures).
Θα χρησιμοποιήσουμε ένα κλείσιμο για να χειριστούμε το DOM.
@ -30,13 +30,13 @@ CO_OP_TRANSLATOR_METADATA:
![Αναπαράσταση δέντρου DOM](../../../../translated_images/dom-tree.7daf0e763cbbba9273f9a66fe04c98276d7d23932309b195cb273a9cf1819b42.el.png)
> Μια αναπαράσταση του DOM και της HTML σήμανσης που το αναφέρεται. Από την [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
> Μια αναπαράσταση του DOM και της HTML σήμανσης που το αναφέρεται. Από [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
Σε αυτό το μάθημα, θα ολοκληρώσουμε το διαδραστικό έργο terrarium δημιουργώντας τη JavaScript που θα επιτρέπει σε έναν χρήστη να χειρίζεται τα φυτά στη σελίδα.
Σε αυτό το μάθημα, θα ολοκληρώσουμε το διαδραστικό έργο terrarium δημιουργώντας τη JavaScript που θα επιτρέπει στον χρήστη να χειρίζεται τα φυτά στη σελίδα.
### Προαπαιτούμενα
### Προαπαιτούμενο
Θα πρέπει να έχετε δημιουργήσει το HTML και το CSS για το terrarium σας. Μέχρι το τέλος αυτού του μαθήματος, θα μπορείτε να μετακινείτε τα φυτά μέσα και έξω από το terrarium σύροντάς τα.
Θα πρέπει να έχετε δημιουργήσει το HTML και το CSS για το terrarium σας. Μέχρι το τέλος αυτού του μαθήματος θα μπορείτε να μετακινείτε τα φυτά μέσα και έξω από το terrarium με τη μέθοδο drag-and-drop.
### Εργασία
@ -46,12 +46,12 @@ CO_OP_TRANSLATOR_METADATA:
<script src="./script.js" defer></script>
```
> Σημείωση: χρησιμοποιήστε το `defer` κατά την εισαγωγή ενός εξωτερικού αρχείου JavaScript στο αρχείο HTML, ώστε να επιτρέψετε στη JavaScript να εκτελεστεί μόνο αφού το αρχείο HTML έχει φορτωθεί πλήρως. Μπορείτε επίσης να χρησιμοποιήσετε το χαρακτηριστικό `async`, το οποίο επιτρέπει στο script να εκτελείται ενώ το αρχείο HTML αναλύεται, αλλά στη δική μας περίπτωση, είναι σημαντικό να είναι πλήρως διαθέσιμα τα στοιχεία HTML για σύρσιμο πριν επιτρέψουμε την εκτέλεση του script σύρσης.
> Σημείωση: χρησιμοποιήστε `defer` όταν εισάγετε ένα εξωτερικό αρχείο JavaScript στο αρχείο HTML, ώστε να επιτρέψετε στη JavaScript να εκτελεστεί μόνο αφού το αρχείο HTML έχει φορτωθεί πλήρως. Μπορείτε επίσης να χρησιμοποιήσετε το χαρακτηριστικό `async`, το οποίο επιτρέπει στο script να εκτελείται ενώ το αρχείο HTML αναλύεται, αλλά στη δική μας περίπτωση, είναι σημαντικό να είναι πλήρως διαθέσιμα τα στοιχεία HTML για το drag πριν εκτελεστεί το script drag.
---
## Τα στοιχεία του DOM
Το πρώτο πράγμα που πρέπει να κάνετε είναι να δημιουργήσετε αναφορές στα στοιχεία που θέλετε να χειριστείτε στο DOM. Στην περίπτωσή μας, είναι τα 14 φυτά που περιμένουν στις πλαϊνές μπάρες.
Το πρώτο πράγμα που πρέπει να κάνετε είναι να δημιουργήσετε αναφορές στα στοιχεία που θέλετε να χειριστείτε στο DOM. Στην περίπτωσή μας, είναι τα 14 φυτά που περιμένουν στις πλευρικές μπάρες.
### Εργασία
@ -72,17 +72,17 @@ dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));
```
Τι συμβαίνει εδώ; Αναφέρεστε στο έγγραφο και ψάχνετε μέσα στο DOM του για να βρείτε ένα στοιχείο με συγκεκριμένο Id. Θυμάστε στο πρώτο μάθημα για το HTML που δώσατε μοναδικά Ids σε κάθε εικόνα φυτού (`id="plant1"`); Τώρα θα αξιοποιήσετε αυτή την προσπάθεια. Αφού εντοπίσετε κάθε στοιχείο, το περνάτε σε μια συνάρτηση που ονομάζεται `dragElement`, την οποία θα δημιουργήσετε σε λίγο. Έτσι, το στοιχείο στο HTML είναι πλέον έτοιμο για σύρσιμο ή θα είναι σύντομα.
Τι συμβαίνει εδώ; Αναφέρεστε στο έγγραφο και ψάχνετε στο DOM του για να βρείτε ένα στοιχείο με συγκεκριμένο Id. Θυμηθείτε στο πρώτο μάθημα για το HTML ότι δώσατε μοναδικά Ids σε κάθε εικόνα φυτού (`id="plant1"`); Τώρα θα αξιοποιήσετε αυτή την προσπάθεια. Αφού εντοπίσετε κάθε στοιχείο, το περνάτε σε μια συνάρτηση που ονομάζεται `dragElement`, την οποία θα δημιουργήσετε σε λίγο. Έτσι, το στοιχείο στο HTML είναι πλέον έτοιμο για drag, ή θα είναι σύντομα.
✅ Γιατί αναφερόμαστε σε στοιχεία με Id; Γιατί όχι με την CSS κλάση τους; Μπορείτε να ανατρέξετε στο προηγούμενο μάθημα για το CSS για να απαντήσετε σε αυτή την ερώτηση.
✅ Γιατί αναφερόμαστε στα στοιχεία με Id; Γιατί όχι με την CSS class τους; Μπορείτε να ανατρέξετε στο προηγούμενο μάθημα για το CSS για να απαντήσετε σε αυτή την ερώτηση.
---
## Το Κλείσιμο
Τώρα είστε έτοιμοι να δημιουργήσετε το κλείσιμο `dragElement`, το οποίο είναι μια εξωτερική συνάρτηση που περικλείει μια ή περισσότερες εσωτερικές συναρτήσεις (στην περίπτωσή μας, θα έχουμε τρεις).
Τώρα είστε έτοιμοι να δημιουργήσετε το κλείσιμο `dragElement`, το οποίο είναι μια εξωτερική συνάρτηση που περικλείει μια εσωτερική συνάρτηση ή συναρτήσεις (στην περίπτωσή μας, θα έχουμε τρεις).
Τα κλεισίματα είναι χρήσιμα όταν μία ή περισσότερες συναρτήσεις χρειάζονται πρόσβαση στο πεδίο της εξωτερικής συνάρτησης. Δείτε ένα παράδειγμα:
Τα κλεισίματα είναι χρήσιμα όταν μία ή περισσότερες συναρτήσεις χρειάζονται πρόσβαση στο scope της εξωτερικής συνάρτησης. Δείτε ένα παράδειγμα:
```javascript
function displayCandy(){
@ -96,9 +96,9 @@ displayCandy();
console.log(candy)
```
Σε αυτό το παράδειγμα, η συνάρτηση `displayCandy` περικλείει μια συνάρτηση που προσθέτει έναν νέο τύπο καραμέλας σε έναν πίνακα που ήδη υπάρχει στη συνάρτηση. Αν εκτελούσατε αυτόν τον κώδικα, ο πίνακας `candy` θα ήταν απροσδιόριστος, καθώς είναι μια τοπική μεταβλητή (τοπική στο κλείσιμο).
Σε αυτό το παράδειγμα, η συνάρτηση `displayCandy` περιβάλλει μια συνάρτηση που προσθέτει έναν νέο τύπο καραμέλας σε έναν πίνακα που ήδη υπάρχει στη συνάρτηση. Αν εκτελέσετε αυτόν τον κώδικα, ο πίνακας `candy` θα είναι undefined, καθώς είναι μια τοπική μεταβλητή (τοπική στο κλείσιμο).
✅ Πώς μπορείτε να κάνετε τον πίνακα `candy` προσβάσιμο; Δοκιμάστε να τον μετακινήσετε έξω από το κλείσιμο. Με αυτόν τον τρόπο, ο πίνακας γίνεται καθολικός, αντί να παραμένει διαθέσιμος μόνο στο τοπικό πεδίο του κλεισίματος.
✅ Πώς μπορείτε να κάνετε τον πίνακα `candy` προσβάσιμο; Δοκιμάστε να τον μετακινήσετε έξω από το κλείσιμο. Με αυτόν τον τρόπο, ο πίνακας γίνεται global, αντί να παραμένει διαθέσιμος μόνο στο τοπικό scope του κλεισίματος.
### Εργασία
@ -115,17 +115,17 @@ function dragElement(terrariumElement) {
}
```
Η `dragElement` λαμβάνει το αντικείμενο `terrariumElement` από τις δηλώσεις στην κορυφή του script. Στη συνέχεια, ορίζετε κάποιες τοπικές θέσεις στο `0` για το αντικείμενο που περνάτε στη συνάρτηση. Αυτές είναι οι τοπικές μεταβλητές που θα χειριστείτε για κάθε στοιχείο καθώς προσθέτετε λειτουργικότητα σύρσης και απόθεσης μέσα στο κλείσιμο για κάθε στοιχείο. Το terrarium θα γεμίσει με αυτά τα στοιχεία που σύρονται, οπότε η εφαρμογή πρέπει να παρακολουθεί πού τοποθετούνται.
Η `dragElement` λαμβάνει το αντικείμενο `terrariumElement` από τις δηλώσεις στην κορυφή του script. Στη συνέχεια, ορίζετε κάποιες τοπικές θέσεις στο `0` για το αντικείμενο που περνάτε στη συνάρτηση. Αυτές είναι οι τοπικές μεταβλητές που θα χειριστούν για κάθε στοιχείο καθώς προσθέτετε λειτουργικότητα drag-and-drop σε κάθε στοιχείο μέσα στο κλείσιμο. Το terrarium θα γεμίσει από αυτά τα στοιχεία που σύρονται, οπότε η εφαρμογή πρέπει να παρακολουθεί πού τοποθετούνται.
Επιπλέον, το `terrariumElement` που περνάτε σε αυτή τη συνάρτηση ανατίθεται σε ένα γεγονός `pointerdown`, το οποίο είναι μέρος των [web APIs](https://developer.mozilla.org/docs/Web/API) που έχουν σχεδιαστεί για να βοηθούν στη διαχείριση του DOM. Το `onpointerdown` ενεργοποιείται όταν πατηθεί ένα κουμπί ή, στην περίπτωσή μας, όταν αγγιχτεί ένα στοιχείο που μπορεί να συρθεί. Αυτός ο χειριστής γεγονότων λειτουργεί τόσο σε [φυλλομετρητές ιστού όσο και σε κινητά](https://caniuse.com/?search=onpointerdown), με λίγες εξαιρέσεις.
Επιπλέον, το `terrariumElement` που περνάτε σε αυτή τη συνάρτηση ανατίθεται σε ένα γεγονός `pointerdown`, το οποίο είναι μέρος των [web APIs](https://developer.mozilla.org/docs/Web/API) που έχουν σχεδιαστεί για να βοηθούν στη διαχείριση του DOM. Το `onpointerdown` ενεργοποιείται όταν πατηθεί ένα κουμπί ή, στην περίπτωσή μας, όταν αγγιχθεί ένα στοιχείο που μπορεί να σύρεται. Αυτός ο χειριστής γεγονότων λειτουργεί τόσο σε [web όσο και σε mobile browsers](https://caniuse.com/?search=onpointerdown), με λίγες εξαιρέσεις.
Ο [χειριστής γεγονότων `onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) έχει πολύ μεγαλύτερη υποστήριξη μεταξύ φυλλομετρητών. Γιατί να μην τον χρησιμοποιήσετε εδώ; Σκεφτείτε τον ακριβή τύπο αλληλεπίδρασης που προσπαθείτε να δημιουργήσετε εδώ.
Το [event handler `onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) έχει πολύ μεγαλύτερη υποστήριξη σε διάφορους browsers. Γιατί δεν το χρησιμοποιείτε εδώ; Σκεφτείτε τον ακριβή τύπο αλληλεπίδρασης που προσπαθείτε να δημιουργήσετε εδώ.
---
## Η συνάρτηση Pointerdrag
Το `terrariumElement` είναι έτοιμο να συρθεί. Όταν ενεργοποιηθεί το γεγονός `onpointerdown`, καλείται η συνάρτηση `pointerDrag`. Προσθέστε αυτή τη συνάρτηση ακριβώς κάτω από αυτή τη γραμμή: `terrariumElement.onpointerdown = pointerDrag;`:
Το `terrariumElement` είναι έτοιμο να σύρεται γύρω. Όταν ενεργοποιηθεί το γεγονός `onpointerdown`, καλείται η συνάρτηση `pointerDrag`. Προσθέστε αυτή τη συνάρτηση ακριβώς κάτω από αυτή τη γραμμή: `terrariumElement.onpointerdown = pointerDrag;`:
### Εργασία
@ -138,15 +138,15 @@ function pointerDrag(e) {
}
```
Συμβαίνουν αρκετά πράγματα. Πρώτα, αποτρέπετε τα προεπιλεγμένα γεγονότα που κανονικά συμβαίνουν στο pointerdown χρησιμοποιώντας `e.preventDefault();`. Με αυτόν τον τρόπο έχετε περισσότερο έλεγχο στη συμπεριφορά της διεπαφής.
Συμβαίνουν αρκετά πράγματα. Πρώτον, αποτρέπετε τα προεπιλεγμένα γεγονότα που συμβαίνουν συνήθως στο pointerdown χρησιμοποιώντας `e.preventDefault();`. Με αυτόν τον τρόπο έχετε μεγαλύτερο έλεγχο στη συμπεριφορά της διεπαφής.
> Επιστρέψτε σε αυτή τη γραμμή όταν έχετε ολοκληρώσει το αρχείο script και δοκιμάστε το χωρίς το `e.preventDefault()` - τι συμβαίνει;
Δεύτερον, ανοίξτε το `index.html` σε ένα παράθυρο φυλλομετρητή και επιθεωρήστε τη διεπαφή. Όταν κάνετε κλικ σε ένα φυτό, μπορείτε να δείτε πώς το γεγονός 'e' καταγράφεται. Εξετάστε το γεγονός για να δείτε πόσες πληροφορίες συλλέγονται από ένα γεγονός pointer down!
Δεύτερον, ανοίξτε το `index.html` σε ένα παράθυρο browser και επιθεωρήστε τη διεπαφή. Όταν κάνετε κλικ σε ένα φυτό, μπορείτε να δείτε πώς καταγράφεται το γεγονός 'e'. Εξετάστε το γεγονός για να δείτε πόσες πληροφορίες συλλέγονται από ένα pointer down γεγονός!
Στη συνέχεια, σημειώστε πώς οι τοπικές μεταβλητές `pos3` και `pos4` ορίζονται στο e.clientX. Μπορείτε να βρείτε τις τιμές `e` στο παράθυρο επιθεώρησης. Αυτές οι τιμές καταγράφουν τις συντεταγμένες x και y του φυτού τη στιγμή που κάνετε κλικ ή το αγγίζετε. Θα χρειαστείτε λεπτομερή έλεγχο της συμπεριφοράς των φυτών καθώς τα κάνετε κλικ και τα σύρετε, οπότε παρακολουθείτε τις συντεταγμένες τους.
✅ Γίνεται πιο ξεκάθαρο γιατί ολόκληρη η εφαρμογή είναι χτισμένη με ένα μεγάλο κλείσιμο; Αν δεν ήταν, πώς θα διατηρούσατε το πεδίο για καθένα από τα 14 φυτά που μπορούν να συρθούν;
✅ Γίνεται πιο σαφές γιατί όλη αυτή η εφαρμογή είναι χτισμένη με ένα μεγάλο κλείσιμο; Αν δεν ήταν, πώς θα διατηρούσατε το scope για καθένα από τα 14 φυτά που μπορούν να σύρονται;
Ολοκληρώστε την αρχική συνάρτηση προσθέτοντας δύο ακόμη χειρισμούς γεγονότων pointer κάτω από το `pos4 = e.clientY`:
@ -154,11 +154,11 @@ function pointerDrag(e) {
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
```
Τώρα υποδεικνύετε ότι θέλετε το φυτό να σύρεται μαζί με τον δείκτη καθώς το μετακινείτε, και η χειρονομία σύρσης να σταματά όταν αποεπιλέγετε το φυτό. Τα `onpointermove` και `onpointerup` είναι όλα μέρη του ίδιου API με το `onpointerdown`. Η διεπαφή θα εμφανίσει σφάλματα τώρα, καθώς δεν έχετε ακόμη ορίσει τις συναρτήσεις `elementDrag` και `stopElementDrag`, οπότε δημιουργήστε τις στη συνέχεια.
Τώρα υποδεικνύετε ότι θέλετε το φυτό να σύρεται μαζί με τον δείκτη καθώς το μετακινείτε, και η χειρονομία σύρσης να σταματά όταν αποεπιλέγετε το φυτό. Τα `onpointermove` και `onpointerup` είναι όλα μέρη του ίδιου API όπως το `onpointerdown`. Η διεπαφή θα εμφανίσει σφάλματα τώρα καθώς δεν έχετε ακόμη ορίσει τις συναρτήσεις `elementDrag` και `stopElementDrag`, οπότε δημιουργήστε τις στη συνέχεια.
## Οι συναρτήσεις elementDrag και stopElementDrag
Θα ολοκληρώσετε το κλείσιμό σας προσθέτοντας δύο ακόμη εσωτερικές συναρτήσεις που θα χειρίζονται τι συμβαίνει όταν σύρετε ένα φυτό και όταν σταματάτε να το σύρετε. Η συμπεριφορά που θέλετε είναι να μπορείτε να σύρετε οποιοδήποτε φυτό ανά πάσα στιγμή και να το τοποθετείτε οπουδήποτε στην οθόνη. Αυτή η διεπαφή είναι αρκετά ευέλικτη (δεν υπάρχει ζώνη απόθεσης, για παράδειγμα) ώστε να σας επιτρέπει να σχεδιάσετε το terrarium σας όπως ακριβώς θέλετε, προσθέτοντας, αφαιρώντας και επανατοποθετώντας φυτά.
Θα ολοκληρώσετε το κλείσιμό σας προσθέτοντας δύο ακόμη εσωτερικές συναρτήσεις που θα χειρίζονται τι συμβαίνει όταν σύρετε ένα φυτό και όταν σταματάτε να το σύρετε. Η συμπεριφορά που θέλετε είναι να μπορείτε να σύρετε οποιοδήποτε φυτό οποιαδήποτε στιγμή και να το τοποθετείτε οπουδήποτε στην οθόνη. Αυτή η διεπαφή είναι αρκετά ευέλικτη (δεν υπάρχει ζώνη πτώσης, για παράδειγμα) ώστε να σας επιτρέπει να σχεδιάσετε το terrarium σας ακριβώς όπως θέλετε προσθέτοντας, αφαιρώντας και επανατοποθετώντας φυτά.
### Εργασία
@ -177,11 +177,11 @@ function elementDrag(e) {
```
Σε αυτή τη συνάρτηση, κάνετε πολλές επεξεργασίες των αρχικών θέσεων 1-4 που ορίσατε ως τοπικές μεταβλητές στην εξωτερική συνάρτηση. Τι συμβαίνει εδώ;
Καθώς σύρετε, επαναπροσδιορίζετε το `pos1` κάνοντάς το ίσο με το `pos3` (το οποίο ορίσατε νωρίτερα ως `e.clientX`) μείον την τρέχουσα τιμή `e.clientX`. Κάνετε μια παρόμοια λειτουργία για το `pos2`. Στη συνέχεια, επαναφέρετε τα `pos3` και `pos4` στις νέες συντεταγμένες X και Y του στοιχείου. Μπορείτε να παρακολουθήσετε αυτές τις αλλαγές στην κονσόλα καθώς σύρετε. Στη συνέχεια, χειρίζεστε το στυλ css του φυτού για να ορίσετε τη νέα του θέση με βάση τις νέες θέσεις των `pos1` και `pos2`, υπολογίζοντας τις συντεταγμένες X και Y του φυτού με βάση τη σύγκριση της μετατόπισής του με αυτές τις νέες θέσεις.
Καθώς σύρετε, επαναπροσδιορίζετε το `pos1` κάνοντάς το ίσο με το `pos3` (το οποίο ορίσατε νωρίτερα ως `e.clientX`) μείον την τρέχουσα τιμή `e.clientX`. Κάνετε μια παρόμοια λειτουργία στο `pos2`. Στη συνέχεια, επαναπροσδιορίζετε το `pos3` και το `pos4` στις νέες συντεταγμένες X και Y του στοιχείου. Μπορείτε να παρακολουθήσετε αυτές τις αλλαγές στην κονσόλα καθώς σύρετε. Στη συνέχεια, χειρίζεστε το css style του φυτού για να ορίσετε τη νέα του θέση βάσει των νέων θέσεων του `pos1` και `pos2`, υπολογίζοντας τις συντεταγμένες X και Y του φυτού βάσει της σύγκρισης της μετατόπισής του με αυτές τις νέες θέσεις.
> Τα `offsetTop` και `offsetLeft` είναι ιδιότητες CSS που ορίζουν τη θέση ενός στοιχείου με βάση αυτή του γονέα του. Ο γονέας του μπορεί να είναι οποιοδήποτε στοιχείο που δεν έχει θέση `static`.
> Τα `offsetTop` και `offsetLeft` είναι ιδιότητες CSS που ορίζουν τη θέση ενός στοιχείου βάσει αυτής του γονέα του. Ο γονέας του μπορεί να είναι οποιοδήποτε στοιχείο που δεν έχει θέση `static`.
Όλη αυτή η επαναϋπολογισμός θέσεων σας επιτρέπει να ρυθμίσετε με ακρίβεια τη συμπεριφορά του terrarium και των φυτών του.
Όλη αυτή η επαναπροσδιορισμός θέσης σας επιτρέπει να ρυθμίσετε τη συμπεριφορά του terrarium και των φυτών του.
### Εργασία
@ -194,7 +194,7 @@ function stopElementDrag() {
}
```
Αυτή η μικρή συνάρτηση επαναφέρει τα γεγονότα `onpointerup` και `onpointermove`, ώστε να μπορείτε είτε να ξεκινήσετε ξανά την πρόοδο του φυτού σας ξεκινώντας να το σύρετε ξανά, είτε να αρχίσετε να σύρετε ένα νέο φυτό.
Αυτή η μικρή συνάρτηση επαναφέρει τα γεγονότα `onpointerup` και `onpointermove`, ώστε να μπορείτε είτε να επανεκκινήσετε την πρόοδο του φυτού σας ξεκινώντας να το σύρετε ξανά, είτε να ξεκινήσετε να σύρετε ένα νέο φυτό.
Τι συμβαίνει αν δεν ορίσετε αυτά τα γεγονότα σε null;
@ -208,23 +208,23 @@ function stopElementDrag() {
Προσθέστε έναν νέο χειριστή γεγονότων στο κλείσιμό σας για να κάνετε κάτι επιπλέον στα φυτά. Για παράδειγμα, κάντε διπλό κλικ σε ένα φυτό για να το φέρετε μπροστά. Γίνετε δημιουργικοί!
## Κουίζ Μετά το Μάθημα
## Ερωτηματολόγιο μετά το μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/20)
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/20)
## Ανασκόπηση & Αυτομελέτη
Ενώ το να σύρετε στοιχεία γύρω από την οθόνη φαίνεται απλό, υπάρχουν πολλοί τρόποι να το κάνετε και πολλές παγίδες, ανάλογα με το αποτέλεσμα που επιδιώκετε. Στην πραγματικότητα, υπάρχει ένα ολόκληρο [drag and drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) που μπορείτε να δοκιμάσετε. Δεν το χρησιμοποιήσαμε σε αυτή τη μονάδα επειδή το αποτέλεσμα που θέλαμε ήταν κάπως διαφορετικό, αλλά δοκιμάστε αυτό το API στο δικό σας έργο και δείτε τι μπορείτε να πετύχετε.
Ενώ η μετακίνηση στοιχείων γύρω από την οθόνη φαίνεται απλή, υπάρχουν πολλοί τρόποι να το κάνετε και πολλές παγίδες, ανάλογα με το αποτέλεσμα που επιδιώκετε. Στην πραγματικότητα, υπάρχει ένα ολόκληρο [drag and drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) που μπορείτε να δοκιμάσετε. Δεν το χρησιμοποιήσαμε σε αυτή τη μονάδα επειδή το αποτέλεσμα που θέλαμε ήταν κάπως διαφορετικό, αλλά δοκιμάστε αυτό το API στο δικό σας έργο και δείτε τι μπορείτε να πετύχετε.
Βρείτε περισσότερες πληροφορίες για τα pointer events στα [έγγραφα W3C](https://www.w3.org/TR/pointerevents1/) και στα [έγγραφα MDN](https://developer.mozilla.org/docs/Web/API/Pointer_events).
Βρείτε περισσότερες πληροφορίες για τα pointer events στα [έγγραφα W3C](https://www.w3.org/TR/pointerevents1/) και στα [έγγραφα MDN web](https://developer.mozilla.org/docs/Web/API/Pointer_events).
Πάντα να ελέγχετε τις δυνατότητες των φυλλομετρητών χρησιμοποιώντας το [CanIUse.com](https://caniuse.com/).
Πάντα να ελέγχετε τις δυνατότητες των browsers χρησιμοποιώντας το [CanIUse.com](https://caniuse.com/).
## Ανάθεση
## Εργασία
[Δουλέψτε λίγο περισσότερο με το DOM](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e982871b8388c59c22a41b73b5fca70f",
"translation_date": "2025-08-26T23:15:35+00:00",
"original_hash": "1b0aeccb600f83c603cd70cb42df594d",
"translation_date": "2025-08-29T07:19:55+00:00",
"source_file": "4-typing-game/typing-game/README.md",
"language_code": "el"
}
@ -13,13 +13,13 @@ CO_OP_TRANSLATOR_METADATA:
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/21)
## Προγραμματισμός με βάση τα γεγονότα
## Προγραμματισμός βασισμένος σε γεγονότα
Όταν δημιουργούμε μια εφαρμογή για τον περιηγητή, παρέχουμε μια γραφική διεπαφή χρήστη (GUI) για να αλληλεπιδράσει ο χρήστης με αυτό που έχουμε δημιουργήσει. Ο πιο συνηθισμένος τρόπος αλληλεπίδρασης με τον περιηγητή είναι μέσω κλικ και πληκτρολόγησης σε διάφορα στοιχεία. Η πρόκληση που αντιμετωπίζουμε ως προγραμματιστές είναι ότι δεν γνωρίζουμε πότε θα εκτελέσουν αυτές τις ενέργειες!
Όταν δημιουργούμε μια εφαρμογή για τον περιηγητή, παρέχουμε μια γραφική διεπαφή χρήστη (GUI) για να αλληλεπιδρά ο χρήστης με αυτό που έχουμε δημιουργήσει. Ο πιο συνηθισμένος τρόπος αλληλεπίδρασης με τον περιηγητή είναι μέσω κλικ και πληκτρολόγησης σε διάφορα στοιχεία. Η πρόκληση που αντιμετωπίζουμε ως προγραμματιστές είναι ότι δεν γνωρίζουμε πότε θα εκτελέσουν αυτές τις ενέργειες!
Ο [προγραμματισμός με βάση τα γεγονότα](https://en.wikipedia.org/wiki/Event-driven_programming) είναι ο τύπος προγραμματισμού που χρειαζόμαστε για να δημιουργήσουμε τη GUI μας. Αν αναλύσουμε λίγο αυτή τη φράση, βλέπουμε ότι η βασική λέξη εδώ είναι **γεγονός**. Σύμφωνα με το [Merriam-Webster](https://www.merriam-webster.com/dictionary/event), γεγονός ορίζεται ως "κάτι που συμβαίνει". Αυτό περιγράφει τέλεια την κατάστασή μας. Ξέρουμε ότι κάτι πρόκειται να συμβεί για το οποίο θέλουμε να εκτελέσουμε κάποιον κώδικα ως απάντηση, αλλά δεν γνωρίζουμε πότε θα συμβεί.
Ο [προγραμματισμός βασισμένος σε γεγονότα](https://en.wikipedia.org/wiki/Event-driven_programming) είναι ο τύπος προγραμματισμού που πρέπει να χρησιμοποιήσουμε για να δημιουργήσουμε τη GUI μας. Αν αναλύσουμε λίγο αυτή τη φράση, βλέπουμε ότι η βασική λέξη εδώ είναι το **γεγονός**. Σύμφωνα με το [Merriam-Webster](https://www.merriam-webster.com/dictionary/event), γεγονός ορίζεται ως "κάτι που συμβαίνει". Αυτό περιγράφει τέλεια την κατάστασή μας. Γνωρίζουμε ότι κάτι πρόκειται να συμβεί για το οποίο θέλουμε να εκτελέσουμε κάποιον κώδικα ως απάντηση, αλλά δεν γνωρίζουμε πότε θα συμβεί.
Ο τρόπος με τον οποίο σημειώνουμε ένα τμήμα κώδικα που θέλουμε να εκτελεστεί είναι δημιουργώντας μια συνάρτηση. Όταν σκεφτόμαστε τον [διαδικαστικό προγραμματισμό](https://en.wikipedia.org/wiki/Procedural_programming), οι συναρτήσεις καλούνται με συγκεκριμένη σειρά. Το ίδιο ισχύει και για τον προγραμματισμό με βάση τα γεγονότα. Η διαφορά είναι **πώς** καλούνται οι συναρτήσεις.
Ο τρόπος με τον οποίο σημειώνουμε ένα τμήμα κώδικα που θέλουμε να εκτελεστεί είναι δημιουργώντας μια συνάρτηση. Όταν σκεφτόμαστε τον [διαδικαστικό προγραμματισμό](https://en.wikipedia.org/wiki/Procedural_programming), οι συναρτήσεις καλούνται με συγκεκριμένη σειρά. Το ίδιο ισχύει και για τον προγραμματισμό βασισμένο σε γεγονότα. Η διαφορά είναι **πώς** καλούνται οι συναρτήσεις.
Για να χειριστούμε τα γεγονότα (κλικ κουμπιών, πληκτρολόγηση κ.λπ.), καταχωρούμε **ακροατές γεγονότων**. Ένας ακροατής γεγονότων είναι μια συνάρτηση που "ακούει" για την εμφάνιση ενός γεγονότος και εκτελείται ως απάντηση. Οι ακροατές γεγονότων μπορούν να ενημερώσουν τη διεπαφή χρήστη, να κάνουν κλήσεις στον διακομιστή ή οτιδήποτε άλλο χρειάζεται να γίνει ως απάντηση στη δράση του χρήστη. Προσθέτουμε έναν ακροατή γεγονότων χρησιμοποιώντας το [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) και παρέχοντας μια συνάρτηση για εκτέλεση.
@ -27,30 +27,30 @@ CO_OP_TRANSLATOR_METADATA:
### Συνηθισμένα γεγονότα
Υπάρχουν [δεκάδες γεγονότα](https://developer.mozilla.org/docs/Web/Events) διαθέσιμα για να ακούσετε όταν δημιουργείτε μια εφαρμογή. Ουσιαστικά, οτιδήποτε κάνει ένας χρήστης σε μια σελίδα δημιουργεί ένα γεγονός, κάτι που σας δίνει μεγάλη δύναμη για να εξασφαλίσετε ότι θα έχουν την εμπειρία που επιθυμείτε. Ευτυχώς, συνήθως θα χρειαστείτε μόνο μια μικρή ομάδα γεγονότων. Εδώ είναι μερικά συνηθισμένα (συμπεριλαμβανομένων των δύο που θα χρησιμοποιήσουμε για τη δημιουργία του παιχνιδιού μας):
Υπάρχουν [δεκάδες γεγονότα](https://developer.mozilla.org/docs/Web/Events) που μπορείτε να παρακολουθήσετε κατά τη δημιουργία μιας εφαρμογής. Ουσιαστικά, οτιδήποτε κάνει ένας χρήστης σε μια σελίδα δημιουργεί ένα γεγονός, κάτι που σας δίνει μεγάλη δύναμη για να εξασφαλίσετε ότι θα έχει την εμπειρία που επιθυμείτε. Ευτυχώς, συνήθως θα χρειαστείτε μόνο μια μικρή ομάδα γεγονότων. Εδώ είναι μερικά συνηθισμένα (συμπεριλαμβανομένων των δύο που θα χρησιμοποιήσουμε για τη δημιουργία του παιχνιδιού μας):
- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event): Ο χρήστης έκανε κλικ σε κάτι, συνήθως ένα κουμπί ή υπερσύνδεσμο
- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event): Ο χρήστης έκανε κλικ σε κάτι, συνήθως ένα κουμπί ή έναν υπερσύνδεσμο
- [contextmenu](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event): Ο χρήστης έκανε δεξί κλικ
- [select](https://developer.mozilla.org/docs/Web/API/Element/select_event): Ο χρήστης επισήμανε κάποιο κείμενο
- [select](https://developer.mozilla.org/docs/Web/API/Element/select_event): Ο χρήστης επέλεξε κάποιο κείμενο
- [input](https://developer.mozilla.org/docs/Web/API/Element/input_event): Ο χρήστης εισήγαγε κάποιο κείμενο
## Δημιουργία του παιχνιδιού
Θα δημιουργήσουμε ένα παιχνίδι για να εξερευνήσουμε πώς λειτουργούν τα γεγονότα στη JavaScript. Το παιχνίδι μας θα δοκιμάσει την ικανότητα πληκτρολόγησης του παίκτη, μια από τις πιο υποτιμημένες δεξιότητες που πρέπει να έχουν όλοι οι προγραμματιστές. Όλοι πρέπει να εξασκούμε την πληκτρολόγησή μας! Η γενική ροή του παιχνιδιού θα είναι η εξής:
Θα δημιουργήσουμε ένα παιχνίδι για να εξερευνήσουμε πώς λειτουργούν τα γεγονότα στη JavaScript. Το παιχνίδι μας θα δοκιμάσει την ικανότητα πληκτρολόγησης του παίκτη, η οποία είναι μία από τις πιο υποτιμημένες δεξιότητες που πρέπει να έχουν όλοι οι προγραμματιστές. Όλοι πρέπει να εξασκούμαστε στην πληκτρολόγηση! Η γενική ροή του παιχνιδιού θα είναι η εξής:
- Ο παίκτης κάνει κλικ στο κουμπί έναρξης και του εμφανίζεται μια φράση για να πληκτρολογήσει
- Ο παίκτης πληκτρολογεί τη φράση όσο πιο γρήγορα μπορεί σε ένα πεδίο κειμένου
- Ο παίκτης πληκτρολογεί τη φράση όσο πιο γρήγορα μπορεί σε ένα πλαίσιο κειμένου
- Καθώς ολοκληρώνεται κάθε λέξη, η επόμενη επισημαίνεται
- Αν ο παίκτης κάνει λάθος, το πεδίο κειμένου γίνεται κόκκινο
- Αν ο παίκτης κάνει κάποιο λάθος, το πλαίσιο κειμένου γίνεται κόκκινο
- Όταν ο παίκτης ολοκληρώσει τη φράση, εμφανίζεται ένα μήνυμα επιτυχίας με τον χρόνο που χρειάστηκε
Ας δημιουργήσουμε το παιχνίδι μας και ας μάθουμε για τα γεγονότα!
### Δομή αρχείων
Θα χρειαστούμε συνολικά τρία αρχεία: **index.html**, **script.js** και **style.css**. Ας ξεκινήσουμε δημιουργώντας τα για να κάνουμε τη ζωή μας λίγο πιο εύκολη.
Θα χρειαστούμε συνολικά τρία αρχεία: **index.html**, **script.js** και **style.css**. Ας τα δημιουργήσουμε για να κάνουμε τη ζωή μας λίγο πιο εύκολη.
- Δημιουργήστε έναν νέο φάκελο για τη δουλειά σας ανοίγοντας ένα παράθυρο κονσόλας ή τερματικού και εκτελώντας την ακόλουθη εντολή:
- Δημιουργήστε έναν νέο φάκελο για τη δουλειά σας ανοίγοντας μια κονσόλα ή ένα τερματικό και εκτελώντας την παρακάτω εντολή:
```bash
# Linux or macOS
@ -73,16 +73,16 @@ code .
## Δημιουργία της διεπαφής χρήστη
Αν εξετάσουμε τις απαιτήσεις, ξέρουμε ότι θα χρειαστούμε μερικά στοιχεία στη σελίδα HTML μας. Αυτό είναι κάπως σαν μια συνταγή, όπου χρειαζόμαστε κάποια υλικά:
Αν εξετάσουμε τις απαιτήσεις, γνωρίζουμε ότι θα χρειαστούμε μερικά στοιχεία στη σελίδα HTML μας. Αυτό μοιάζει λίγο με συνταγή, όπου χρειαζόμαστε κάποια υλικά:
- Κάπου για να εμφανίζεται η φράση που πρέπει να πληκτρολογήσει ο χρήστης
- Κάπου για να εμφανίζονται μηνύματα, όπως ένα μήνυμα επιτυχίας
- Ένα πεδίο κειμένου για την πληκτρολόγηση
- Ένα μέρος για να εμφανίζεται η φράση που πρέπει να πληκτρολογήσει ο χρήστης
- Ένα μέρος για να εμφανίζονται μηνύματα, όπως ένα μήνυμα επιτυχίας
- Ένα πλαίσιο κειμένου για πληκτρολόγηση
- Ένα κουμπί έναρξης
Το καθένα από αυτά θα χρειαστεί IDs ώστε να μπορούμε να τα χρησιμοποιήσουμε στον κώδικα JavaScript μας. Θα προσθέσουμε επίσης αναφορές στα αρχεία CSS και JavaScript που θα δημιουργήσουμε.
Το καθένα από αυτά θα χρειαστεί IDs ώστε να μπορούμε να τα χειριστούμε μέσω JavaScript. Θα προσθέσουμε επίσης αναφορές στα αρχεία CSS και JavaScript που θα δημιουργήσουμε.
Δημιουργήστε ένα νέο αρχείο με όνομα **index.html**. Προσθέστε τον ακόλουθο HTML:
Δημιουργήστε ένα νέο αρχείο με όνομα **index.html**. Προσθέστε τον παρακάτω HTML:
```html
<!-- inside index.html -->
@ -107,24 +107,24 @@ code .
### Εκκίνηση της εφαρμογής
Είναι πάντα καλύτερο να αναπτύσσουμε επαναληπτικά για να δούμε πώς φαίνονται τα πράγματα. Ας εκκινήσουμε την εφαρμογή μας. Υπάρχει μια εξαιρετική επέκταση για το Visual Studio Code που ονομάζεται [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), η οποία θα φιλοξενήσει την εφαρμογή σας τοπικά και θα ανανεώσει τον περιηγητή κάθε φορά που αποθηκεύετε.
Είναι πάντα καλύτερο να αναπτύσσουμε επαναληπτικά για να βλέπουμε πώς φαίνονται τα πράγματα. Ας εκκινήσουμε την εφαρμογή μας. Υπάρχει μια εξαιρετική επέκταση για το Visual Studio Code που ονομάζεται [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), η οποία φιλοξενεί την εφαρμογή σας τοπικά και ανανεώνει τον περιηγητή κάθε φορά που αποθηκεύετε.
- Εγκαταστήστε το [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) ακολουθώντας τον σύνδεσμο και κάνοντας κλικ στο **Install**
- Θα σας ζητηθεί από τον περιηγητή να ανοίξετε το Visual Studio Code και στη συνέχεια από το Visual Studio Code να εκτελέσετε την εγκατάσταση
- Ο περιηγητής θα σας ζητήσει να ανοίξετε το Visual Studio Code και στη συνέχεια το Visual Studio Code θα σας ζητήσει να εκτελέσετε την εγκατάσταση
- Επανεκκινήστε το Visual Studio Code αν σας ζητηθεί
- Μόλις εγκατασταθεί, στο Visual Studio Code, πατήστε Ctrl-Shift-P (ή Cmd-Shift-P) για να ανοίξετε την παλέτα εντολών
- Μόλις εγκατασταθεί, στο Visual Studio Code, πατήστε Ctrl-Shift-P (ή Cmd-Shift-P) για να ανοίξετε το command palette
- Πληκτρολογήστε **Live Server: Open with Live Server**
- Το Live Server θα ξεκινήσει να φιλοξενεί την εφαρμογή σας
- Ανοίξτε έναν περιηγητή και πλοηγηθείτε στο **https://localhost:5500**
- Τώρα θα πρέπει να βλέπετε τη σελίδα που δημιουργήσατε!
- Ανοίξτε έναν περιηγητή και μεταβείτε στη διεύθυνση **https://localhost:5500**
- Θα πρέπει τώρα να βλέπετε τη σελίδα που δημιουργήσατε!
Ας προσθέσουμε κάποια λειτουργικότητα.
Ας προσθέσουμε λίγη λειτουργικότητα.
## Προσθήκη CSS
## Προσθήκη του CSS
Με τον HTML μας έτοιμο, ας προσθέσουμε το CSS για τον βασικό σχεδιασμό. Χρειαζόμαστε να επισημάνουμε τη λέξη που πρέπει να πληκτρολογήσει ο παίκτης και να χρωματίσουμε το πεδίο κειμένου αν αυτό που έχει πληκτρολογήσει είναι λανθασμένο. Θα το κάνουμε αυτό με δύο κλάσεις.
Με τον HTML μας έτοιμο, ας προσθέσουμε το CSS για τον βασικό σχεδιασμό. Χρειαζόμαστε να επισημάνουμε τη λέξη που πρέπει να πληκτρολογήσει ο παίκτης και να χρωματίσουμε το πλαίσιο κειμένου αν αυτό που πληκτρολόγησε είναι λανθασμένο. Θα το κάνουμε αυτό με δύο κλάσεις.
Δημιουργήστε ένα νέο αρχείο με όνομα **style.css** και προσθέστε την ακόλουθη σύνταξη.
Δημιουργήστε ένα νέο αρχείο με όνομα **style.css** και προσθέστε την παρακάτω σύνταξη.
```css
/* inside style.css */
@ -138,7 +138,7 @@ code .
}
```
✅ Όσον αφορά το CSS, μπορείτε να διαμορφώσετε τη σελίδα σας όπως θέλετε. Αφιερώστε λίγο χρόνο για να κάνετε τη σελίδα πιο ελκυστική:
✅ Όταν πρόκειται για CSS, μπορείτε να διαμορφώσετε τη σελίδα σας όπως θέλετε. Αφιερώστε λίγο χρόνο για να κάνετε τη σελίδα πιο ελκυστική:
- Επιλέξτε διαφορετική γραμματοσειρά
- Χρωματίστε τους τίτλους
@ -146,7 +146,7 @@ code .
## JavaScript
Με τη διεπαφή χρήστη έτοιμη, είναι ώρα να επικεντρωθούμε στη JavaScript που θα παρέχει τη λογική. Θα το χωρίσουμε σε μερικά βήματα:
Με τη διεπαφή χρήστη έτοιμη, ήρθε η ώρα να επικεντρωθούμε στη JavaScript που θα παρέχει τη λογική. Θα το χωρίσουμε σε μερικά βήματα:
- [Δημιουργία των σταθερών](../../../../4-typing-game/typing-game)
- [Ακροατής γεγονότων για την έναρξη του παιχνιδιού](../../../../4-typing-game/typing-game)
@ -156,17 +156,17 @@ code .
### Δημιουργία των σταθερών
Θα χρειαστούμε μερικά στοιχεία για να κάνουμε τη ζωή μας λίγο πιο εύκολη στον προγραμματισμό. Και πάλι, όπως μια συνταγή, εδώ είναι τι θα χρειαστούμε:
Θα χρειαστούμε μερικά στοιχεία για να κάνουμε τη ζωή μας λίγο πιο εύκολη στον προγραμματισμό. Και πάλι, όπως σε μια συνταγή, εδώ είναι τι θα χρειαστούμε:
- Πίνακας με τη λίστα όλων των φράσεων
- Κενός πίνακας για την αποθήκευση όλων των λέξεων της τρέχουσας φράσης
- Χώρος για την αποθήκευση του δείκτη της λέξης που πληκτρολογεί ο παίκτης
- Ο χρόνος που ο παίκτης έκανε κλικ στο κουμπί έναρξης
- Έναν πίνακα με τη λίστα όλων των φράσεων
- Έναν κενό πίνακα για να αποθηκεύσουμε όλες τις λέξεις της τρέχουσας φράσης
- Χώρο για να αποθηκεύσουμε τον δείκτη της λέξης που πληκτρολογεί ο παίκτης
- Τον χρόνο που ο παίκτης έκανε κλικ στο κουμπί έναρξης
Θα θέλουμε επίσης αναφορές στα στοιχεία της διεπαφής χρήστη:
Θα χρειαστούμε επίσης αναφορές στα στοιχεία της διεπαφής χρήστη:
- Το πεδίο κειμένου (**typed-value**)
- Η εμφάνιση της φράσης (**quote**)
- Το πλαίσιο κειμένου (**typed-value**)
- Την εμφάνιση της φράσης (**quote**)
- Το μήνυμα (**message**)
```javascript
@ -194,9 +194,9 @@ const typedValueElement = document.getElementById('typed-value');
✅ Προσθέστε περισσότερες φράσεις στο παιχνίδι σας
> **NOTE:** Μπορούμε να ανακτήσουμε τα στοιχεία όποτε θέλουμε στον κώδικα χρησιμοποιώντας το `document.getElementById`. Επειδή θα αναφερόμαστε σε αυτά τα στοιχεία τακτικά, θα αποφύγουμε τα τυπογραφικά λάθη με συμβολοσειρές χρησιμοποιώντας σταθερές. Frameworks όπως το [Vue.js](https://vuejs.org/) ή το [React](https://reactjs.org/) μπορούν να σας βοηθήσουν να διαχειριστείτε καλύτερα την κεντρικοποίηση του κώδικα σας.
> **NOTE:** Μπορούμε να ανακτήσουμε τα στοιχεία όποτε θέλουμε στον κώδικα χρησιμοποιώντας το `document.getElementById`. Επειδή θα αναφερόμαστε συχνά σε αυτά τα στοιχεία, θα αποφύγουμε τα τυπογραφικά λάθη με συμβολοσειρές χρησιμοποιώντας σταθερές. Πλαίσια όπως το [Vue.js](https://vuejs.org/) ή το [React](https://reactjs.org/) μπορούν να σας βοηθήσουν να διαχειριστείτε καλύτερα την κεντρικοποίηση του κώδικά σας.
Αφιερώστε ένα λεπτό για να παρακολουθήσετε ένα βίντεο σχετικά με τη χρήση των `const`, `let` και `var`
Αφιερώστε ένα λεπτό για να παρακολουθήσετε ένα βίντεο σχετικά με τη χρήση των `const`, `let` και `var`.
[![Τύποι μεταβλητών](https://img.youtube.com/vi/JNIXfGiDWM8/0.jpg)](https://youtube.com/watch?v=JNIXfGiDWM8 "Τύποι μεταβλητών")
@ -204,7 +204,7 @@ const typedValueElement = document.getElementById('typed-value');
### Προσθήκη λογικής έναρξης
Για να ξεκινήσει το παιχνίδι, ο παίκτης θα κάνει κλικ στο κουμπί έναρξης. Φυσικά, δεν γνωρίζουμε πότε θα κάνει κλικ στο κουμπί έναρξης. Εδώ είναι που ένας [ακροατής γεγονότων](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) μπαίνει στο παιχνίδι. Ένας ακροατής γεγονότων θα μας επιτρέψει να "ακούμε" για την εμφάνιση ενός γεγονότος και να εκτελούμε κώδικα ως απάντηση. Στην περίπτωσή μας, θέλουμε να εκτελέσουμε κώδικα όταν ο χρήστης κάνει κλικ στο κουμπί έναρξης.
Για να ξεκινήσει το παιχνίδι, ο παίκτης θα κάνει κλικ στο κουμπί έναρξης. Φυσικά, δεν γνωρίζουμε πότε θα κάνει κλικ στο κουμπί έναρξης. Εδώ είναι που ένας [ακροατής γεγονότων](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) μπαίνει στο παιχνίδι. Ένας ακροατής γεγονότων θα μας επιτρέψει να "ακούμε" για κάτι που συμβαίνει (ένα γεγονός) και να εκτελούμε κώδικα ως απάντηση. Στην περίπτωσή μας, θέλουμε να εκτελέσουμε κώδικα όταν ο χρήστης κάνει κλικ στο κουμπί έναρξης.
Όταν ο χρήστης κάνει κλικ στο **start**, πρέπει να επιλέξουμε μια φράση, να ρυθμίσουμε τη διεπαφή χρήστη και να ρυθμίσουμε την παρακολούθηση για την τρέχουσα λέξη και τον χρόνο. Παρακάτω είναι η JavaScript που θα χρειαστεί να προσθέσετε. Θα την αναλύσουμε αμέσως μετά το μπλοκ κώδικα.
@ -246,22 +246,22 @@ document.getElementById('start').addEventListener('click', () => {
- Ρύθμιση παρακολούθησης λέξεων
- Χρησιμοποιώντας το [Math.floor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) και το [Math.random](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random), επιλέγουμε τυχαία μια φράση από τον πίνακα `quotes`
- Μετατρέπουμε τη `quote` σε έναν πίνακα `words` για να παρακολουθούμε τη λέξη που πληκτρολογεί ο παίκτης
- Ο `wordIndex` ορίζεται στο 0, καθώς ο παίκτης θα ξεκινήσει από την πρώτη λέξη
- Ορίζουμε το `wordIndex` στο 0, καθώς ο παίκτης θα ξεκινήσει από την πρώτη λέξη
- Ρύθμιση διεπαφής χρήστη
- Δημιουργούμε έναν πίνακα `spanWords`, που περιέχει κάθε λέξη μέσα σε ένα στοιχείο `span`
- Δημιουργούμε έναν πίνακα `spanWords`, ο οποίος περιέχει κάθε λέξη μέσα σε ένα στοιχείο `span`
- Αυτό θα μας επιτρέψει να επισημάνουμε τη λέξη στην οθόνη
- Χρησιμοποιούμε το `join` για να δημιουργήσουμε μια συμβολοσειρά που μπορούμε να χρησιμοποιήσουμε για να ενημερώσουμε το `innerHTML` στο `quoteElement`
- Χρησιμοποιούμε το `join` στον πίνακα για να δημιουργήσουμε μια συμβολοσειρά που μπορούμε να χρησιμοποιήσουμε για να ενημερώσουμε το `innerHTML` του `quoteElement`
- Αυτό θα εμφανίσει τη φράση στον παίκτη
- Ορίζουμε το `className` του πρώτου στοιχείου `span` σε `highlight` για να το επισημάνουμε ως κίτρινο
- Καθαρίζουμε το `messageElement` ορίζοντας το `innerText` σε `''`
- Ρύθμιση πεδίου κειμένου
- Καθαρίζουμε την τρέχουσα `value` στο `typedValueElement`
- Ρύθμιση πλαισίου κειμένου
- Καθαρίζουμε την τρέχουσα `value` του `typedValueElement`
- Ορίζουμε το `focus` στο `typedValueElement`
- Ξεκινάμε το χρονόμετρο καλώντας το `getTime`
### Προσθήκη λογικής πληκτρολόγησης
Καθώς ο παίκτης πληκτρολογεί, δημιουργείται ένα γεγονός `input`. Αυτός ο ακροατής γεγονότων θα ελέγξει αν ο παίκτης πληκτρολογεί σωστά τη λέξη και θα χειριστεί την τρέχουσα κατάσταση του παιχνιδιού. Επιστρέφοντας στο **script.js**, προσθέστε τον ακόλουθο κώδικα στο τέλος. Θα τον αναλύσουμε αμέσως μετά.
Καθώς ο παίκτης πληκτρολογεί, δημιουργείται ένα γεγονός `input`. Αυτός ο ακροατής γεγονότων θα ελέγξει αν ο παίκτης πληκτρολογεί σωστά τη λέξη και θα χειριστεί την τρέχουσα κατάσταση του παιχνιδιού. Επιστρέφοντας στο **script.js**, προσθέστε τον παρακάτω κώδικα στο τέλος. Θα τον αναλύσουμε αμέσως μετά.
```javascript
// at the end of script.js
@ -300,26 +300,24 @@ typedValueElement.addEventListener('input', () => {
});
```
Ας αναλύσουμε τον κώδικα! Ξεκινάμε παίρνοντας την τρέχουσα λέξη και την τιμή που έχει πληκτρολογήσει ο παίκτης μέχρι στιγμής. Στη συνέχεια, έχουμε λογική καταρράκτη, όπου ελέγχουμε αν η φράση έχει ολοκληρωθεί, η λέξη έχει ολοκληρωθεί, η λέξη είναι σωστή ή (τελικά) αν υπάρχει σφάλμα.
Ας αναλύσουμε τον κώδικα! Ξεκινάμε παίρνοντας την τρέχουσα λέξη και την τιμή που έχει πληκτρολογήσει μέχρι στιγμής ο παίκτης. Στη συνέχεια, έχουμε λογική "καταρράκτη", όπου ελέγχουμε αν η φράση έχει ολοκληρωθεί, αν η λέξη έχει ολοκληρωθεί, αν η λέξη είναι σωστή ή (τελικά) αν υπάρχει κάποιο λάθος.
- Η φράση έχει ολοκληρωθεί, υποδεικνύεται από το `typedValue` να είναι ίσο με το `currentWord` και το `wordIndex` να είναι ίσο με ένα λιγότερο από το `length` του `words`
- Η φράση έχει ολοκληρωθεί, κάτι που υποδεικνύεται από το `typedValue` να είναι ίσο με το `currentWord` και το `wordIndex` να είναι ίσο με το μήκος του `words` μείον ένα
- Υπολογίζουμε το `elapsedTime` αφαιρώντας το `startTime` από τον τρέχοντα χρόνο
- Διαιρούμε το `elapsedTime` με 1,000 για να το μετατρέψουμε από χιλιοστά του
- Αποθηκεύστε υψηλές βαθμολογίες χρησιμοποιώντας το [localStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage)
- Διαιρούμε το `elapsedTime` με το 1.000 για να το μετατρέψουμε από χ
## Κουίζ Μετά τη Διάλεξη
## Κουίζ μετά το μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/22)
[Κουίζ μετά τη διάλεξη](https://ff-quizzes.netlify.app/web/quiz/22)
## Ανασκόπηση & Αυτομελέτη
Διαβάστε για [όλα τα διαθέσιμα γεγονότα](https://developer.mozilla.org/docs/Web/Events) που είναι διαθέσιμα στον προγραμματιστή μέσω του προγράμματος περιήγησης, και σκεφτείτε τα σενάρια στα οποία θα χρησιμοποιούσατε το καθένα.
Διαβάστε για [όλα τα διαθέσιμα γεγονότα](https://developer.mozilla.org/docs/Web/Events) που παρέχονται στον προγραμματιστή μέσω του προγράμματος περιήγησης και σκεφτείτε τα σενάρια στα οποία θα χρησιμοποιούσατε το καθένα.
## Εργασία
[Δημιουργήστε ένα νέο παιχνίδι με πληκτρολόγιο](assignment.md)
[Δημιουργήστε ένα νέο παιχνίδι πληκτρολογίου](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "0bb55e0b98600afab801eea115228873",
"translation_date": "2025-08-26T22:37:56+00:00",
"original_hash": "2326d04e194a10aa760b51f5e5a1f61d",
"translation_date": "2025-08-29T07:04:56+00:00",
"source_file": "5-browser-extension/1-about-browsers/README.md",
"language_code": "el"
}
@ -10,11 +10,11 @@ CO_OP_TRANSLATOR_METADATA:
# Έργο Επέκτασης Περιηγητή Μέρος 1: Όλα για τους Περιηγητές
![Σημειώσεις περιηγητή](../../../../translated_images/browser.60317c9be8b7f84adce43e30bff8d47a1ae15793beab762317b2bc6b74337c1a.el.jpg)
> Σημειώσεις από [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
> Σημειώσεις από τον [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
## Ερωτηματολόγιο πριν το μάθημα
## Κουίζ πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/23)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/23)
### Εισαγωγή
@ -28,10 +28,10 @@ CO_OP_TRANSLATOR_METADATA:
✅ Λίγη ιστορία: ο πρώτος περιηγητής ονομαζόταν 'WorldWideWeb' και δημιουργήθηκε από τον Sir Timothy Berners-Lee το 1990.
![πρώτοι περιηγητές](../../../../translated_images/earlybrowsers.d984b711cdf3a42ddac919d46c4b5ca7232f68ccfbd81395e04e5a64c0015277.el.jpg)
> Μερικοί πρώτοι περιηγητές, μέσω [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
![πρώιμοι περιηγητές](../../../../translated_images/earlybrowsers.d984b711cdf3a42ddac919d46c4b5ca7232f68ccfbd81395e04e5a64c0015277.el.jpg)
> Μερικοί πρώιμοι περιηγητές, μέσω της [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
Όταν ένας χρήστης συνδέεται στο διαδίκτυο χρησιμοποιώντας μια διεύθυνση URL (Uniform Resource Locator), συνήθως μέσω του πρωτοκόλλου Hypertext Transfer Protocol με μια διεύθυνση `http` ή `https`, ο περιηγητής επικοινωνεί με έναν διακομιστή ιστού και ανακτά μια ιστοσελίδα.
Όταν ένας χρήστης συνδέεται στο διαδίκτυο χρησιμοποιώντας μια διεύθυνση URL (Uniform Resource Locator), συνήθως μέσω του Hypertext Transfer Protocol με μια διεύθυνση `http` ή `https`, ο περιηγητής επικοινωνεί με έναν διακομιστή ιστού και ανακτά μια ιστοσελίδα.
Σε αυτό το σημείο, η μηχανή απόδοσης του περιηγητή την εμφανίζει στη συσκευή του χρήστη, η οποία μπορεί να είναι κινητό τηλέφωνο, επιτραπέζιος υπολογιστής ή φορητός υπολογιστής.
@ -41,11 +41,11 @@ CO_OP_TRANSLATOR_METADATA:
Ένας πολύ χρήσιμος ιστότοπος που πιθανότατα θα πρέπει να προσθέσετε στους σελιδοδείκτες σας, όποιον περιηγητή κι αν προτιμάτε να χρησιμοποιείτε, είναι το [caniuse.com](https://www.caniuse.com). Όταν δημιουργείτε ιστοσελίδες, είναι πολύ χρήσιμο να χρησιμοποιείτε τις λίστες υποστηριζόμενων τεχνολογιών του caniuse, ώστε να υποστηρίζετε καλύτερα τους χρήστες σας.
✅ Πώς μπορείτε να καταλάβετε ποιοι περιηγητές είναι πιο δημοφιλείς στους χρήστες του ιστότοπού σας; Ελέγξτε τα αναλυτικά σας δεδομένα - μπορείτε να εγκαταστήσετε διάφορα πακέτα αναλυτικών δεδομένων ως μέρος της διαδικασίας ανάπτυξης ιστού, και αυτά θα σας δείξουν ποιοι περιηγητές χρησιμοποιούνται περισσότερο από τους διάφορους δημοφιλείς περιηγητές.
✅ Πώς μπορείτε να καταλάβετε ποιοι περιηγητές είναι πιο δημοφιλείς στη βάση χρηστών του ιστότοπού σας; Ελέγξτε τα αναλυτικά στοιχεία σας - μπορείτε να εγκαταστήσετε διάφορα πακέτα αναλυτικών στοιχείων ως μέρος της διαδικασίας ανάπτυξης ιστού, και αυτά θα σας πουν ποιοι περιηγητές χρησιμοποιούνται περισσότερο από τους διάφορους δημοφιλείς περιηγητές.
## Επεκτάσεις περιηγητή
Γιατί να θέλετε να δημιουργήσετε μια επέκταση περιηγητή; Είναι ένα χρήσιμο εργαλείο που μπορείτε να προσθέσετε στον περιηγητή σας όταν χρειάζεστε γρήγορη πρόσβαση σε εργασίες που τείνετε να επαναλαμβάνετε. Για παράδειγμα, αν χρειάζεται συχνά να ελέγχετε χρώματα στις διάφορες ιστοσελίδες που αλληλεπιδράτε, μπορείτε να εγκαταστήσετε μια επέκταση περιηγητή για επιλογή χρωμάτων. Αν δυσκολεύεστε να θυμάστε κωδικούς πρόσβασης, μπορείτε να χρησιμοποιήσετε μια επέκταση περιηγητή για διαχείριση κωδικών πρόσβασης.
Γιατί να θέλετε να δημιουργήσετε μια επέκταση περιηγητή; Είναι ένα χρήσιμο εργαλείο που μπορείτε να προσθέσετε στον περιηγητή σας όταν χρειάζεστε γρήγορη πρόσβαση σε εργασίες που τείνετε να επαναλαμβάνετε. Για παράδειγμα, αν χρειάζεται να ελέγχετε χρώματα στις διάφορες ιστοσελίδες με τις οποίες αλληλεπιδράτε, μπορείτε να εγκαταστήσετε μια επέκταση περιηγητή για επιλογή χρωμάτων. Αν δυσκολεύεστε να θυμάστε κωδικούς πρόσβασης, μπορείτε να χρησιμοποιήσετε μια επέκταση περιηγητή για διαχείριση κωδικών πρόσβασης.
Οι επεκτάσεις περιηγητή είναι επίσης διασκεδαστικές για ανάπτυξη. Τείνουν να διαχειρίζονται έναν πεπερασμένο αριθμό εργασιών που εκτελούν καλά.
@ -53,7 +53,7 @@ CO_OP_TRANSLATOR_METADATA:
### Εγκατάσταση επεκτάσεων
Πριν ξεκινήσετε την ανάπτυξη, ρίξτε μια ματιά στη διαδικασία δημιουργίας και ανάπτυξης μιας επέκτασης περιηγητή. Παρόλο που κάθε περιηγητής διαφέρει λίγο στον τρόπο που διαχειρίζεται αυτή την εργασία, η διαδικασία είναι παρόμοια στον Chrome και τον Firefox με αυτό το παράδειγμα στον Edge:
Πριν ξεκινήσετε την ανάπτυξη, ρίξτε μια ματιά στη διαδικασία δημιουργίας και ανάπτυξης μιας επέκτασης περιηγητή. Ενώ κάθε περιηγητής διαφέρει λίγο στον τρόπο που διαχειρίζεται αυτή την εργασία, η διαδικασία είναι παρόμοια στον Chrome και τον Firefox με αυτό το παράδειγμα στον Edge:
![στιγμιότυπο οθόνης του περιηγητή Edge που δείχνει την ανοιχτή σελίδα edge://extensions και το ανοιχτό μενού ρυθμίσεων](../../../../translated_images/install-on-edge.d68781acaf0b3d3dada8b7507cde7a64bf74b7040d9818baaa9070668e819f90.el.png)
@ -62,7 +62,7 @@ CO_OP_TRANSLATOR_METADATA:
Στην ουσία, η διαδικασία θα είναι:
- δημιουργήστε την επέκτασή σας χρησιμοποιώντας `npm run build`
- πλοηγηθείτε στον περιηγητή στη σελίδα επεκτάσεων χρησιμοποιώντας το κουμπί "Ρυθμίσεις και περισσότερα" (το εικονίδιο `...`) πάνω δεξιά
- πλοηγηθείτε στον περιηγητή στο πάνελ επεκτάσεων χρησιμοποιώντας το κουμπί "Ρυθμίσεις και περισσότερα" (το εικονίδιο `...`) πάνω δεξιά
- αν είναι νέα εγκατάσταση, επιλέξτε `load unpacked` για να ανεβάσετε μια νέα επέκταση από τον φάκελο δημιουργίας της (στην περίπτωσή μας είναι `/dist`)
- ή, κάντε κλικ στο `reload` αν επαναφορτώνετε την ήδη εγκατεστημένη επέκταση
@ -70,16 +70,16 @@ CO_OP_TRANSLATOR_METADATA:
### Ξεκινήστε
Θα δημιουργήσετε μια επέκταση περιηγητή που εμφανίζει το αποτύπωμα άνθρακα της περιοχής σας, δείχνοντας τη χρήση ενέργειας της περιοχής σας και την πηγή της ενέργειας. Η επέκταση θα έχει μια φόρμα που συλλέγει ένα API key ώστε να μπορείτε να έχετε πρόσβαση στο API του CO2 Signal.
Θα δημιουργήσετε μια επέκταση περιηγητή που εμφανίζει το αποτύπωμα άνθρακα της περιοχής σας, δείχνοντας τη χρήση ενέργειας της περιοχής σας και την πηγή της ενέργειας. Η επέκταση θα έχει μια φόρμα που συλλέγει ένα κλειδί API ώστε να μπορείτε να έχετε πρόσβαση στο API του CO2 Signal.
**Χρειάζεστε:**
- [ένα API key](https://www.co2signal.com/); εισάγετε το email σας στο πλαίσιο αυτής της σελίδας και θα σας σταλεί ένα
- [ένα κλειδί API](https://www.co2signal.com/); εισάγετε το email σας στο πλαίσιο αυτής της σελίδας και θα σας σταλεί ένα
- τον [κωδικό για την περιοχή σας](http://api.electricitymap.org/v3/zones) που αντιστοιχεί στον [Electricity Map](https://www.electricitymap.org/map) (στη Βοστώνη, για παράδειγμα, χρησιμοποιώ 'US-NEISO').
- τον [κώδικα εκκίνησης](../../../../5-browser-extension/start). Κατεβάστε τον φάκελο `start`. Θα ολοκληρώσετε τον κώδικα σε αυτόν τον φάκελο.
- [NPM](https://www.npmjs.com) - Το NPM είναι ένα εργαλείο διαχείρισης πακέτων. Εγκαταστήστε το τοπικά και τα πακέτα που αναφέρονται στο αρχείο `package.json` θα εγκατασταθούν για χρήση από το web asset σας.
- τον [αρχικό κώδικα](../../../../5-browser-extension/start). Κατεβάστε τον φάκελο `start`. Θα ολοκληρώσετε τον κώδικα σε αυτόν τον φάκελο.
- [NPM](https://www.npmjs.com) - Το NPM είναι ένα εργαλείο διαχείρισης πακέτων. Εγκαταστήστε το τοπικά και τα πακέτα που αναφέρονται στο αρχείο `package.json` σας θα εγκατασταθούν για χρήση από το web asset σας.
✅ Μάθετε περισσότερα για τη διαχείριση πακέτων σε αυτό το [εξαιρετικό module εκμάθησης](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
✅ Μάθετε περισσότερα για τη διαχείριση πακέτων σε αυτό το [εξαιρετικό μάθημα Learn](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
Ρίξτε μια ματιά στη βάση κώδικα:
@ -91,13 +91,13 @@ dist
src
-|index.js (ο κώδικας JS σας πηγαίνει εδώ)
✅ Μόλις έχετε το API key και τον κωδικό περιοχής σας έτοιμα, αποθηκεύστε τα κάπου σε μια σημείωση για μελλοντική χρήση.
✅ Μόλις έχετε το κλειδί API και τον κωδικό περιοχής σας έτοιμα, αποθηκεύστε τα κάπου σε μια σημείωση για μελλοντική χρήση.
### Δημιουργήστε το HTML για την επέκταση
Αυτή η επέκταση έχει δύο προβολές. Μία για τη συλλογή του API key και του κωδικού περιοχής:
Αυτή η επέκταση έχει δύο προβολές. Μία για τη συλλογή του κλειδιού API και του κωδικού περιοχής:
![στιγμιότυπο οθόνης της ολοκληρωμένης επέκτασης ανοιχτής σε περιηγητή, που εμφανίζει μια φόρμα με πεδία εισαγωγής για το όνομα περιοχής και το API key.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.el.png)
![στιγμιότυπο οθόνης της ολοκληρωμένης επέκτασης ανοιχτής σε περιηγητή, που εμφανίζει μια φόρμα με πεδία εισαγωγής για το όνομα περιοχής και το κλειδί API.](../../../../translated_images/1.b6da8c1394b07491afeb6b2a8e5aca73ebd3cf478e27bcc9aeabb187e722648e.el.png)
Και η δεύτερη για την εμφάνιση της χρήσης άνθρακα της περιοχής:
@ -105,7 +105,7 @@ src
Ας ξεκινήσουμε δημιουργώντας το HTML για τη φόρμα και μορφοποιώντας το με CSS.
Στον φάκελο `/dist`, θα δημιουργήσετε μια φόρμα και μια περιοχή αποτελεσμάτων. Στο αρχείο `index.html`, συμπληρώστε την περιοχή της φόρμας που έχει καθοριστεί:
Στον φάκελο `/dist`, θα δημιουργήσετε μια φόρμα και μια περιοχή αποτελεσμάτων. Στο αρχείο `index.html`, συμπληρώστε την καθορισμένη περιοχή φόρμας:
```HTML
<form class="form-data" autocomplete="on">
@ -158,9 +158,9 @@ npm install
Ρίξτε μια ματιά σε ένα κατάστημα επεκτάσεων περιηγητή και εγκαταστήστε μία στον περιηγητή σας. Μπορείτε να εξετάσετε τα αρχεία της με ενδιαφέροντες τρόπους. Τι ανακαλύπτετε;
## Ερωτηματολόγιο μετά το μάθημα
## Κουίζ μετά το μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/24)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/24)
## Ανασκόπηση & Αυτομελέτη
@ -178,5 +178,5 @@ npm install
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,29 +1,29 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "e10f168beac4e7b05e30e0eb5c92bf11",
"translation_date": "2025-08-26T22:32:14+00:00",
"original_hash": "a7587943d38d095de8613e1b508609f5",
"translation_date": "2025-08-29T07:08:01+00:00",
"source_file": "5-browser-extension/2-forms-browsers-local-storage/README.md",
"language_code": "el"
}
-->
# Έργο Επέκτασης Περιηγητή Μέρος 2: Κλήση API, χρήση Τοπικής Αποθήκευσης
## Ερωτηματολόγιο πριν το μάθημα
## Κουίζ πριν το μάθημα
[Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/25)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/25)
### Εισαγωγή
Σε αυτό το μάθημα, θα καλέσετε ένα API υποβάλλοντας τη φόρμα της επέκτασης του περιηγητή σας και θα εμφανίσετε τα αποτελέσματα στην επέκταση. Επιπλέον, θα μάθετε πώς μπορείτε να αποθηκεύσετε δεδομένα στην τοπική αποθήκευση του περιηγητή σας για μελλοντική αναφορά και χρήση.
✅ Ακολουθήστε τα αριθμημένα τμήματα στα κατάλληλα αρχεία για να γνωρίζετε πού να τοποθετήσετε τον κώδικα σας.
✅ Ακολουθήστε τα αριθμημένα τμήματα στα κατάλληλα αρχεία για να ξέρετε πού να τοποθετήσετε τον κώδικά σας.
### Ρύθμιση των στοιχείων για χειρισμό στην επέκταση:
### Ρύθμιση στοιχείων για χειρισμό στην επέκταση:
Μέχρι τώρα έχετε δημιουργήσει το HTML για τη φόρμα και το `<div>` των αποτελεσμάτων για την επέκταση του περιηγητή σας. Από εδώ και πέρα, θα χρειαστεί να εργαστείτε στο αρχείο `/src/index.js` και να χτίσετε την επέκταση σας βήμα-βήμα. Ανατρέξτε στο [προηγούμενο μάθημα](../1-about-browsers/README.md) για να ρυθμίσετε το έργο σας και να μάθετε για τη διαδικασία δημιουργίας.
Μέχρι τώρα έχετε δημιουργήσει το HTML για τη φόρμα και το `<div>` των αποτελεσμάτων για την επέκταση του περιηγητή σας. Από εδώ και στο εξής, θα χρειαστεί να εργαστείτε στο αρχείο `/src/index.js` και να χτίσετε την επέκτασή σας βήμα-βήμα. Ανατρέξτε στο [προηγούμενο μάθημα](../1-about-browsers/README.md) για να ρυθμίσετε το έργο σας και να μάθετε για τη διαδικασία δημιουργίας.
Εργαζόμενοι στο αρχείο `index.js`, ξεκινήστε δημιουργώντας μερικές μεταβλητές `const` για να κρατήσετε τις τιμές που σχετίζονται με διάφορα πεδία:
Εργαζόμενοι στο αρχείο `index.js`, ξεκινήστε δημιουργώντας κάποιες μεταβλητές `const` για να κρατήσετε τις τιμές που σχετίζονται με διάφορα πεδία:
```JavaScript
// form fields
@ -41,11 +41,11 @@ const myregion = document.querySelector('.my-region');
const clearBtn = document.querySelector('.clear-btn');
```
Όλα αυτά τα πεδία αναφέρονται μέσω της css class τους, όπως τα ρυθμίσατε στο HTML στο προηγούμενο μάθημα.
Όλα αυτά τα πεδία αναφέρονται από την css κλάση τους, όπως τα ορίσατε στο HTML στο προηγούμενο μάθημα.
### Προσθήκη ακροατών συμβάντων
### Προσθήκη ακροατών
Στη συνέχεια, προσθέστε ακροατές συμβάντων στη φόρμα και στο κουμπί εκκαθάρισης που επαναφέρει τη φόρμα, ώστε αν ένας χρήστης υποβάλει τη φόρμα ή κάνει κλικ στο κουμπί εκκαθάρισης, να συμβεί κάτι, και προσθέστε την κλήση για την αρχικοποίηση της εφαρμογής στο κάτω μέρος του αρχείου:
Στη συνέχεια, προσθέστε ακροατές συμβάντων στη φόρμα και στο κουμπί εκκαθάρισης που επαναφέρει τη φόρμα, ώστε αν ένας χρήστης υποβάλει τη φόρμα ή κάνει κλικ στο κουμπί εκκαθάρισης, να συμβεί κάτι, και προσθέστε την κλήση για την αρχικοποίηση της εφαρμογής στο τέλος του αρχείου:
```JavaScript
form.addEventListener('submit', (e) => handleSubmit(e));
@ -53,9 +53,9 @@ clearBtn.addEventListener('click', (e) => reset(e));
init();
```
✅ Παρατηρήστε τη συντομογραφία που χρησιμοποιείται για την ακρόαση ενός συμβάντος υποβολής ή κλικ και πώς το συμβάν περνάει στις συναρτήσεις handleSubmit ή reset. Μπορείτε να γράψετε το ισοδύναμο αυτής της συντομογραφίας σε μεγαλύτερη μορφή; Ποια προτιμάτε;
✅ Παρατηρήστε τη συντομογραφία που χρησιμοποιείται για την ακρόαση ενός συμβάντος υποβολής ή κλικ και πώς το συμβάν περνάει στις συναρτήσεις `handleSubmit` ή `reset`. Μπορείτε να γράψετε το ισοδύναμο αυτής της συντομογραφίας σε μεγαλύτερη μορφή; Ποια προτιμάτε;
### Δημιουργία της συνάρτησης init() και της συνάρτησης reset():
### Δημιουργία της συνάρτησης init() και reset():
Τώρα θα δημιουργήσετε τη συνάρτηση που αρχικοποιεί την επέκταση, η οποία ονομάζεται init():
@ -93,34 +93,34 @@ function reset(e) {
```
Σε αυτή τη συνάρτηση υπάρχει κάποια ενδιαφέρουσα λογική. Διαβάζοντας την, μπορείτε να δείτε τι συμβαίνει;
Σε αυτή τη συνάρτηση, υπάρχει κάποια ενδιαφέρουσα λογική. Διαβάζοντάς την, μπορείτε να δείτε τι συμβαίνει;
- Δύο `const` δημιουργούνται για να ελέγξουν αν ο χρήστης έχει αποθηκεύσει ένα APIKey και έναν κωδικό περιοχής στην τοπική αποθήκευση.
- Αν κάποιο από αυτά είναι null, εμφανίστε τη φόρμα αλλάζοντας το στυλ της ώστε να εμφανίζεται ως 'block'.
- Κρύψτε την περιοχή αποτελεσμάτων, το μήνυμα φόρτωσης και το clearBtn και ορίστε οποιοδήποτε κείμενο σφάλματος ως κενό.
- Αν υπάρχει κλειδί και περιοχή, ξεκινήστε μια διαδικασία για:
- Κλήση του API για λήψη δεδομένων χρήσης άνθρακα.
- Κρύψτε την περιοχή αποτελεσμάτων.
- Κρύψτε τη φόρμα.
- Εμφανίστε το κουμπί επαναφοράς.
- Δύο `const` ορίζονται για να ελέγξουν αν ο χρήστης έχει αποθηκεύσει ένα APIKey και έναν κωδικό περιοχής στην τοπική αποθήκευση.
- Αν κάποιο από αυτά είναι null, εμφανίστε τη φόρμα αλλάζοντας το στυλ της σε 'block'.
- Κρύψτε τα αποτελέσματα, το φόρτωμα και το clearBtn και ορίστε οποιοδήποτε κείμενο σφάλματος σε κενή συμβολοσειρά.
- Αν υπάρχει κλειδί και περιοχή, ξεκινήστε μια ρουτίνα για:
- Κλήση του API για λήψη δεδομένων κατανάλωσης άνθρακα.
- Απόκρυψη της περιοχής αποτελεσμάτων.
- Απόκρυψη της φόρμας.
- Εμφάνιση του κουμπιού επαναφοράς.
Πριν προχωρήσετε, είναι χρήσιμο να μάθετε για μια πολύ σημαντική έννοια που είναι διαθέσιμη στους περιηγητές: [Τοπική Αποθήκευση](https://developer.mozilla.org/docs/Web/API/Window/localStorage). Η Τοπική Αποθήκευση είναι ένας χρήσιμος τρόπος για να αποθηκεύετε συμβολοσειρές στον περιηγητή ως ζεύγη `key-value`. Αυτός ο τύπος αποθήκευσης ιστού μπορεί να χειριστεί από τη JavaScript για τη διαχείριση δεδομένων στον περιηγητή. Η Τοπική Αποθήκευση δεν λήγει, ενώ η SessionStorage, ένας άλλος τύπος αποθήκευσης ιστού, διαγράφεται όταν κλείνει ο περιηγητής. Οι διάφοροι τύποι αποθήκευσης έχουν πλεονεκτήματα και μειονεκτήματα στη χρήση τους.
Πριν προχωρήσετε, είναι χρήσιμο να μάθετε για μια πολύ σημαντική έννοια που είναι διαθέσιμη στους περιηγητές: [Τοπική Αποθήκευση](https://developer.mozilla.org/docs/Web/API/Window/localStorage). Η Τοπική Αποθήκευση είναι ένας χρήσιμος τρόπος αποθήκευσης συμβολοσειρών στον περιηγητή ως ζεύγος `κλειδί-τιμή`. Αυτός ο τύπος αποθήκευσης ιστού μπορεί να χειριστεί από τη JavaScript για τη διαχείριση δεδομένων στον περιηγητή. Η Τοπική Αποθήκευση δεν λήγει, ενώ η SessionStorage, ένας άλλος τύπος αποθήκευσης ιστού, διαγράφεται όταν κλείνει ο περιηγητής. Οι διάφοροι τύποι αποθήκευσης έχουν πλεονεκτήματα και μειονεκτήματα στη χρήση τους.
> Σημείωση - η επέκταση του περιηγητή σας έχει τη δική της τοπική αποθήκευση· το κύριο παράθυρο του περιηγητή είναι μια διαφορετική περίπτωση και λειτουργεί ξεχωριστά.
> Σημείωση - η επέκταση του περιηγητή σας έχει τη δική της τοπική αποθήκευση· το κύριο παράθυρο του περιηγητή είναι διαφορετική περίπτωση και λειτουργεί ξεχωριστά.
Ορίστε το APIKey σας να έχει μια τιμή συμβολοσειράς, για παράδειγμα, και μπορείτε να δείτε ότι έχει οριστεί στο Edge κάνοντας "επιθεώρηση" μιας ιστοσελίδας (μπορείτε να κάνετε δεξί κλικ σε έναν περιηγητή για επιθεώρηση) και πηγαίνοντας στην καρτέλα Εφαρμογές για να δείτε την αποθήκευση.
Ορίστε το APIKey σας να έχει μια τιμή συμβολοσειράς, για παράδειγμα, και μπορείτε να δείτε ότι έχει οριστεί στον Edge "επιθεωρώντας" μια ιστοσελίδα (μπορείτε να κάνετε δεξί κλικ σε έναν περιηγητή για να επιθεωρήσετε) και πηγαίνοντας στην καρτέλα Εφαρμογές για να δείτε την αποθήκευση.
![Πίνακας τοπικής αποθήκευσης](../../../../translated_images/localstorage.472f8147b6a3f8d141d9551c95a2da610ac9a3c6a73d4a1c224081c98bae09d9.el.png)
✅ Σκεφτείτε καταστάσεις όπου ΔΕΝ θα θέλατε να αποθηκεύσετε κάποια δεδομένα στην Τοπική Αποθήκευση. Γενικά, η τοποθέτηση API Keys στην Τοπική Αποθήκευση είναι κακή ιδέα! Μπορείτε να δείτε γιατί; Στην περίπτωσή μας, καθώς η εφαρμογή μας είναι καθαρά για εκμάθηση και δεν θα αναπτυχθεί σε κατάστημα εφαρμογών, θα χρησιμοποιήσουμε αυτή τη μέθοδο.
✅ Σκεφτείτε καταστάσεις όπου ΔΕΝ θα θέλατε να αποθηκεύσετε κάποια δεδομένα στην Τοπική Αποθήκευση. Γενικά, η τοποθέτηση API Keys στην Τοπική Αποθήκευση είναι κακή ιδέα! Μπορείτε να δείτε γιατί; Στην περίπτωσή μας, δεδομένου ότι η εφαρμογή μας είναι καθαρά για μάθηση και δεν θα αναπτυχθεί σε κατάστημα εφαρμογών, θα χρησιμοποιήσουμε αυτή τη μέθοδο.
Παρατηρήστε ότι χρησιμοποιείτε το Web API για να χειριστείτε την Τοπική Αποθήκευση, είτε χρησιμοποιώντας `getItem()`, `setItem()`, είτε `removeItem()`. Υποστηρίζεται ευρέως στους περιηγητές.
Παρατηρήστε ότι χρησιμοποιείτε το Web API για να χειριστείτε την Τοπική Αποθήκευση, είτε χρησιμοποιώντας `getItem()`, `setItem()`, είτε `removeItem()`. Υποστηρίζεται ευρέως σε όλους τους περιηγητές.
Πριν δημιουργήσετε τη συνάρτηση `displayCarbonUsage()` που καλείται στο `init()`, ας δημιουργήσουμε τη λειτουργικότητα για τη διαχείριση της αρχικής υποβολής φόρμας.
### Διαχείριση της υποβολής φόρμας
### Διαχείριση υποβολής φόρμας
Δημιουργήστε μια συνάρτηση που ονομάζεται `handleSubmit` που δέχεται ένα όρισμα συμβάντος `(e)`. Σταματήστε την εξάπλωση του συμβάντος (σε αυτή την περίπτωση, θέλουμε να σταματήσουμε τον περιηγητή από το να ανανεωθεί) και καλέστε μια νέα συνάρτηση, `setUpUser`, περνώντας τα ορίσματα `apiKey.value` και `region.value`. Με αυτόν τον τρόπο, χρησιμοποιείτε τις δύο τιμές που εισάγονται μέσω της αρχικής φόρμας όταν τα κατάλληλα πεδία είναι συμπληρωμένα.
Δημιουργήστε μια συνάρτηση που ονομάζεται `handleSubmit` που δέχεται ένα όρισμα συμβάντος `(e)`. Σταματήστε τη διάδοση του συμβάντος (σε αυτή την περίπτωση, θέλουμε να σταματήσουμε τον περιηγητή από το να ανανεωθεί) και καλέστε μια νέα συνάρτηση, `setUpUser`, περνώντας τα ορίσματα `apiKey.value` και `region.value`. Με αυτόν τον τρόπο, χρησιμοποιείτε τις δύο τιμές που εισάγονται μέσω της αρχικής φόρμας όταν τα κατάλληλα πεδία είναι συμπληρωμένα.
```JavaScript
function handleSubmit(e) {
@ -129,11 +129,11 @@ function handleSubmit(e) {
}
```
Ανανεώστε τη μνήμη σας - το HTML που ρυθμίσατε στο τελευταίο μάθημα έχει δύο πεδία εισόδου των οποίων οι `τιμές` καταγράφονται μέσω των `const` που δημιουργήσατε στην κορυφή του αρχείου, και είναι και τα δύο `απαιτούμενα`, ώστε ο περιηγητής να σταματά τους χρήστες από την εισαγωγή null τιμών.
Φρεσκάρετε τη μνήμη σας - το HTML που δημιουργήσατε στο τελευταίο μάθημα έχει δύο πεδία εισαγωγής των οποίων οι `τιμές` καταγράφονται μέσω των `const` που ορίσατε στην κορυφή του αρχείου, και είναι και τα δύο `απαιτούμενα`, ώστε ο περιηγητής να εμποδίζει τους χρήστες από το να εισάγουν κενές τιμές.
### Ρύθμιση του χρήστη
### Ρύθμιση χρήστη
Προχωρώντας στη συνάρτηση `setUpUser`, εδώ είναι όπου ορίζετε τις τιμές τοπικής αποθήκευσης για το apiKey και το regionName. Προσθέστε μια νέα συνάρτηση:
Προχωρώντας στη συνάρτηση `setUpUser`, εδώ είναι που ορίζετε τις τιμές τοπικής αποθήκευσης για το apiKey και το regionName. Προσθέστε μια νέα συνάρτηση:
```JavaScript
function setUpUser(apiKey, regionName) {
@ -149,15 +149,15 @@ function setUpUser(apiKey, regionName) {
Αυτή η συνάρτηση ορίζει ένα μήνυμα φόρτωσης για εμφάνιση ενώ καλείται το API. Σε αυτό το σημείο, έχετε φτάσει στη δημιουργία της πιο σημαντικής συνάρτησης αυτής της επέκτασης περιηγητή!
### Εμφάνιση Χρήσης Άνθρακα
### Εμφάνιση Κατανάλωσης Άνθρακα
Τέλος, είναι ώρα να κάνετε ερώτημα στο API!
Τέλος, ήρθε η ώρα να κάνετε ερώτημα στο API!
Πριν προχωρήσουμε, θα πρέπει να συζητήσουμε για τα APIs. Τα APIs, ή [Διεπαφές Προγραμματισμού Εφαρμογών](https://www.webopedia.com/TERM/A/API.html), είναι ένα κρίσιμο στοιχείο της εργαλειοθήκης ενός προγραμματιστή ιστού. Παρέχουν τυποποιημένους τρόπους για τα προγράμματα να αλληλεπιδρούν και να συνδέονται μεταξύ τους. Για παράδειγμα, αν δημιουργείτε μια ιστοσελίδα που χρειάζεται να κάνει ερώτημα σε μια βάση δεδομένων, κάποιος μπορεί να έχει δημιουργήσει ένα API για να χρησιμοποιήσετε. Ενώ υπάρχουν πολλοί τύποι APIs, ένας από τους πιο δημοφιλείς είναι ένα [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
Πριν προχωρήσουμε, ας συζητήσουμε για τα APIs. Τα APIs, ή [Διεπαφές Προγραμματισμού Εφαρμογών](https://www.webopedia.com/TERM/A/API.html), είναι ένα κρίσιμο στοιχείο στη φαρέτρα ενός προγραμματιστή ιστού. Παρέχουν τυποποιημένους τρόπους για τα προγράμματα να αλληλεπιδρούν και να διασυνδέονται μεταξύ τους. Για παράδειγμα, αν δημιουργείτε έναν ιστότοπο που χρειάζεται να κάνει ερώτημα σε μια βάση δεδομένων, κάποιος μπορεί να έχει δημιουργήσει ένα API για να χρησιμοποιήσετε. Ενώ υπάρχουν πολλοί τύποι APIs, ένας από τους πιο δημοφιλείς είναι ένα [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
Ο όρος 'REST' σημαίνει 'Μεταφορά Κατάστασης Αναπαράστασης' και περιλαμβάνει τη χρήση διαμορφωμένων URLs για την ανάκτηση δεδομένων. Κάντε λίγη έρευνα για τους διάφορους τύπους APIs που είναι διαθέσιμοι στους προγραμματιστές. Ποια μορφή σας φαίνεται πιο ελκυστική;
Ο όρος 'REST' σημαίνει 'Μεταφορά Αναπαραστασιακής Κατάστασης' και περιλαμβάνει τη χρήση διαμορφωμένων URLs για την ανάκτηση δεδομένων. Κάντε λίγη έρευνα για τους διάφορους τύπους APIs που είναι διαθέσιμοι στους προγραμματιστές. Ποια μορφή σας ελκύει;
Υπάρχουν σημαντικά πράγματα που πρέπει να σημειώσετε για αυτή τη συνάρτηση. Πρώτον, παρατηρήστε τη λέξη-κλειδί [`async`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Γράφοντας τις συναρτήσεις σας ώστε να λειτουργούν ασύγχρονα σημαίνει ότι περιμένουν μια ενέργεια, όπως η επιστροφή δεδομένων, να ολοκληρωθεί πριν συνεχίσουν.
Υπάρχουν σημαντικά πράγματα που πρέπει να σημειώσετε για αυτή τη συνάρτηση. Πρώτον, παρατηρήστε τη λέξη-κλειδί [`async`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Η συγγραφή των συναρτήσεών σας ώστε να εκτελούνται ασύγχρονα σημαίνει ότι περιμένουν μια ενέργεια, όπως η επιστροφή δεδομένων, να ολοκληρωθεί πριν συνεχίσουν.
Δείτε ένα σύντομο βίντεο για το `async`:
@ -207,14 +207,14 @@ async function displayCarbonUsage(apiKey, region) {
Αυτή είναι μια μεγάλη συνάρτηση. Τι συμβαίνει εδώ;
- Ακολουθώντας τις βέλτιστες πρακτικές, χρησιμοποιείτε τη λέξη-κλειδί `async` για να κάνετε αυτή τη συνάρτηση να λειτουργεί ασύγχρονα. Η συνάρτηση περιέχει ένα μπλοκ `try/catch`, καθώς θα επιστρέψει μια υπόσχεση όταν το API επιστρέψει δεδομένα. Επειδή δεν έχετε έλεγχο στην ταχύτητα με την οποία το API θα απαντήσει (μπορεί να μην απαντήσει καθόλου!), πρέπει να χειριστείτε αυτή την αβεβαιότητα καλώντας το ασύγχρονα.
- Κάνετε ερώτημα στο API co2signal για να λάβετε τα δεδομένα της περιοχής σας, χρησιμοποιώντας το API Key σας. Για να χρησιμοποιήσετε αυτό το κλειδί, πρέπει να χρησιμοποιήσετε έναν τύπο αυθεντικοποίησης στις παραμέτρους της κεφαλίδας σας.
- Μόλις το API απαντήσει, αναθέτετε διάφορα στοιχεία των δεδομένων της απάντησής του στα μέρη της οθόνης σας που ρυθμίσατε για να εμφανίσετε αυτά τα δεδομένα.
- Ακολουθώντας τις βέλτιστες πρακτικές, χρησιμοποιείτε τη λέξη-κλειδί `async` για να κάνετε αυτή τη συνάρτηση να λειτουργεί ασύγχρονα. Η συνάρτηση περιέχει ένα μπλοκ `try/catch`, καθώς θα επιστρέψει μια υπόσχεση όταν το API επιστρέψει δεδομένα. Επειδή δεν έχετε έλεγχο στην ταχύτητα με την οποία θα απαντήσει το API (μπορεί να μην απαντήσει καθόλου!), πρέπει να χειριστείτε αυτή την αβεβαιότητα καλώντας το ασύγχρονα.
- Κάνετε ερώτημα στο API co2signal για να λάβετε δεδομένα της περιοχής σας, χρησιμοποιώντας το API Key σας. Για να χρησιμοποιήσετε αυτό το κλειδί, πρέπει να χρησιμοποιήσετε έναν τύπο αυθεντικοποίησης στις παραμέτρους κεφαλίδας.
- Μόλις το API απαντήσει, αναθέτετε διάφορα στοιχεία των δεδομένων απόκρισης στα μέρη της οθόνης που ορίσατε για να εμφανίσετε αυτά τα δεδομένα.
- Αν υπάρχει σφάλμα ή αν δεν υπάρχει αποτέλεσμα, εμφανίζετε ένα μήνυμα σφάλματος.
Η χρήση ασύγχρονων προτύπων προγραμματισμού είναι ένα ακόμη πολύ χρήσιμο εργαλείο στην εργαλειοθήκη σας. Διαβάστε [για τους διάφορους τρόπους](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) που μπορείτε να διαμορφώσετε αυτόν τον τύπο κώδικα.
Η χρήση ασύγχρονων προτύπων προγραμματισμού είναι ένα ακόμη πολύ χρήσιμο εργαλείο στη φαρέτρα σας. Διαβάστε [για τους διάφορους τρόπους](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) που μπορείτε να διαμορφώσετε αυτόν τον τύπο κώδικα.
Συγχαρητήρια! Αν δημιουργήσετε την επέκτασή σας (`npm run build`) και την ανανεώσετε στον πίνακα επεκτάσεων σας, έχετε μια λειτουργική επέκταση! Το μόνο πράγμα που δεν λειτουργεί είναι το εικονίδιο, και θα το διορθώσετε στο επόμενο μάθημα.
Συγχαρητήρια! Αν δημιουργήσετε την επέκτασή σας (`npm run build`) και την ανανεώσετε στον πίνακα επεκτάσεων, έχετε μια λειτουργική επέκταση! Το μόνο που δεν λειτουργεί είναι το εικονίδιο, και θα το διορθώσετε στο επόμενο μάθημα.
---
@ -222,19 +222,19 @@ async function displayCarbonUsage(apiKey, region) {
Έχουμε συζητήσει διάφορους τύπους API μέχρι τώρα σε αυτά τα μαθήματα. Επιλέξτε ένα web API και ερευνήστε σε βάθος τι προσφέρει. Για παράδειγμα, ρίξτε μια ματιά στα APIs που είναι διαθέσιμα στους περιηγητές, όπως το [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API). Τι κάνει ένα API εξαιρετικό κατά τη γνώμη σας;
## Ερωτηματολόγιο μετά το μάθημα
## Κουίζ μετά το μάθημα
[Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/26)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/26)
## Ανασκόπηση & Αυτομελέτη
Μάθατε για την Τοπική Αποθήκευση και τα APIs σε αυτό το μάθημα, και τα δύο πολύ χρήσιμα για τον επαγγελματία προγραμματιστή ιστού. Μπορείτε να σκεφτείτε πώς αυτά τα δύο πράγματα συνεργάζονται; Σκεφτείτε πώς θα σχεδιάζατε μια ιστοσελίδα που θα αποθηκεύει αντικείμενα για χρήση από ένα API.
Μάθατε για την Τοπική Αποθήκευση και τα APIs σε αυτό το μάθημα, και τα δύο πολύ χρήσιμα για τον επαγγελματία προγραμματιστή ιστού. Μπορείτε να σκεφτείτε πώς αυτά τα δύο πράγματα συνεργάζονται; Σκεφτείτε πώς θα σχεδιάζατε έναν ιστότοπο που θα αποθήκευε αντικείμενα για χρήση από ένα API.
## Εργασία
[Adopt an API](assignment.md)
[Υιοθετήστε ένα API](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "f198c6b817b4b2a99749f4662e7cae98",
"translation_date": "2025-08-26T22:41:25+00:00",
"original_hash": "49b58721a71cfda824e2f3e1f46908c6",
"translation_date": "2025-08-29T07:06:23+00:00",
"source_file": "5-browser-extension/3-background-tasks-and-performance/README.md",
"language_code": "el"
}
@ -15,29 +15,29 @@ CO_OP_TRANSLATOR_METADATA:
### Εισαγωγή
Στα δύο τελευταία μαθήματα αυτής της ενότητας, μάθατε πώς να δημιουργείτε μια φόρμα και μια περιοχή εμφάνισης για δεδομένα που λαμβάνονται από ένα API. Είναι ένας πολύ τυπικός τρόπος δημιουργίας παρουσίας στο διαδίκτυο. Μάθατε επίσης πώς να χειρίζεστε την ασύγχρονη λήψη δεδομένων. Η επέκταση του περιηγητή σας είναι σχεδόν ολοκληρωμένη.
Στα δύο τελευταία μαθήματα αυτής της ενότητας, μάθατε πώς να δημιουργείτε μια φόρμα και μια περιοχή εμφάνισης για δεδομένα που λαμβάνονται από ένα API. Είναι ένας πολύ τυπικός τρόπος δημιουργίας παρουσίας στον ιστό. Μάθατε επίσης πώς να χειρίζεστε την ασύγχρονη λήψη δεδομένων. Η επέκταση του περιηγητή σας είναι σχεδόν ολοκληρωμένη.
Απομένει να διαχειριστείτε κάποιες εργασίες υποβάθρου, όπως η ανανέωση του χρώματος του εικονιδίου της επέκτασης, οπότε είναι μια εξαιρετική στιγμή να μιλήσουμε για το πώς ο περιηγητής διαχειρίζεται αυτού του είδους τις εργασίες. Ας σκεφτούμε αυτές τις εργασίες του περιηγητή στο πλαίσιο της απόδοσης των διαδικτυακών σας στοιχείων καθώς τα δημιουργείτε.
Απομένει να διαχειριστείτε κάποιες εργασίες υποβάθρου, όπως η ανανέωση του χρώματος του εικονιδίου της επέκτασης, οπότε είναι μια εξαιρετική στιγμή να μιλήσουμε για το πώς ο περιηγητής διαχειρίζεται αυτού του είδους τις εργασίες. Ας σκεφτούμε αυτές τις εργασίες του περιηγητή στο πλαίσιο της απόδοσης των στοιχείων του ιστότοπού σας καθώς τα δημιουργείτε.
## Βασικές Αρχές Απόδοσης Ιστού
## Βασικά Στοιχεία Απόδοσης Ιστού
> "Η απόδοση μιας ιστοσελίδας αφορά δύο πράγματα: πόσο γρήγορα φορτώνει η σελίδα και πόσο γρήγορα εκτελείται ο κώδικας σε αυτήν." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
> "Η απόδοση ενός ιστότοπου αφορά δύο πράγματα: πόσο γρήγορα φορτώνει η σελίδα και πόσο γρήγορα εκτελείται ο κώδικας σε αυτήν." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
Το θέμα του πώς να κάνετε τις ιστοσελίδες σας εξαιρετικά γρήγορες σε κάθε είδους συσκευές, για κάθε είδους χρήστες, σε κάθε είδους καταστάσεις, είναι αναμενόμενα εκτενές. Ακολουθούν ορισμένα σημεία που πρέπει να έχετε υπόψη σας καθώς δημιουργείτε είτε ένα τυπικό διαδικτυακό έργο είτε μια επέκταση περιηγητή.
Το θέμα του πώς να κάνετε τους ιστότοπούς σας εξαιρετικά γρήγορους σε κάθε είδους συσκευές, για κάθε είδους χρήστες, σε κάθε είδους καταστάσεις, είναι αναμενόμενα εκτενές. Ακολουθούν ορισμένα σημεία που πρέπει να έχετε υπόψη σας καθώς δημιουργείτε είτε ένα τυπικό έργο ιστού είτε μια επέκταση περιηγητή.
Το πρώτο πράγμα που πρέπει να κάνετε για να διασφαλίσετε ότι ο ιστότοπός σας λειτουργεί αποτελεσματικά είναι να συλλέξετε δεδομένα σχετικά με την απόδοσή του. Το πρώτο μέρος για να το κάνετε αυτό είναι στα εργαλεία προγραμματιστών του περιηγητή σας. Στον Edge, μπορείτε να επιλέξετε το κουμπί "Ρυθμίσεις και περισσότερα" (το εικονίδιο με τις τρεις τελείες στην επάνω δεξιά γωνία του περιηγητή) και στη συνέχεια να μεταβείτε στα Περισσότερα Εργαλεία > Εργαλεία Προγραμματιστών και να ανοίξετε την καρτέλα Απόδοση. Μπορείτε επίσης να χρησιμοποιήσετε τις συντομεύσεις πληκτρολογίου `Ctrl` + `Shift` + `I` στα Windows ή `Option` + `Command` + `I` στο Mac για να ανοίξετε τα εργαλεία προγραμματιστών.
Το πρώτο πράγμα που πρέπει να κάνετε για να διασφαλίσετε ότι ο ιστότοπός σας λειτουργεί αποτελεσματικά είναι να συλλέξετε δεδομένα σχετικά με την απόδοσή του. Το πρώτο μέρος για να το κάνετε αυτό είναι στα εργαλεία προγραμματιστών του περιηγητή σας. Στον Edge, μπορείτε να επιλέξετε το κουμπί "Ρυθμίσεις και περισσότερα" (το εικονίδιο με τις τρεις τελείες επάνω δεξιά στον περιηγητή) και στη συνέχεια να μεταβείτε στα Περισσότερα Εργαλεία > Εργαλεία Προγραμματιστών και να ανοίξετε την καρτέλα Απόδοση. Μπορείτε επίσης να χρησιμοποιήσετε τις συντομεύσεις πληκτρολογίου `Ctrl` + `Shift` + `I` στα Windows ή `Option` + `Command` + `I` στο Mac για να ανοίξετε τα εργαλεία προγραμματιστών.
Η καρτέλα Απόδοση περιέχει ένα εργαλείο Προφίλ. Ανοίξτε έναν ιστότοπο (δοκιμάστε, για παράδειγμα, [https://www.microsoft.com](https://www.microsoft.com/?WT.mc_id=academic-77807-sagibbon)) και κάντε κλικ στο κουμπί 'Εγγραφή', στη συνέχεια ανανεώστε τον ιστότοπο. Σταματήστε την εγγραφή οποιαδήποτε στιγμή και θα μπορείτε να δείτε τις ρουτίνες που δημιουργούνται για 'script', 'render' και 'paint' του ιστότοπου:
Η καρτέλα Απόδοση περιέχει ένα εργαλείο Προφίλ. Ανοίξτε έναν ιστότοπο (δοκιμάστε, για παράδειγμα, [https://www.microsoft.com](https://www.microsoft.com/?WT.mc_id=academic-77807-sagibbon)) και κάντε κλικ στο κουμπί 'Εγγραφή', στη συνέχεια ανανεώστε τον ιστότοπο. Σταματήστε την εγγραφή οποιαδήποτε στιγμή και θα μπορείτε να δείτε τις διαδικασίες που δημιουργούνται για να 'σενάριο', 'απόδοση' και 'ζωγραφική' του ιστότοπου:
![Edge profiler](../../../../translated_images/profiler.5a4a62479c5df01cfec9aab74173dba13f91d2c968e1a1ae434c26165792df15.el.png)
✅ Επισκεφθείτε την [Τεκμηρίωση της Microsoft](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) για την καρτέλα Απόδοση στον Edge.
✅ Επισκεφθείτε την [Τεκμηρίωση της Microsoft](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) σχετικά με την καρτέλα Απόδοσης στον Edge
> Συμβουλή: για να έχετε μια ακριβή μέτρηση του χρόνου εκκίνησης του ιστότοπού σας, καθαρίστε την προσωρινή μνήμη του περιηγητή σας.
> Συμβουλή: για να έχετε μια ακριβή μέτρηση του χρόνου εκκίνησης του ιστότοπού σας, καθαρίστε την προσωρινή μνήμη του περιηγητή σας
Επιλέξτε στοιχεία της χρονογραμμής προφίλ για να εστιάσετε σε γεγονότα που συμβαίνουν ενώ φορτώνει η σελίδα σας.
Πάρτε ένα στιγμιότυπο της απόδοσης της σελίδας σας επιλέγοντας ένα μέρος της χρονογραμμής προφίλ και κοιτάζοντας το παράθυρο σύνοψης:
Αποκτήστε μια στιγμιότυπο της απόδοσης της σελίδας σας επιλέγοντας ένα μέρος της χρονογραμμής προφίλ και κοιτάζοντας το παράθυρο σύνοψης:
![Edge profiler snapshot](../../../../translated_images/snapshot.97750180ebcad73794a3594b36925eb5c8dbaac9e03fec7f9b974188c9ac63c7.el.png)
@ -51,17 +51,17 @@ CO_OP_TRANSLATOR_METADATA:
Γενικά, υπάρχουν ορισμένες "προβληματικές περιοχές" που κάθε προγραμματιστής ιστού πρέπει να παρακολουθεί κατά τη δημιουργία ενός ιστότοπου για να αποφύγει δυσάρεστες εκπλήξεις όταν έρθει η ώρα να τον αναπτύξει σε παραγωγή.
**Μεγέθη στοιχείων**: Το διαδίκτυο έχει γίνει πιο 'βαρύ' και, επομένως, πιο αργό τα τελευταία χρόνια. Μέρος αυτού του βάρους έχει να κάνει με τη χρήση εικόνων.
**Μεγέθη στοιχείων**: Ο ιστός έχει γίνει πιο 'βαρύς' και, επομένως, πιο αργός τα τελευταία χρόνια. Μέρος αυτού του βάρους έχει να κάνει με τη χρήση εικόνων.
✅ Αναζητήστε στο [Internet Archive](https://httparchive.org/reports/page-weight) μια ιστορική άποψη του βάρους των σελίδων και περισσότερα.
Μια καλή πρακτική είναι να διασφαλίσετε ότι οι εικόνες σας είναι βελτιστοποιημένες και παραδίδονται στο σωστό μέγεθος και ανάλυση για τους χρήστες σας.
**Περιηγήσεις στο DOM**: Ο περιηγητής πρέπει να δημιουργήσει το Μοντέλο Αντικειμένου Εγγράφου (DOM) βάσει του κώδικα που γράφετε, οπότε είναι προς το συμφέρον της καλής απόδοσης της σελίδας να διατηρείτε τις ετικέτες σας ελάχιστες, χρησιμοποιώντας και μορφοποιώντας μόνο ό,τι χρειάζεται η σελίδα. Σε αυτό το σημείο, το υπερβολικό CSS που σχετίζεται με μια σελίδα θα μπορούσε να βελτιστοποιηθεί. Στυλ που χρειάζονται μόνο σε μία σελίδα δεν χρειάζεται να περιλαμβάνονται στο κύριο φύλλο στυλ, για παράδειγμα.
**Περιηγήσεις DOM**: Ο περιηγητής πρέπει να δημιουργήσει το Μοντέλο Αντικειμένου Εγγράφου (DOM) βάσει του κώδικα που γράφετε, οπότε είναι προς το συμφέρον της καλής απόδοσης της σελίδας να διατηρείτε τις ετικέτες σας ελάχιστες, χρησιμοποιώντας και στυλιζάροντας μόνο ό,τι χρειάζεται η σελίδα. Σε αυτό το σημείο, το υπερβολικό CSS που σχετίζεται με μια σελίδα θα μπορούσε να βελτιστοποιηθεί. Στυλ που χρειάζονται μόνο σε μία σελίδα δεν χρειάζεται να περιλαμβάνονται στο κύριο φύλλο στυλ, για παράδειγμα.
**JavaScript**: Κάθε προγραμματιστής JavaScript πρέπει να παρακολουθεί 'scripts που μπλοκάρουν την απόδοση', τα οποία πρέπει να φορτωθούν πριν ο υπόλοιπος DOM μπορέσει να περιηγηθεί και να ζωγραφιστεί στον περιηγητή. Σκεφτείτε να χρησιμοποιήσετε `defer` με τα ενσωματωμένα scripts σας (όπως γίνεται στην ενότητα Terrarium).
**JavaScript**: Κάθε προγραμματιστής JavaScript πρέπει να παρακολουθεί 'σενάρια που μπλοκάρουν την απόδοση', τα οποία πρέπει να φορτωθούν πριν ο υπόλοιπος DOM μπορέσει να περιηγηθεί και να ζωγραφιστεί στον περιηγητή. Σκεφτείτε να χρησιμοποιήσετε `defer` με τα ενσωματωμένα σενάριά σας (όπως γίνεται στην ενότητα Terrarium).
✅ Δοκιμάστε μερικούς ιστότοπους σε έναν [ιστότοπο δοκιμής ταχύτητας](https://www.webpagetest.org/) για να μάθετε περισσότερα σχετικά με τους συνήθεις ελέγχους που γίνονται για να προσδιοριστεί η απόδοση του ιστότοπου.
✅ Δοκιμάστε μερικούς ιστότοπους σε έναν [ιστότοπο δοκιμής ταχύτητας](https://www.webpagetest.org/) για να μάθετε περισσότερα σχετικά με τους κοινούς ελέγχους που γίνονται για να προσδιοριστεί η απόδοση του ιστότοπου.
Τώρα που έχετε μια ιδέα για το πώς ο περιηγητής αποδίδει τα στοιχεία που του στέλνετε, ας δούμε τα τελευταία πράγματα που πρέπει να κάνετε για να ολοκληρώσετε την επέκτασή σας:
@ -88,19 +88,19 @@ function calculateColor(value) {
}
```
Τι συμβαίνει εδώ; Δίνετε μια τιμή (την ένταση άνθρακα) από την κλήση API που ολοκληρώσατε στο προηγούμενο μάθημα και στη συνέχεια υπολογίζετε πόσο κοντά είναι η τιμή της στον δείκτη που παρουσιάζεται στον πίνακα χρωμάτων. Στη συνέχεια, στέλνετε αυτήν την πιο κοντινή τιμή χρώματος στο chrome runtime.
Τι συμβαίνει εδώ; Δίνετε μια τιμή (την ένταση του άνθρακα) από την κλήση API που ολοκληρώσατε στο τελευταίο μάθημα και στη συνέχεια υπολογίζετε πόσο κοντά είναι η τιμή της στον δείκτη που παρουσιάζεται στον πίνακα χρωμάτων. Στη συνέχεια, στέλνετε αυτήν την πλησιέστερη τιμή χρώματος στο chrome runtime.
Το chrome.runtime έχει [ένα API](https://developer.chrome.com/extensions/runtime) που χειρίζεται κάθε είδους εργασίες υποβάθρου, και η επέκτασή σας το αξιοποιεί:
> "Χρησιμοποιήστε το chrome.runtime API για να ανακτήσετε τη σελίδα υποβάθρου, να επιστρέψετε λεπτομέρειες σχετικά με το manifest και να ακούσετε και να απαντήσετε σε γεγονότα στον κύκλο ζωής της εφαρμογής ή της επέκτασης. Μπορείτε επίσης να χρησιμοποιήσετε αυτό το API για να μετατρέψετε τη σχετική διαδρομή των URL σε πλήρως προσδιορισμένα URL."
> "Χρησιμοποιήστε το API chrome.runtime για να ανακτήσετε τη σελίδα υποβάθρου, να επιστρέψετε λεπτομέρειες σχετικά με το manifest και να ακούσετε και να απαντήσετε σε γεγονότα στον κύκλο ζωής της εφαρμογής ή της επέκτασης. Μπορείτε επίσης να χρησιμοποιήσετε αυτό το API για να μετατρέψετε τη σχετική διαδρομή των URL σε πλήρως προσδιορισμένα URL."
✅ Εάν αναπτύσσετε αυτήν την επέκταση περιηγητή για τον Edge, μπορεί να σας εκπλήξει ότι χρησιμοποιείτε ένα API του chrome. Οι νεότερες εκδόσεις του περιηγητή Edge λειτουργούν στη μηχανή περιήγησης Chromium, οπότε μπορείτε να αξιοποιήσετε αυτά τα εργαλεία.
> Σημείωση: Εάν θέλετε να κάνετε προφίλ μιας επέκτασης περιηγητή, ανοίξτε τα εργαλεία προγραμματιστών από την ίδια την επέκταση, καθώς είναι μια ξεχωριστή περίπτωση περιηγητή.
> Σημείωση: Εάν θέλετε να κάνετε προφίλ μιας επέκτασης περιηγητή, ανοίξτε τα εργαλεία προγραμματιστών από την ίδια την επέκταση, καθώς είναι μια ξεχωριστή παρουσία περιηγητή.
### Ορισμός προεπιλεγμένου χρώματος εικονιδίου
Τώρα, στη συνάρτηση `init()`, ορίστε το εικονίδιο να είναι γενικά πράσινο για αρχή καλώντας ξανά τη δράση `updateIcon` του chrome:
Τώρα, στη συνάρτηση `init()`, ορίστε το εικονίδιο να είναι γενικά πράσινο για αρχή, καλώντας ξανά τη δράση `updateIcon` του chrome:
```JavaScript
chrome.runtime.sendMessage({
@ -120,7 +120,7 @@ chrome.runtime.sendMessage({
calculateColor(CO2);
```
Και τέλος, στο `/dist/background.js`, προσθέστε τον ακροατή για αυτές τις κλήσεις ενεργειών υποβάθρου:
Και τέλος, στο `/dist/background.js`, προσθέστε τον ακροατή για αυτές τις κλήσεις δράσης υποβάθρου:
```JavaScript
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
@ -162,13 +162,13 @@ function drawIcon(value) {
## Ανασκόπηση & Αυτομελέτη
Σκεφτείτε να εγγραφείτε σε ένα [newsletter για την απόδοση](https://perf.email/).
Σκεφτείτε να εγγραφείτε σε ένα [newsletter απόδοσης](https://perf.email/)
Ερευνήστε μερικούς από τους τρόπους με τους οποίους οι περιηγητές αξιολογούν την απόδοση ιστού κοιτάζοντας τις καρτέλες απόδοσης στα εργαλεία ιστού τους. Βρίσκετε κάποιες σημαντικές διαφορές;
## Εργασία
[Αναλύστε έναν ιστότοπο για την απόδοση](assignment.md)
[Αναλύστε έναν ιστότοπο για απόδοση](assignment.md)
---

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "d9da6dc61fb712b29f65e108c79b8a5d",
"translation_date": "2025-08-26T22:05:23+00:00",
"original_hash": "979cfcce2413a87d9e4c67eb79234bc3",
"translation_date": "2025-08-29T07:11:51+00:00",
"source_file": "6-space-game/1-introduction/README.md",
"language_code": "el"
}
@ -11,36 +11,36 @@ CO_OP_TRANSLATOR_METADATA:
![video](../../../../6-space-game/images/pewpew.gif)
## Ερωτηματολόγιο Πριν το Μάθημα
## Κουίζ πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/29)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/29)
### Κληρονομικότητα και Σύνθεση στην ανάπτυξη παιχνιδιών
Στα προηγούμενα μαθήματα, δεν υπήρχε μεγάλη ανάγκη να ανησυχείτε για την αρχιτεκτονική σχεδίαση των εφαρμογών που δημιουργήσατε, καθώς τα έργα ήταν πολύ μικρής κλίμακας. Ωστόσο, όταν οι εφαρμογές σας μεγαλώνουν σε μέγεθος και εύρος, οι αρχιτεκτονικές αποφάσεις γίνονται πιο σημαντικές. Υπάρχουν δύο κύριες προσεγγίσεις για τη δημιουργία μεγαλύτερων εφαρμογών στη JavaScript: *σύνθεση* ή *κληρονομικότητα*. Υπάρχουν πλεονεκτήματα και μειονεκτήματα και στις δύο, αλλά ας τις εξηγήσουμε μέσα από το πλαίσιο ενός παιχνιδιού.
Στα προηγούμενα μαθήματα, δεν υπήρχε μεγάλη ανάγκη να ανησυχείτε για την αρχιτεκτονική σχεδίαση των εφαρμογών που δημιουργούσατε, καθώς τα έργα ήταν μικρής κλίμακας. Ωστόσο, όταν οι εφαρμογές σας μεγαλώνουν σε μέγεθος και εύρος, οι αρχιτεκτονικές αποφάσεις γίνονται πιο σημαντικές. Υπάρχουν δύο κύριες προσεγγίσεις για τη δημιουργία μεγαλύτερων εφαρμογών στη JavaScript: *σύνθεση* ή *κληρονομικότητα*. Υπάρχουν πλεονεκτήματα και μειονεκτήματα και στις δύο, αλλά ας τις εξηγήσουμε μέσα από το πλαίσιο ενός παιχνιδιού.
✅ Ένα από τα πιο διάσημα βιβλία προγραμματισμού που έχουν γραφτεί ποτέ αφορά τα [σχεδιαστικά μοτίβα](https://en.wikipedia.org/wiki/Design_Patterns).
Σε ένα παιχνίδι έχετε `game objects`, δηλαδή αντικείμενα που υπάρχουν στην οθόνη. Αυτό σημαίνει ότι έχουν μια θέση σε ένα καρτεσιανό σύστημα συντεταγμένων, που χαρακτηρίζεται από τις συντεταγμένες `x` και `y`. Καθώς αναπτύσσετε ένα παιχνίδι, θα παρατηρήσετε ότι όλα τα αντικείμενα του παιχνιδιού σας έχουν μια τυπική ιδιότητα, κοινή για κάθε παιχνίδι που δημιουργείτε, δηλαδή στοιχεία που είναι:
Σε ένα παιχνίδι, έχετε `αντικείμενα παιχνιδιού`, τα οποία είναι αντικείμενα που υπάρχουν στην οθόνη. Αυτό σημαίνει ότι έχουν μια θέση σε ένα καρτεσιανό σύστημα συντεταγμένων, που χαρακτηρίζεται από τις συντεταγμένες `x` και `y`. Καθώς αναπτύσσετε ένα παιχνίδι, θα παρατηρήσετε ότι όλα τα αντικείμενα παιχνιδιού έχουν μια τυπική ιδιότητα, κοινή για κάθε παιχνίδι που δημιουργείτε, δηλαδή στοιχεία που είναι:
- **βασισμένα στη θέση** Τα περισσότερα, αν όχι όλα, τα στοιχεία του παιχνιδιού βασίζονται στη θέση. Αυτό σημαίνει ότι έχουν μια θέση, ένα `x` και ένα `y`.
- **κινούμενα** Αυτά είναι αντικείμενα που μπορούν να μετακινηθούν σε μια νέα θέση. Συνήθως είναι ένας ήρωας, ένα τέρας ή ένας NPC (χαρακτήρας που δεν ελέγχεται από τον παίκτη), αλλά όχι, για παράδειγμα, ένα στατικό αντικείμενο όπως ένα δέντρο.
- **βασισμένα στη θέση** Τα περισσότερα, αν όχι όλα, τα στοιχεία του παιχνιδιού βασίζονται στη θέση. Αυτό σημαίνει ότι έχουν μια θέση, `x` και `y`.
- **κινητά** Αυτά είναι αντικείμενα που μπορούν να μετακινηθούν σε μια νέα θέση. Συνήθως είναι ένας ήρωας, ένα τέρας ή ένας NPC (χαρακτήρας που δεν ελέγχεται από τον παίκτη), αλλά όχι, για παράδειγμα, ένα στατικό αντικείμενο όπως ένα δέντρο.
- **αυτοκαταστρεφόμενα** Αυτά τα αντικείμενα υπάρχουν μόνο για μια συγκεκριμένη χρονική περίοδο πριν προγραμματιστούν για διαγραφή. Συνήθως αυτό εκπροσωπείται από μια boolean μεταβλητή `dead` ή `destroyed` που σηματοδοτεί στη μηχανή του παιχνιδιού ότι αυτό το αντικείμενο δεν πρέπει πλέον να εμφανίζεται.
- **χρονικής καθυστέρησης** Η "χρονική καθυστέρηση" είναι μια τυπική ιδιότητα μεταξύ αντικειμένων μικρής διάρκειας ζωής. Ένα τυπικό παράδειγμα είναι ένα κομμάτι κειμένου ή ένα γραφικό εφέ όπως μια έκρηξη που πρέπει να εμφανίζεται μόνο για λίγα χιλιοστά του δευτερολέπτου.
- **με χρονική καθυστέρηση** Η "χρονική καθυστέρηση" είναι μια τυπική ιδιότητα μεταξύ αντικειμένων μικρής διάρκειας. Ένα τυπικό παράδειγμα είναι ένα κομμάτι κειμένου ή ένα γραφικό εφέ όπως μια έκρηξη που πρέπει να εμφανίζεται μόνο για λίγα χιλιοστά του δευτερολέπτου.
✅ Σκεφτείτε ένα παιχνίδι όπως το Pac-Man. Μπορείτε να εντοπίσετε τους τέσσερις τύπους αντικειμένων που αναφέρονται παραπάνω σε αυτό το παιχνίδι;
### Έκφραση συμπεριφοράς
Όλα όσα περιγράψαμε παραπάνω είναι συμπεριφορές που μπορούν να έχουν τα αντικείμενα του παιχνιδιού. Πώς λοιπόν τις κωδικοποιούμε; Μπορούμε να εκφράσουμε αυτές τις συμπεριφορές ως μεθόδους που συνδέονται είτε με κλάσεις είτε με αντικείμενα.
Όλα όσα περιγράψαμε παραπάνω είναι συμπεριφορές που μπορούν να έχουν τα αντικείμενα παιχνιδιού. Πώς μπορούμε να τις κωδικοποιήσουμε; Μπορούμε να εκφράσουμε αυτές τις συμπεριφορές ως μεθόδους που σχετίζονται είτε με κλάσεις είτε με αντικείμενα.
**Κλάσεις**
Η ιδέα είναι να χρησιμοποιήσουμε `κλάσεις` σε συνδυασμό με την `κληρονομικότητα` για να προσθέσουμε μια συγκεκριμένη συμπεριφορά σε μια κλάση.
Η κληρονομικότητα είναι μια σημαντική έννοια που πρέπει να κατανοήσετε. Μάθετε περισσότερα στο [άρθρο του MDN για την κληρονομικότητα](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
Η κληρονομικότητα είναι μια σημαντική έννοια που πρέπει να κατανοήσετε. Μάθετε περισσότερα στο [άρθρο της MDN για την κληρονομικότητα](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
Εκφρασμένο μέσω κώδικα, ένα αντικείμενο παιχνιδιού μπορεί να μοιάζει κάπως έτσι:
Εκφρασμένο μέσω κώδικα, ένα αντικείμενο παιχνιδιού μπορεί τυπικά να μοιάζει κάπως έτσι:
```javascript
@ -88,7 +88,7 @@ hero.moveTo(5,5);
const tree = new Tree();
```
✅ Αφιερώστε λίγα λεπτά για να φανταστείτε έναν ήρωα του Pac-Man (για παράδειγμα, Inky, Pinky ή Blinky) και πώς θα μπορούσε να γραφτεί σε JavaScript.
✅ Αφιερώστε λίγα λεπτά για να φανταστείτε έναν ήρωα του Pac-Man (π.χ. Inky, Pinky ή Blinky) και πώς θα γραφόταν σε JavaScript.
**Σύνθεση**
@ -137,7 +137,7 @@ hero.moveTo(5,5);
const tree = createStatic(0,0, 'Tree');
```
**Ποιο μοτίβο πρέπει να χρησιμοποιήσω;**
**Ποιο μοτίβο να χρησιμοποιήσω;**
Εξαρτάται από εσάς ποιο μοτίβο θα επιλέξετε. Η JavaScript υποστηρίζει και τα δύο αυτά παραδείγματα.
@ -145,17 +145,17 @@ const tree = createStatic(0,0, 'Tree');
Ένα άλλο μοτίβο που είναι κοινό στην ανάπτυξη παιχνιδιών αντιμετωπίζει το πρόβλημα της διαχείρισης της εμπειρίας χρήστη και της απόδοσης του παιχνιδιού.
## Μοτίβο Pub/sub
## Μοτίβο Pub/Sub
Το Pub/Sub σημαίνει 'δημοσίευση-συνδρομή'
Αυτό το μοτίβο αντιμετωπίζει την ιδέα ότι τα διάφορα μέρη της εφαρμογής σας δεν πρέπει να γνωρίζουν το ένα για το άλλο. Γιατί συμβαίνει αυτό; Κάνει πολύ πιο εύκολο να δείτε τι συμβαίνει γενικά αν τα διάφορα μέρη είναι διαχωρισμένα. Επίσης, καθιστά ευκολότερη την αλλαγή συμπεριφοράς αν χρειαστεί. Πώς το επιτυγχάνουμε αυτό; Το κάνουμε καθιερώνοντας κάποιες έννοιες:
Αυτό το μοτίβο αντιμετωπίζει την ιδέα ότι τα διάφορα μέρη της εφαρμογής σας δεν πρέπει να γνωρίζουν το ένα για το άλλο. Γιατί αυτό; Κάνει πολύ πιο εύκολο να κατανοήσετε τι συμβαίνει γενικά αν τα διάφορα μέρη είναι διαχωρισμένα. Επίσης, καθιστά πιο εύκολη την αλλαγή συμπεριφοράς αν χρειαστεί. Πώς το πετυχαίνουμε αυτό; Το κάνουμε καθιερώνοντας κάποιες έννοιες:
- **μήνυμα**: Ένα μήνυμα είναι συνήθως μια συμβολοσειρά κειμένου συνοδευόμενη από ένα προαιρετικό φορτίο (ένα κομμάτι δεδομένων που διευκρινίζει τι αφορά το μήνυμα). Ένα τυπικό μήνυμα σε ένα παιχνίδι μπορεί να είναι `KEY_PRESSED_ENTER`.
- **δημοσιευτής**: Αυτό το στοιχείο *δημοσιεύει* ένα μήνυμα και το στέλνει σε όλους τους συνδρομητές.
- **συνδρομητής**: Αυτό το στοιχείο *ακούει* συγκεκριμένα μηνύματα και εκτελεί κάποια εργασία ως αποτέλεσμα της λήψης αυτού του μηνύματος, όπως το να πυροδοτήσει ένα λέιζερ.
- **συνδρομητής**: Αυτό το στοιχείο *ακούει* συγκεκριμένα μηνύματα και εκτελεί κάποια ενέργεια ως αποτέλεσμα της λήψης αυτού του μηνύματος, όπως το να πυροβολήσει ένα λέιζερ.
Η υλοποίηση είναι αρκετά μικρή σε μέγεθος αλλά είναι ένα πολύ ισχυρό μοτίβο. Να πώς μπορεί να υλοποιηθεί:
Η υλοποίηση είναι αρκετά μικρή σε μέγεθος, αλλά είναι ένα πολύ ισχυρό μοτίβο. Να πώς μπορεί να υλοποιηθεί:
```javascript
//set up an EventEmitter class that contains listeners
@ -204,7 +204,7 @@ window.addEventListener('keyup', (evt) => {
});
```
Στον παραπάνω κώδικα συνδέουμε ένα συμβάν πληκτρολογίου, `ArrowLeft`, και στέλνουμε το μήνυμα `HERO_MOVE_LEFT`. Ακούμε αυτό το μήνυμα και μετακινούμε τον `hero` ως αποτέλεσμα. Η δύναμη αυτού του μοτίβου είναι ότι ο ακροατής συμβάντων και ο ήρωας δεν γνωρίζουν ο ένας τον άλλον. Μπορείτε να επαναχαρτογραφήσετε το `ArrowLeft` στο πλήκτρο `A`. Επιπλέον, θα ήταν δυνατό να κάνετε κάτι εντελώς διαφορετικό στο `ArrowLeft` κάνοντας μερικές επεξεργασίες στη συνάρτηση `on` του eventEmitter:
Στον παραπάνω κώδικα, συνδέουμε ένα συμβάν πληκτρολογίου, `ArrowLeft`, και στέλνουμε το μήνυμα `HERO_MOVE_LEFT`. Ακούμε αυτό το μήνυμα και μετακινούμε τον `ήρωα` ως αποτέλεσμα. Η δύναμη αυτού του μοτίβου είναι ότι ο ακροατής συμβάντων και ο ήρωας δεν γνωρίζουν ο ένας τον άλλον. Μπορείτε να αντιστοιχίσετε το `ArrowLeft` στο πλήκτρο `A`. Επιπλέον, θα ήταν δυνατό να κάνετε κάτι εντελώς διαφορετικό στο `ArrowLeft` κάνοντας μερικές αλλαγές στη συνάρτηση `on` του eventEmitter:
```javascript
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
@ -220,9 +220,9 @@ eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
Σκεφτείτε πώς το μοτίβο pub-sub μπορεί να βελτιώσει ένα παιχνίδι. Ποια μέρη θα πρέπει να εκπέμπουν συμβάντα και πώς θα πρέπει το παιχνίδι να αντιδρά σε αυτά; Τώρα είναι η ευκαιρία σας να γίνετε δημιουργικοί, σκεπτόμενοι ένα νέο παιχνίδι και πώς τα μέρη του μπορεί να συμπεριφέρονται.
## Ερωτηματολόγιο Μετά το Μάθημα
## Κουίζ μετά το μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/30)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/30)
## Ανασκόπηση & Αυτομελέτη
@ -230,9 +230,9 @@ eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
## Εργασία
[Δημιουργήστε ένα προσχέδιο παιχνιδιού](assignment.md)
[Σχεδιάστε ένα παιχνίδι](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "41be8d35e7f30aa9dad10773c35e89c4",
"translation_date": "2025-08-26T21:58:48+00:00",
"original_hash": "056641280211e52fd0adb81b6058ec55",
"translation_date": "2025-08-29T07:10:37+00:00",
"source_file": "6-space-game/2-drawing-to-canvas/README.md",
"language_code": "el"
}
@ -33,7 +33,7 @@ CO_OP_TRANSLATOR_METADATA:
## Σχεδίαση απλών γεωμετρικών σχημάτων
Ο καμβάς χρησιμοποιεί ένα καρτεσιανό σύστημα συντεταγμένων για να σχεδιάζει αντικείμενα. Έτσι, χρησιμοποιεί άξονες x και y για να εκφράσει τη θέση ενός αντικειμένου. Η θέση `0,0` είναι η πάνω αριστερή γωνία και η κάτω δεξιά είναι αυτή που ορίσατε ως ΠΛΑΤΟΣ (WIDTH) και ΥΨΟΣ (HEIGHT) του καμβά.
Ο καμβάς χρησιμοποιεί ένα καρτεσιανό σύστημα συντεταγμένων για τη σχεδίαση αντικειμένων. Έτσι, χρησιμοποιεί άξονες x και y για να εκφράσει πού βρίσκεται κάτι. Η θέση `0,0` είναι η πάνω αριστερή γωνία και η κάτω δεξιά είναι αυτή που ορίσατε ως ΠΛΑΤΟΣ (WIDTH) και ΥΨΟΣ (HEIGHT) του καμβά.
![το πλέγμα του καμβά](../../../../translated_images/canvas_grid.5f209da785ded492a01ece440e3032afe51efa500cc2308e5ea4252487ceaf0b.el.png)
> Εικόνα από [MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
@ -63,7 +63,7 @@ ctx.fillRect(0,0, 200, 200) // x,y,width, height
Το Canvas API επικεντρώνεται κυρίως σε δισδιάστατα σχήματα, αλλά μπορείτε επίσης να σχεδιάσετε τρισδιάστατα αντικείμενα σε μια ιστοσελίδα· για αυτό, μπορείτε να χρησιμοποιήσετε το [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API).
Μπορείτε να σχεδιάσετε διάφορα πράγματα με το Canvas API, όπως:
Με το Canvas API μπορείτε να σχεδιάσετε διάφορα πράγματα, όπως:
- **Γεωμετρικά σχήματα**, έχουμε ήδη δείξει πώς να σχεδιάσετε ένα ορθογώνιο, αλλά μπορείτε να σχεδιάσετε πολλά περισσότερα.
- **Κείμενο**, μπορείτε να σχεδιάσετε κείμενο με οποιαδήποτε γραμματοσειρά και χρώμα επιθυμείτε.
@ -87,7 +87,7 @@ img.onload = () => {
### Πρότυπο φόρτωσης αρχείου
Συνιστάται να τυλίξετε τα παραπάνω σε μια κατασκευή όπως η παρακάτω, ώστε να είναι πιο εύχρηστο και να προσπαθείτε να το χειριστείτε μόνο όταν φορτωθεί πλήρως:
Συνιστάται να τυλίξετε τα παραπάνω σε μια δομή όπως η παρακάτω, ώστε να είναι πιο εύχρηστο και να προσπαθείτε να το χειριστείτε μόνο όταν φορτωθεί πλήρως:
```javascript
function loadAsset(path) {
@ -110,7 +110,7 @@ async function run() {
```
Για να σχεδιάσετε στοιχεία του παιχνιδιού στην οθόνη, ο κώδικάς σας θα μοιάζει κάπως έτσι:
Για να σχεδιάσετε στοιχεία του παιχνιδιού στην οθόνη, ο κώδικας σας θα μοιάζει κάπως έτσι:
```javascript
async function run() {
@ -124,9 +124,9 @@ async function run() {
}
```
## Ώρα να ξεκινήσετε να δημιουργείτε το παιχνίδι σας
## Ώρα να ξεκινήσετε να φτιάχνετε το παιχνίδι σας
### Τι να δημιουργήσετε
### Τι να φτιάξετε
Θα δημιουργήσετε μια ιστοσελίδα με ένα στοιχείο καμβά. Θα πρέπει να εμφανίζει μια μαύρη οθόνη `1024*768`. Σας παρέχουμε δύο εικόνες:
@ -169,7 +169,7 @@ npm start
Προσθέστε τον απαραίτητο κώδικα στο `your-work/app.js` για να λύσετε τα παρακάτω:
1. **Σχεδιάστε** έναν καμβά με μαύρο φόντο
> συμβουλή: προσθέστε δύο γραμμές κάτω από το κατάλληλο TODO στο `/app.js`, ορίζοντας το στοιχείο `ctx` να είναι μαύρο και τις συντεταγμένες πάνω/αριστερά στο 0,0 και το ύψος και το πλάτος να είναι ίσα με αυτά του καμβά.
> συμβουλή: προσθέστε δύο γραμμές κάτω από το κατάλληλο TODO στο `/app.js`, ορίζοντας το στοιχείο `ctx` να είναι μαύρο και τις συντεταγμένες πάνω/αριστερά στο 0,0, ενώ το ύψος και το πλάτος να είναι ίσα με αυτά του καμβά.
2. **Φορτώστε** υφές
> συμβουλή: προσθέστε τις εικόνες του παίκτη και του εχθρού χρησιμοποιώντας `await loadTexture` και περνώντας τη διαδρομή της εικόνας. Δεν θα τις δείτε ακόμα στην οθόνη!
3. **Σχεδιάστε** τον ήρωα στο κέντρο της οθόνης στο κάτω μισό
@ -186,7 +186,7 @@ npm start
const STOP_X = START_X + MONSTER_WIDTH;
```
έπειτα, δημιουργήστε έναν βρόχο για να σχεδιάσετε τον πίνακα των τεράτων στην οθόνη:
έπειτα, δημιουργήστε έναν βρόχο για να σχεδιάσετε τον πίνακα με τα τέρατα στην οθόνη:
```javascript
for (let x = START_X; x < STOP_X; x += 98) {
@ -227,4 +227,4 @@ npm start
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε κάθε προσπάθεια για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,19 +1,19 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "23f088add24f0f1fa51014a9e27ea280",
"translation_date": "2025-08-26T21:55:39+00:00",
"original_hash": "a9a161871de7706cb0e23b1bd0c74559",
"translation_date": "2025-08-29T07:08:51+00:00",
"source_file": "6-space-game/3-moving-elements-around/README.md",
"language_code": "el"
}
-->
# Δημιουργία ενός Παιχνιδιού Διαστήματος Μέρος 3: Προσθήκη Κίνησης
## Ερωτηματολόγιο πριν το μάθημα
## Κουίζ πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/33)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/33)
Τα παιχνίδια δεν είναι τόσο διασκεδαστικά μέχρι να δούμε εξωγήινους να κινούνται στην οθόνη! Σε αυτό το παιχνίδι, θα χρησιμοποιήσουμε δύο τύπους κινήσεων:
Τα παιχνίδια δεν είναι πολύ διασκεδαστικά μέχρι να αρχίσουν να εμφανίζονται εξωγήινοι στην οθόνη! Σε αυτό το παιχνίδι, θα χρησιμοποιήσουμε δύο τύπους κινήσεων:
- **Κίνηση με πληκτρολόγιο/ποντίκι**: όταν ο χρήστης αλληλεπιδρά με το πληκτρολόγιο ή το ποντίκι για να μετακινήσει ένα αντικείμενο στην οθόνη.
- **Κίνηση που προκαλείται από το παιχνίδι**: όταν το παιχνίδι μετακινεί ένα αντικείμενο σε συγκεκριμένα χρονικά διαστήματα.
@ -22,8 +22,8 @@ CO_OP_TRANSLATOR_METADATA:
Συνήθως χρειάζεστε τα παρακάτω βήματα για να επιτύχετε *κίνηση* στην οθόνη:
1. **Ορισμός νέας θέσης** για ένα αντικείμενο· αυτό είναι απαραίτητο για να αντιληφθούμε ότι το αντικείμενο έχει μετακινηθεί.
2. **Καθαρισμός της οθόνης**, η οθόνη πρέπει να καθαρίζεται μεταξύ των σχεδιάσεων. Μπορούμε να την καθαρίσουμε σχεδιάζοντας ένα ορθογώνιο γεμάτο με χρώμα φόντου.
1. **Ορισμός νέας θέσης** για ένα αντικείμενο· αυτό είναι απαραίτητο για να φαίνεται ότι το αντικείμενο έχει μετακινηθεί.
2. **Καθαρισμός της οθόνης**, η οθόνη πρέπει να καθαρίζεται μεταξύ των σχεδιάσεων. Μπορούμε να την καθαρίσουμε σχεδιάζοντας ένα ορθογώνιο που γεμίζουμε με ένα χρώμα φόντου.
3. **Ξανασχεδίαση του αντικειμένου** στη νέα θέση. Με αυτόν τον τρόπο επιτυγχάνουμε τελικά τη μετακίνηση του αντικειμένου από μία θέση σε άλλη.
Αυτό μπορεί να μοιάζει κάπως έτσι στον κώδικα:
@ -92,7 +92,7 @@ window.addEventListener('keydown', onKeyDown);
## Κίνηση που προκαλείται από το παιχνίδι
Μπορούμε να κάνουμε τα αντικείμενα να κινούνται μόνα τους χρησιμοποιώντας χρονομετρητές όπως οι συναρτήσεις `setTimeout()` ή `setInterval()` που ενημερώνουν τη θέση του αντικειμένου σε κάθε χρονικό διάστημα. Αυτό μπορεί να μοιάζει κάπως έτσι:
Μπορούμε να κάνουμε αντικείμενα να κινούνται μόνα τους χρησιμοποιώντας χρονομετρητές όπως οι συναρτήσεις `setTimeout()` ή `setInterval()` που ενημερώνουν τη θέση του αντικειμένου σε κάθε χρονικό διάστημα. Αυτό μπορεί να μοιάζει κάπως έτσι:
```javascript
let id = setInterval(() => {
@ -103,7 +103,7 @@ let id = setInterval(() => {
## Ο βρόχος του παιχνιδιού
Ο βρόχος του παιχνιδιού είναι μια έννοια που ουσιαστικά είναι μια συνάρτηση που καλείται σε τακτά χρονικά διαστήματα. Ονομάζεται βρόχος παιχνιδιού καθώς όλα όσα πρέπει να είναι ορατά στον χρήστη σχεδιάζονται μέσα στον βρόχο. Ο βρόχος παιχνιδιού χρησιμοποιεί όλα τα αντικείμενα του παιχνιδιού που αποτελούν μέρος του παιχνιδιού, σχεδιάζοντας όλα εκτός αν για κάποιο λόγο δεν πρέπει να αποτελούν πλέον μέρος του παιχνιδιού. Για παράδειγμα, αν ένα αντικείμενο είναι ένας εχθρός που χτυπήθηκε από ένα λέιζερ και εκρήγνυται, δεν αποτελεί πλέον μέρος του τρέχοντος βρόχου παιχνιδιού (θα μάθετε περισσότερα για αυτό σε επόμενα μαθήματα).
Ο βρόχος του παιχνιδιού είναι μια έννοια που ουσιαστικά είναι μια συνάρτηση που καλείται σε τακτά χρονικά διαστήματα. Ονομάζεται βρόχος παιχνιδιού καθώς όλα όσα πρέπει να είναι ορατά στον χρήστη σχεδιάζονται μέσα στον βρόχο. Ο βρόχος παιχνιδιού χρησιμοποιεί όλα τα αντικείμενα του παιχνιδιού που αποτελούν μέρος του παιχνιδιού, σχεδιάζοντας όλα εκτός αν για κάποιο λόγο δεν πρέπει να αποτελούν πλέον μέρος του παιχνιδιού. Για παράδειγμα, αν ένα αντικείμενο είναι ένας εχθρός που χτυπήθηκε από ένα λέιζερ και ανατινάχθηκε, δεν αποτελεί πλέον μέρος του τρέχοντος βρόχου παιχνιδιού (θα μάθετε περισσότερα για αυτό σε επόμενα μαθήματα).
Αυτός είναι ένας τυπικός βρόχος παιχνιδιού, εκφρασμένος σε κώδικα:
@ -205,7 +205,7 @@ npm start
}
```
2. **Προσθέστε χειριστές συμβάντων πληκτρολογίου** για να χειριστείτε την πλοήγηση με πλήκτρα (μετακίνηση του ήρωα πάνω/κάτω, αριστερά/δεξιά).
2. **Προσθέστε χειριστές συμβάντων πληκτρολογίου** για να χειριστείτε την πλοήγηση με πλήκτρα (μετακίνηση ήρωα πάνω/κάτω, αριστερά/δεξιά).
*ΘΥΜΗΘΕΙΤΕ* ότι είναι ένα καρτεσιανό σύστημα, η πάνω-αριστερή γωνία είναι `0,0`. Επίσης, θυμηθείτε να προσθέσετε κώδικα για να σταματήσετε την *προεπιλεγμένη συμπεριφορά*.
@ -221,9 +221,9 @@ npm start
window.addEventListener("keydown", onKeyDown);
```
Ελέγξτε την κονσόλα του περιηγητή σας σε αυτό το σημείο και παρακολουθήστε τα πλήκτρα που καταγράφονται.
Ελέγξτε την κονσόλα του περιηγητή σας σε αυτό το σημείο και παρακολουθήστε τα πατήματα πλήκτρων που καταγράφονται.
3. **Υλοποιήστε** το [Μοτίβο Pub sub](../README.md), αυτό θα κρατήσει τον κώδικά σας καθαρό καθώς ακολουθείτε τα υπόλοιπα μέρη.
3. **Υλοποιήστε** το [Μοτίβο Pub-Sub](../README.md), αυτό θα κρατήσει τον κώδικά σας καθαρό καθώς ακολουθείτε τα υπόλοιπα μέρη.
Για να κάνετε αυτό το τελευταίο μέρος, μπορείτε:
@ -313,7 +313,7 @@ npm start
1. **Ρυθμίστε τον βρόχο του παιχνιδιού**
Αναδιαμορφώστε τη συνάρτηση window.onload για να αρχικοποιήσετε το παιχνίδι και να ρυθμίσετε έναν βρόχο παιχνιδιού σε ένα καλό χρονικό διάστημα. Θα προσθέσετε επίσης μια ακτίνα λέιζερ:
Αναμορφώστε τη συνάρτηση window.onload για να αρχικοποιήσετε το παιχνίδι και να ρυθμίσετε έναν βρόχο παιχνιδιού σε ένα καλό χρονικό διάστημα. Θα προσθέσετε επίσης μια ακτίνα λέιζερ:
```javascript
window.onload = async () => {
@ -336,7 +336,7 @@ npm start
5. **Προσθέστε κώδικα** για να μετακινήσετε τους εχθρούς σε συγκεκριμένα χρονικά διαστήματα.
Αναδιαμορφώστε τη συνάρτηση `createEnemies()` για να δημιουργήσετε τους εχθρούς και να τους προσθέσετε στη νέα κλάση gameObjects:
Αναμορφώστε τη συνάρτηση `createEnemies()` για να δημιουργήσετε τους εχθρούς και να τους προσθέσετε στη νέα κλάση gameObjects:
```javascript
function createEnemies() {
@ -384,13 +384,13 @@ npm start
Όπως βλέπετε, ο κώδικάς σας μπορεί να μετατραπεί σε 'σπαγγέτι κώδικα' όταν αρχίζετε να προσθέτετε συναρτήσεις, μεταβλητές και κλάσεις. Πώς μπορείτε να οργανώσετε καλύτερα τον κώδικά σας ώστε να είναι πιο ευανάγνωστος; Σχεδιάστε ένα σύστημα για την οργάνωση του κώδικα σας, ακόμα κι αν εξακολουθεί να βρίσκεται σε ένα αρχείο.
## Ερωτηματολόγιο μετά το μάθημα
## Κουίζ μετά το μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/34)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/34)
## Ανασκόπηση & Αυτομελέτη
Ενώ γράφουμε το παιχνίδι μας χωρίς τη χρήση frameworks, υπάρχουν πολλά frameworks για ανάπτυξη παιχνιδιών με JavaScript και καμβά. Αφιερώστε χρόνο για να κάνετε [ανάγνωση σχετικά με αυτά](https://github.com/collections/javascript-game-engines).
Ενώ γράφουμε το παιχνίδι μας χωρίς τη χρήση frameworks, υπάρχουν πολλά frameworks για ανάπτυξη παιχνιδιών με JavaScript που βασίζονται στον καμβά. Αφιερώστε λίγο χρόνο για να κάνετε [ανάγνωση σχετικά με αυτά](https://github.com/collections/javascript-game-engines).
## Εργασία
@ -399,4 +399,4 @@ npm start
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,15 +1,15 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2e83e38c35dc003f046d7cc0bbfd4920",
"translation_date": "2025-08-26T22:01:32+00:00",
"original_hash": "a6ce295ff03bb49df7a3e17e6e7100a0",
"translation_date": "2025-08-29T07:09:54+00:00",
"source_file": "6-space-game/4-collision-detection/README.md",
"language_code": "el"
}
-->
# Δημιουργία Παιχνιδιού Διαστήματος Μέρος 4: Προσθήκη Λέιζερ και Ανίχνευση Συγκρούσεων
# Δημιουργία ενός Διαστημικού Παιχνιδιού Μέρος 4: Προσθήκη Λέιζερ και Ανίχνευση Συγκρούσεων
## Κουίζ Πριν το Μάθημα
## Κουίζ πριν το μάθημα
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/35)
@ -17,22 +17,22 @@ CO_OP_TRANSLATOR_METADATA:
- **Ένα λέιζερ**: αυτό το λέιζερ εκτοξεύεται από το διαστημόπλοιο του ήρωά σας και κινείται κάθετα προς τα πάνω.
- **Ανίχνευση συγκρούσεων**, ως μέρος της υλοποίησης της δυνατότητας να *πυροβολείτε*, θα προσθέσουμε και κάποιους ωραίους κανόνες παιχνιδιού:
- **Το λέιζερ χτυπάει εχθρό**: Ο εχθρός πεθαίνει αν χτυπηθεί από λέιζερ.
- **Το λέιζερ χτυπάει την κορυφή της οθόνης**: Το λέιζερ καταστρέφεται αν φτάσει στην κορυφή της οθόνης.
- **Σύγκρουση εχθρού και ήρωα**: Εχθρός και ήρωας καταστρέφονται αν συγκρουστούν.
- **Ο εχθρός φτάνει στο κάτω μέρος της οθόνης**: Εχθρός και ήρωας καταστρέφονται αν ο εχθρός φτάσει στο κάτω μέρος της οθόνης.
- **Το λέιζερ χτυπά εχθρό**: Ο εχθρός πεθαίνει αν χτυπηθεί από λέιζερ.
- **Το λέιζερ χτυπά την κορυφή της οθόνης**: Το λέιζερ καταστρέφεται αν φτάσει στο πάνω μέρος της οθόνης.
- **Σύγκρουση εχθρού και ήρωα**: Ένας εχθρός και ο ήρωας καταστρέφονται αν συγκρουστούν.
- **Ο εχθρός φτάνει στο κάτω μέρος της οθόνης**: Ένας εχθρός και ο ήρωας καταστρέφονται αν ο εχθρός φτάσει στο κάτω μέρος της οθόνης.
Με λίγα λόγια, εσείς -- *ο ήρωας* -- πρέπει να χτυπήσετε όλους τους εχθρούς με λέιζερ πριν καταφέρουν να φτάσουν στο κάτω μέρος της οθόνης.
✅ Κάντε μια μικρή έρευνα για το πρώτο παιχνίδι υπολογιστή που δημιουργήθηκε ποτέ. Ποια ήταν η λειτουργικότητά του;
✅ Κάντε μια μικρή έρευνα για το πρώτο παιχνίδι υπολογιστή που γράφτηκε ποτέ. Ποια ήταν η λειτουργικότητά του;
Ας γίνουμε ηρωικοί μαζί!
Ας γίνουμε ήρωες μαζί!
## Ανίχνευση Συγκρούσεων
## Ανίχνευση συγκρούσεων
Πώς κάνουμε ανίχνευση συγκρούσεων; Πρέπει να σκεφτούμε τα αντικείμενα του παιχνιδιού μας ως ορθογώνια που κινούνται. Γιατί αυτό, μπορεί να ρωτήσετε; Λοιπόν, η εικόνα που χρησιμοποιείται για να σχεδιάσει ένα αντικείμενο παιχνιδιού είναι ένα ορθογώνιο: έχει `x`, `y`, `πλάτος` και `ύψος`.
Αν δύο ορθογώνια, δηλαδή ένας ήρωας και ένας εχθρός, *τέμνονται*, έχουμε σύγκρουση. Τι πρέπει να συμβεί τότε εξαρτάται από τους κανόνες του παιχνιδιού. Για να υλοποιήσετε την ανίχνευση συγκρούσεων, χρειάζεστε τα εξής:
Αν δύο ορθογώνια, δηλαδή ένας ήρωας και ένας εχθρός, *τέμνονται*, έχουμε μια σύγκρουση. Τι πρέπει να συμβεί τότε εξαρτάται από τους κανόνες του παιχνιδιού. Για να υλοποιήσετε την ανίχνευση συγκρούσεων χρειάζεστε τα εξής:
1. Έναν τρόπο να αποκτήσετε μια ορθογώνια αναπαράσταση ενός αντικειμένου παιχνιδιού, κάτι σαν αυτό:
@ -60,14 +60,14 @@ CO_OP_TRANSLATOR_METADATA:
## Πώς καταστρέφουμε αντικείμενα
Για να καταστρέψετε αντικείμενα σε ένα παιχνίδι, πρέπει να ενημερώσετε το παιχνίδι ότι δεν πρέπει πλέον να σχεδιάζει αυτό το αντικείμενο στον βρόχο του παιχνιδιού που ενεργοποιείται σε ένα συγκεκριμένο διάστημα. Ένας τρόπος να το κάνετε αυτό είναι να χαρακτηρίσετε ένα αντικείμενο παιχνιδιού ως *νεκρό* όταν συμβεί κάτι, όπως αυτό:
Για να καταστρέψετε αντικείμενα σε ένα παιχνίδι, πρέπει να ενημερώσετε το παιχνίδι ότι δεν πρέπει πλέον να σχεδιάζει αυτό το αντικείμενο στον βρόχο του παιχνιδιού που ενεργοποιείται σε ένα συγκεκριμένο διάστημα. Ένας τρόπος να το κάνετε αυτό είναι να σημειώσετε ένα αντικείμενο παιχνιδιού ως *νεκρό* όταν συμβεί κάτι, όπως:
```javascript
// collision happened
enemy.dead = true
```
Στη συνέχεια, μπορείτε να φιλτράρετε τα *νεκρά* αντικείμενα πριν ξανασχεδιάσετε την οθόνη, όπως αυτό:
Στη συνέχεια, μπορείτε να προχωρήσετε στην αφαίρεση των *νεκρών* αντικειμένων πριν ξανασχεδιάσετε την οθόνη, όπως:
```javascript
gameObjects = gameObject.filter(go => !go.dead);
@ -75,15 +75,15 @@ gameObjects = gameObject.filter(go => !go.dead);
## Πώς πυροβολούμε ένα λέιζερ
Το να πυροβολήσετε ένα λέιζερ σημαίνει να ανταποκριθείτε σε ένα γεγονός πλήκτρου και να δημιουργήσετε ένα αντικείμενο που κινείται προς μια συγκεκριμένη κατεύθυνση. Πρέπει λοιπόν να εκτελέσουμε τα εξής βήματα:
Το να πυροβολήσετε ένα λέιζερ μεταφράζεται σε απόκριση σε ένα γεγονός πλήκτρου και δημιουργία ενός αντικειμένου που κινείται προς μια συγκεκριμένη κατεύθυνση. Πρέπει λοιπόν να εκτελέσουμε τα εξής βήματα:
1. **Δημιουργία ενός αντικειμένου λέιζερ**: από την κορυφή του διαστημοπλοίου του ήρωά μας, το οποίο μόλις δημιουργηθεί αρχίζει να κινείται προς τα πάνω.
2. **Σύνδεση κώδικα σε ένα γεγονός πλήκτρου**: πρέπει να επιλέξουμε ένα πλήκτρο στο πληκτρολόγιο που θα αντιπροσωπεύει την ενέργεια του παίκτη να πυροβολήσει το λέιζερ.
1. **Δημιουργία ενός αντικειμένου λέιζερ**: από την κορυφή του διαστημοπλοίου του ήρωά μας, το οποίο μόλις δημιουργηθεί αρχίζει να κινείται προς τα πάνω προς την κορυφή της οθόνης.
2. **Σύνδεση κώδικα σε ένα γεγονός πλήκτρου**: πρέπει να επιλέξουμε ένα πλήκτρο στο πληκτρολόγιο που να αντιπροσωπεύει τον παίκτη που πυροβολεί το λέιζερ.
3. **Δημιουργία ενός αντικειμένου παιχνιδιού που μοιάζει με λέιζερ** όταν πατηθεί το πλήκτρο.
## Χρονικό διάστημα για το λέιζερ
## Χρονική καθυστέρηση στο λέιζερ
Το λέιζερ πρέπει να πυροβολείται κάθε φορά που πατάτε ένα πλήκτρο, όπως το *space* για παράδειγμα. Για να αποτρέψουμε το παιχνίδι από το να δημιουργεί πάρα πολλά λέιζερ σε σύντομο χρονικό διάστημα, πρέπει να διορθώσουμε αυτό το πρόβλημα. Η λύση είναι να υλοποιήσουμε ένα λεγόμενο *χρονικό διάστημα*, έναν χρονοδιακόπτη, που διασφαλίζει ότι ένα λέιζερ μπορεί να πυροβοληθεί μόνο κάθε τόσο. Μπορείτε να το υλοποιήσετε με τον εξής τρόπο:
Το λέιζερ πρέπει να πυροβολεί κάθε φορά που πατάτε ένα πλήκτρο, όπως το *space* για παράδειγμα. Για να αποτρέψουμε το παιχνίδι από το να παράγει πάρα πολλά λέιζερ σε σύντομο χρονικό διάστημα, πρέπει να διορθώσουμε αυτό το πρόβλημα. Η λύση είναι η υλοποίηση μιας λεγόμενης *χρονικής καθυστέρησης*, ενός χρονομέτρου, που διασφαλίζει ότι ένα λέιζερ μπορεί να πυροβοληθεί μόνο σε συγκεκριμένα διαστήματα. Μπορείτε να το υλοποιήσετε με τον εξής τρόπο:
```javascript
class Cooldown {
@ -109,19 +109,19 @@ class Weapon {
}
```
✅ Ανατρέξτε στο μάθημα 1 της σειράς παιχνιδιών διαστήματος για να θυμηθείτε τα *χρονικά διαστήματα*.
✅ Ανατρέξτε στο μάθημα 1 της σειράς διαστημικών παιχνιδιών για να θυμηθείτε τις *χρονικές καθυστερήσεις*.
## Τι να δημιουργήσετε
Θα πάρετε τον υπάρχοντα κώδικα (τον οποίο θα πρέπει να έχετε καθαρίσει και αναδιαρθρώσει) από το προηγούμενο μάθημα και θα τον επεκτείνετε. Ξεκινήστε είτε με τον κώδικα από το μέρος II είτε χρησιμοποιήστε τον κώδικα από το [Μέρος III - αρχικό](../../../../../../../../../your-work).
Θα πάρετε τον υπάρχοντα κώδικα (τον οποίο θα έπρεπε να έχετε καθαρίσει και αναδιαρθρώσει) από το προηγούμενο μάθημα και θα τον επεκτείνετε. Ξεκινήστε είτε με τον κώδικα από το μέρος ΙΙ είτε χρησιμοποιήστε τον κώδικα στο [Μέρος ΙΙΙ - αρχικό](../../../../../../../../../your-work).
> συμβουλή: το λέιζερ με το οποίο θα δουλέψετε βρίσκεται ήδη στον φάκελο των πόρων σας και αναφέρεται στον κώδικά σας.
> συμβουλή: το λέιζερ με το οποίο θα δουλέψετε βρίσκεται ήδη στον φάκελο των πόρων σας και αναφέρεται στον κώδικά σας
- **Προσθέστε ανίχνευση συγκρούσεων**, όταν ένα λέιζερ συγκρούεται με κάτι, οι παρακάτω κανόνες πρέπει να ισχύουν:
1. **Το λέιζερ χτυπάει εχθρό**: ο εχθρός πεθαίνει αν χτυπηθεί από λέιζερ.
2. **Το λέιζερ χτυπάει την κορυφή της οθόνης**: Το λέιζερ καταστρέφεται αν φτάσει στην κορυφή της οθόνης.
1. **Το λέιζερ χτυπά εχθρό**: ο εχθρός πεθαίνει αν χτυπηθεί από λέιζερ.
2. **Το λέιζερ χτυπά την κορυφή της οθόνης**: Το λέιζερ καταστρέφεται αν φτάσει στο πάνω μέρος της οθόνης.
3. **Σύγκρουση εχθρού και ήρωα**: ένας εχθρός και ο ήρωας καταστρέφονται αν συγκρουστούν.
4. **Ο εχθρός φτάνει στο κάτω μέρος της οθόνης**: ένας εχθρός και ο ήρωας καταστρέφονται αν ο εχθρός φτάσει στο κάτω μέρος της οθόνης.
4. **Ο εχθρός φτάνει στο κάτω μέρος της οθόνης**: Ένας εχθρός και ο ήρωας καταστρέφονται αν ο εχθρός φτάσει στο κάτω μέρος της οθόνης.
## Προτεινόμενα βήματα
@ -144,11 +144,11 @@ cd your-work
npm start
```
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν περιηγητή και εισάγετε αυτή τη διεύθυνση. Προς το παρόν, θα πρέπει να εμφανίζεται ο ήρωας και όλοι οι εχθροί, αλλά τίποτα δεν κινείται - ακόμα :).
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν περιηγητή και εισάγετε αυτή τη διεύθυνση, αυτή τη στιγμή θα πρέπει να εμφανίζει τον ήρωα και όλους τους εχθρούς, τίποτα δεν κινείται - ακόμα :).
### Προσθέστε κώδικα
### Προσθήκη κώδικα
1. **Ρυθμίστε μια ορθογώνια αναπαράσταση του αντικειμένου παιχνιδιού σας για να χειριστείτε συγκρούσεις**. Ο παρακάτω κώδικας σας επιτρέπει να αποκτήσετε μια ορθογώνια αναπαράσταση ενός `GameObject`. Επεξεργαστείτε την κλάση GameObject για να την επεκτείνετε:
1. **Ρυθμίστε μια ορθογώνια αναπαράσταση του αντικειμένου παιχνιδιού σας για να χειριστείτε συγκρούσεις** Ο παρακάτω κώδικας σας επιτρέπει να αποκτήσετε μια ορθογώνια αναπαράσταση ενός `GameObject`. Επεξεργαστείτε την κλάση GameObject για να την επεκτείνετε:
```javascript
rectFromGameObject() {
@ -161,7 +161,7 @@ npm start
}
```
2. **Προσθέστε κώδικα που ελέγχει συγκρούσεις**. Αυτή θα είναι μια νέα συνάρτηση που ελέγχει αν δύο ορθογώνια τέμνονται:
2. **Προσθέστε κώδικα που ελέγχει συγκρούσεις** Αυτή θα είναι μια νέα συνάρτηση που ελέγχει αν δύο ορθογώνια τέμνονται:
```javascript
function intersectRect(r1, r2) {
@ -175,7 +175,7 @@ npm start
```
3. **Προσθέστε δυνατότητα πυροβολισμού λέιζερ**
1. **Προσθέστε μήνυμα γεγονότος πλήκτρου**. Το πλήκτρο *space* θα πρέπει να δημιουργεί ένα λέιζερ ακριβώς πάνω από το διαστημόπλοιο του ήρωα. Προσθέστε τρεις σταθερές στο αντικείμενο Messages:
1. **Προσθέστε μήνυμα γεγονότος πλήκτρου**. Το πλήκτρο *space* πρέπει να δημιουργεί ένα λέιζερ ακριβώς πάνω από το διαστημόπλοιο του ήρωα. Προσθέστε τρεις σταθερές στο αντικείμενο Messages:
```javascript
KEY_EVENT_SPACE: "KEY_EVENT_SPACE",
@ -209,7 +209,7 @@ npm start
})
```
1. **Κινήστε το αντικείμενο**, Διασφαλίστε ότι το λέιζερ κινείται σταδιακά προς την κορυφή της οθόνης. Θα δημιουργήσετε μια νέα κλάση Laser που επεκτείνει το `GameObject`, όπως κάνατε πριν:
1. **Μετακινήστε το αντικείμενο**, Διασφαλίστε ότι το λέιζερ κινείται σταδιακά προς την κορυφή της οθόνης. Θα δημιουργήσετε μια νέα κλάση Laser που επεκτείνει το `GameObject`, όπως έχετε κάνει πριν:
```javascript
class Laser extends GameObject {
@ -230,7 +230,7 @@ npm start
}
```
1. **Χειριστείτε συγκρούσεις**, Υλοποιήστε κανόνες συγκρούσεων για το λέιζερ. Προσθέστε μια συνάρτηση `updateGameObjects()` που ελέγχει τα αντικείμενα για συγκρούσεις:
1. **Χειριστείτε συγκρούσεις**, Υλοποιήστε τους κανόνες συγκρούσεων για το λέιζερ. Προσθέστε μια συνάρτηση `updateGameObjects()` που ελέγχει τα αντικείμενα για συγκρούσεις:
```javascript
function updateGameObjects() {
@ -254,9 +254,9 @@ npm start
Βεβαιωθείτε ότι προσθέσατε τη `updateGameObjects()` στον βρόχο του παιχνιδιού στο `window.onload`.
4. **Υλοποιήστε χρονικό διάστημα** για το λέιζερ, ώστε να μπορεί να πυροβολείται μόνο κάθε τόσο.
4. **Υλοποιήστε χρονική καθυστέρηση** στο λέιζερ, ώστε να μπορεί να πυροβολείται μόνο σε συγκεκριμένα διαστήματα.
Τέλος, επεξεργαστείτε την κλάση Hero ώστε να μπορεί να έχει χρονικό διάστημα:
Τέλος, επεξεργαστείτε την κλάση Hero ώστε να υποστηρίζει χρονική καθυστέρηση:
```javascript
class Hero extends GameObject {
@ -285,21 +285,21 @@ npm start
}
```
Σε αυτό το σημείο, το παιχνίδι σας έχει κάποια λειτουργικότητα! Μπορείτε να πλοηγηθείτε με τα πλήκτρα βελών, να πυροβολήσετε λέιζερ με το πλήκτρο space και οι εχθροί εξαφανίζονται όταν τους χτυπάτε. Μπράβο!
Σε αυτό το σημείο, το παιχνίδι σας έχει κάποια λειτουργικότητα! Μπορείτε να μετακινείστε με τα βελάκια, να πυροβολείτε λέιζερ με το πλήκτρο space και οι εχθροί εξαφανίζονται όταν τους χτυπάτε. Μπράβο!
---
## 🚀 Πρόκληση
Προσθέστε μια έκρηξη! Ρίξτε μια ματιά στα γραφικά του παιχνιδιού στον [φάκελο Space Art](../../../../6-space-game/solution/spaceArt/readme.txt) και προσπαθήστε να προσθέσετε μια έκρηξη όταν το λέιζερ χτυπάει έναν εξωγήινο.
Προσθέστε μια έκρηξη! Ρίξτε μια ματιά στα αρχεία πόρων του παιχνιδιού στο [Space Art repo](../../../../6-space-game/solution/spaceArt/readme.txt) και προσπαθήστε να προσθέσετε μια έκρηξη όταν το λέιζερ χτυπά έναν εξωγήινο.
## Κουίζ Μετά το Μάθημα
## Κουίζ μετά το μάθημα
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/36)
## Ανασκόπηση & Αυτομελέτη
Πειραματιστείτε με τα διαστήματα στο παιχνίδι σας μέχρι τώρα. Τι συμβαίνει όταν τα αλλάζετε; Διαβάστε περισσότερα για τα [χρονικά γεγονότα της JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
Πειραματιστείτε με τα διαστήματα στο παιχνίδι σας μέχρι τώρα. Τι συμβαίνει όταν τα αλλάζετε; Διαβάστε περισσότερα για τα [γεγονότα χρονισμού της JavaScript](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
## Εργασία
@ -307,5 +307,5 @@ npm start
---
**Αποποίηση Ευθύνης**:
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,23 +1,23 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "4e8250db84b027c9ff816b4e4c093457",
"translation_date": "2025-08-26T21:52:49+00:00",
"original_hash": "adda95e02afa3fbee67b6e385b1109e1",
"translation_date": "2025-08-29T07:09:28+00:00",
"source_file": "6-space-game/5-keeping-score/README.md",
"language_code": "el"
}
-->
# Δημιουργία Παιχνιδιού Διαστήματος Μέρος 5: Βαθμολογία και Ζωές
# Δημιουργία ενός Παιχνιδιού Διαστήματος Μέρος 5: Βαθμολογία και Ζωές
## Ερωτηματολόγιο Πριν το Μάθημα
## Κουίζ πριν το μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/37)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/37)
Σε αυτό το μάθημα, θα μάθετε πώς να προσθέσετε βαθμολογία σε ένα παιχνίδι και να υπολογίσετε ζωές.
## Σχεδίαση κειμένου στην οθόνη
Για να εμφανίσετε τη βαθμολογία του παιχνιδιού στην οθόνη, θα χρειαστεί να γνωρίζετε πώς να τοποθετήσετε κείμενο στην οθόνη. Η απάντηση είναι η χρήση της μεθόδου `fillText()` στο αντικείμενο canvas. Μπορείτε επίσης να ελέγξετε άλλες πτυχές, όπως τη γραμματοσειρά που θα χρησιμοποιήσετε, το χρώμα του κειμένου και ακόμη και την ευθυγράμμιση (αριστερά, δεξιά, κέντρο). Παρακάτω υπάρχει κώδικας που σχεδιάζει κείμενο στην οθόνη.
Για να μπορέσετε να εμφανίσετε τη βαθμολογία του παιχνιδιού στην οθόνη, θα χρειαστεί να ξέρετε πώς να τοποθετήσετε κείμενο στην οθόνη. Η απάντηση είναι η χρήση της μεθόδου `fillText()` στο αντικείμενο canvas. Μπορείτε επίσης να ελέγξετε άλλες παραμέτρους, όπως τη γραμματοσειρά που θα χρησιμοποιηθεί, το χρώμα του κειμένου και ακόμη και την ευθυγράμμισή του (αριστερά, δεξιά, κέντρο). Παρακάτω υπάρχει κώδικας που σχεδιάζει κείμενο στην οθόνη.
```javascript
ctx.font = "30px Arial";
@ -26,18 +26,18 @@ ctx.textAlign = "right";
ctx.fillText("show this on the screen", 0, 0);
```
✅ Διαβάστε περισσότερα για [πώς να προσθέσετε κείμενο σε ένα canvas](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_text) και μη διστάσετε να κάνετε το δικό σας πιο εντυπωσιακό!
✅ Διαβάστε περισσότερα για [το πώς να προσθέσετε κείμενο σε ένα canvas](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_text) και μη διστάσετε να κάνετε το δικό σας πιο εντυπωσιακό!
## Ζωή, ως έννοια παιχνιδιού
## Η ζωή ως έννοια στο παιχνίδι
Η έννοια της ζωής σε ένα παιχνίδι είναι απλώς ένας αριθμός. Στο πλαίσιο ενός παιχνιδιού διαστήματος, είναι συνηθισμένο να αποδίδονται συγκεκριμένες ζωές που μειώνονται μία προς μία όταν το σκάφος σας δέχεται ζημιά. Είναι ωραίο αν μπορείτε να δείξετε μια γραφική αναπαράσταση αυτού, όπως μικροσκάφη ή καρδιές αντί για έναν αριθμό.
Η έννοια της ζωής σε ένα παιχνίδι είναι απλώς ένας αριθμός. Στο πλαίσιο ενός παιχνιδιού διαστήματος, είναι συνηθισμένο να αποδίδονται συγκεκριμένες ζωές που μειώνονται μία-μία όταν το διαστημόπλοιό σας δέχεται ζημιά. Είναι ωραίο αν μπορείτε να δείξετε μια γραφική αναπαράσταση αυτού, όπως μικρά διαστημόπλοια ή καρδιές, αντί για έναν αριθμό.
## Τι θα δημιουργήσετε
Ας προσθέσουμε τα εξής στο παιχνίδι σας:
- **Βαθμολογία παιχνιδιού**: Για κάθε εχθρικό σκάφος που καταστρέφεται, ο ήρωας θα πρέπει να κερδίζει πόντους. Προτείνουμε 100 πόντους ανά σκάφος. Η βαθμολογία του παιχνιδιού θα πρέπει να εμφανίζεται κάτω αριστερά.
- **Ζωή**: Το σκάφος σας έχει τρεις ζωές. Χάνετε μία ζωή κάθε φορά που ένα εχθρικό σκάφος συγκρούεται με εσάς. Η βαθμολογία ζωής θα πρέπει να εμφανίζεται κάτω δεξιά και να αποτελείται από το εξής γραφικό ![εικόνα ζωής](../../../../translated_images/life.6fb9f50d53ee0413cd91aa411f7c296e10a1a6de5c4a4197c718b49bf7d63ebf.el.png).
- **Βαθμολογία παιχνιδιού**: Για κάθε εχθρικό διαστημόπλοιο που καταστρέφεται, ο ήρωας θα πρέπει να κερδίζει πόντους. Προτείνουμε 100 πόντους ανά διαστημόπλοιο. Η βαθμολογία του παιχνιδιού θα πρέπει να εμφανίζεται κάτω αριστερά.
- **Ζωές**: Το διαστημόπλοιό σας έχει τρεις ζωές. Χάνετε μία ζωή κάθε φορά που ένα εχθρικό διαστημόπλοιο συγκρούεται μαζί σας. Η βαθμολογία ζωής θα πρέπει να εμφανίζεται κάτω δεξιά και να αποτελείται από το εξής γραφικό: ![εικόνα ζωής](../../../../translated_images/life.6fb9f50d53ee0413cd91aa411f7c296e10a1a6de5c4a4197c718b49bf7d63ebf.el.png).
## Προτεινόμενα βήματα
@ -60,11 +60,11 @@ cd your-work
npm start
```
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν browser και εισάγετε αυτή τη διεύθυνση. Αυτή τη στιγμή θα πρέπει να εμφανίζεται ο ήρωας και όλοι οι εχθροί, και καθώς πατάτε τα αριστερά και δεξιά βέλη, ο ήρωας κινείται και μπορεί να καταρρίψει εχθρούς.
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν περιηγητή και εισάγετε αυτή τη διεύθυνση. Αυτή τη στιγμή θα πρέπει να εμφανίζεται ο ήρωας και όλοι οι εχθροί, και καθώς πατάτε τα βελάκια αριστερά και δεξιά, ο ήρωας θα κινείται και θα μπορεί να καταρρίπτει εχθρούς.
### Προσθήκη κώδικα
1. **Αντιγράψτε τα απαραίτητα assets** από τον φάκελο `solution/assets/` στον φάκελο `your-work`. Θα προσθέσετε το asset `life.png`. Προσθέστε το lifeImg στη συνάρτηση window.onload:
1. **Αντιγράψτε τα απαραίτητα αρχεία** από τον φάκελο `solution/assets/` στον φάκελο `your-work`. Θα προσθέσετε το αρχείο `life.png`. Προσθέστε το lifeImg στη συνάρτηση window.onload:
```javascript
lifeImg = await loadTexture("assets/life.png");
@ -80,9 +80,9 @@ npm start
eventEmitter = new EventEmitter();
```
2. **Προσθέστε μεταβλητές**. Προσθέστε κώδικα που αντιπροσωπεύει τη συνολική βαθμολογία (0) και τις ζωές που απομένουν (3), και εμφανίστε αυτές τις βαθμολογίες στην οθόνη.
2. **Προσθέστε μεταβλητές**. Προσθέστε κώδικα που αντιπροσωπεύει τη συνολική σας βαθμολογία (0) και τις ζωές που απομένουν (3), και εμφανίστε αυτές τις τιμές στην οθόνη.
3. **Επεκτείνετε τη συνάρτηση `updateGameObjects()`**. Επεκτείνετε τη συνάρτηση `updateGameObjects()` για να χειριστείτε τις συγκρούσεις με εχθρούς:
3. **Επεκτείνετε τη συνάρτηση `updateGameObjects()`**. Επεκτείνετε τη συνάρτηση `updateGameObjects()` για να χειρίζεται συγκρούσεις με εχθρούς:
```javascript
enemies.forEach(enemy => {
@ -93,15 +93,15 @@ npm start
})
```
4. **Προσθέστε `life` και `points`**.
1. **Αρχικοποιήστε μεταβλητές**. Κάτω από το `this.cooldown = 0` στην κλάση `Hero`, ορίστε τις μεταβλητές life και points:
4. **Προσθέστε "ζωές" και "πόντους"**.
1. **Αρχικοποιήστε μεταβλητές**. Κάτω από το `this.cooldown = 0` στην κλάση `Hero`, ορίστε τις ζωές και τους πόντους:
```javascript
this.life = 3;
this.points = 0;
```
1. **Σχεδιάστε τις μεταβλητές στην οθόνη**. Σχεδιάστε αυτές τις τιμές στην οθόνη:
1. **Σχεδιάστε τις μεταβλητές στην οθόνη**. Εμφανίστε αυτές τις τιμές στην οθόνη:
```javascript
function drawLife() {
@ -135,7 +135,7 @@ npm start
drawLife();
```
1. **Υλοποιήστε κανόνες παιχνιδιού**. Υλοποιήστε τους εξής κανόνες παιχνιδιού:
1. **Υλοποιήστε τους κανόνες του παιχνιδιού**. Υλοποιήστε τους εξής κανόνες:
1. **Για κάθε σύγκρουση ήρωα και εχθρού**, αφαιρέστε μία ζωή.
@ -152,7 +152,7 @@ npm start
2. **Για κάθε λέιζερ που χτυπά έναν εχθρό**, αυξήστε τη βαθμολογία του παιχνιδιού κατά 100 πόντους.
Επεκτείνετε την κλάση Hero για να κάνετε αυτή την αύξηση:
Επεκτείνετε την κλάση `Hero` για να κάνετε αυτή την αύξηση:
```javascript
incrementPoints() {
@ -160,7 +160,7 @@ npm start
}
```
Προσθέστε αυτές τις συναρτήσεις στους Collision Event Emitters:
Προσθέστε αυτές τις συναρτήσεις στους Εκπομπούς Συμβάντων Συγκρούσεων:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
@ -175,29 +175,29 @@ npm start
});
```
✅ Κάντε λίγη έρευνα για να ανακαλύψετε άλλα παιχνίδια που έχουν δημιουργηθεί χρησιμοποιώντας JavaScript/Canvas. Ποια είναι τα κοινά χαρακτηριστικά τους;
✅ Κάντε λίγη έρευνα για να ανακαλύψετε άλλα παιχνίδια που έχουν δημιουργηθεί χρησιμοποιώντας JavaScript/Canvas. Ποια είναι τα κοινά τους χαρακτηριστικά;
Μέχρι το τέλος αυτής της εργασίας, θα πρέπει να βλέπετε τα μικρά σκάφη ζωής κάτω δεξιά, τους πόντους κάτω αριστερά, και θα πρέπει να βλέπετε τον αριθμό ζωών να μειώνεται καθώς συγκρούεστε με εχθρούς και τους πόντους να αυξάνονται όταν καταρρίπτετε εχθρούς. Μπράβο! Το παιχνίδι σας είναι σχεδόν ολοκληρωμένο.
Μέχρι το τέλος αυτής της εργασίας, θα πρέπει να βλέπετε τα μικρά διαστημόπλοια "ζωής" κάτω δεξιά, τους πόντους κάτω αριστερά, και να βλέπετε τον αριθμό των ζωών σας να μειώνεται όταν συγκρούεστε με εχθρούς και τους πόντους σας να αυξάνονται όταν καταρρίπτετε εχθρούς. Μπράβο! Το παιχνίδι σας είναι σχεδόν έτοιμο.
---
## 🚀 Πρόκληση
Ο κώδικάς σας είναι σχεδόν ολοκληρωμένος. Μπορείτε να φανταστείτε τα επόμενα βήματα;
Ο κώδικάς σας είναι σχεδόν έτοιμος. Μπορείτε να φανταστείτε τα επόμενα βήματα;
## Ερωτηματολόγιο Μετά το Μάθημα
## Κουίζ μετά το μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/38)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/38)
## Ανασκόπηση & Αυτομελέτη
Ερευνήστε μερικούς τρόπους με τους οποίους μπορείτε να αυξάνετε και να μειώνετε τις βαθμολογίες και τις ζωές στο παιχνίδι. Υπάρχουν ενδιαφέρουσες μηχανές παιχνιδιών όπως το [PlayFab](https://playfab.com). Πώς θα μπορούσε η χρήση μιας τέτοιας μηχανής να βελτιώσει το παιχνίδι σας;
Ερευνήστε τρόπους με τους οποίους μπορείτε να αυξομειώνετε τη βαθμολογία και τις ζωές σε ένα παιχνίδι. Υπάρχουν ενδιαφέρουσες μηχανές παιχνιδιών όπως το [PlayFab](https://playfab.com). Πώς θα μπορούσε η χρήση μιας τέτοιας μηχανής να βελτιώσει το παιχνίδι σας;
## Εργασία
[Δημιουργία Παιχνιδιού Βαθμολογίας](assignment.md)
[Δημιουργήστε ένα Παιχνίδι με Βαθμολογία](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "01336cddd638242e99b133614111ea40",
"translation_date": "2025-08-26T22:07:39+00:00",
"original_hash": "05be6c37791668e3719c4fba94566367",
"translation_date": "2025-08-29T07:11:10+00:00",
"source_file": "6-space-game/6-end-condition/README.md",
"language_code": "el"
}
@ -13,29 +13,29 @@ CO_OP_TRANSLATOR_METADATA:
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/39)
Υπάρχουν διάφοροι τρόποι να εκφράσετε μια *συνθήκη τερματισμού* σε ένα παιχνίδι. Εναπόκειται σε εσάς, ως δημιουργός του παιχνιδιού, να καθορίσετε γιατί το παιχνίδι τελειώνει. Ακολουθούν μερικοί λόγοι, αν υποθέσουμε ότι μιλάμε για το παιχνίδι διαστήματος που έχετε δημιουργήσει μέχρι τώρα:
Υπάρχουν διάφοροι τρόποι να εκφράσετε μια *συνθήκη τέλους* σε ένα παιχνίδι. Εσείς, ως δημιουργός του παιχνιδιού, αποφασίζετε γιατί το παιχνίδι τελειώνει. Εδώ είναι μερικοί λόγοι, αν υποθέσουμε ότι μιλάμε για το παιχνίδι διαστήματος που έχετε δημιουργήσει μέχρι τώρα:
- **`N` Εχθρικά σκάφη έχουν καταστραφεί**: Είναι αρκετά συνηθισμένο, αν χωρίσετε το παιχνίδι σε διαφορετικά επίπεδα, να χρειάζεται να καταστρέψετε `N` εχθρικά σκάφη για να ολοκληρώσετε ένα επίπεδο.
- **Το σκάφος σας έχει καταστραφεί**: Υπάρχουν σίγουρα παιχνίδια όπου χάνετε αν το σκάφος σας καταστραφεί. Μια άλλη συνηθισμένη προσέγγιση είναι η έννοια των ζωών. Κάθε φορά που το σκάφος σας καταστρέφεται, αφαιρείται μια ζωή. Όταν όλες οι ζωές χαθούν, τότε χάνετε το παιχνίδι.
- **Έχετε συλλέξει `N` πόντους**: Μια άλλη συνηθισμένη συνθήκη τερματισμού είναι να συλλέξετε πόντους. Το πώς αποκτάτε πόντους εξαρτάται από εσάς, αλλά είναι αρκετά συνηθισμένο να αποδίδονται πόντοι σε διάφορες δραστηριότητες, όπως η καταστροφή ενός εχθρικού σκάφους ή η συλλογή αντικειμένων που *πέφτουν* όταν καταστρέφονται.
- **Ολοκλήρωση ενός επιπέδου**: Αυτό μπορεί να περιλαμβάνει διάφορες συνθήκες, όπως `X` εχθρικά σκάφη καταστραμμένα, `Y` πόντοι συλλεγμένοι ή ίσως η συλλογή ενός συγκεκριμένου αντικειμένου.
- **`N` Εχθρικά σκάφη έχουν καταστραφεί**: Είναι αρκετά συνηθισμένο, αν χωρίζετε το παιχνίδι σε διαφορετικά επίπεδα, να χρειάζεται να καταστρέψετε `N` εχθρικά σκάφη για να ολοκληρώσετε ένα επίπεδο.
- **Το σκάφος σας έχει καταστραφεί**: Υπάρχουν σίγουρα παιχνίδια όπου χάνετε αν το σκάφος σας καταστραφεί. Μια άλλη κοινή προσέγγιση είναι η έννοια των ζωών. Κάθε φορά που το σκάφος σας καταστρέφεται, χάνετε μία ζωή. Όταν όλες οι ζωές χαθούν, τότε χάνετε το παιχνίδι.
- **Έχετε συλλέξει `N` πόντους**: Μια άλλη συνηθισμένη συνθήκη τέλους είναι να συλλέξετε πόντους. Το πώς κερδίζετε πόντους εξαρτάται από εσάς, αλλά είναι αρκετά συνηθισμένο να αποδίδονται πόντοι σε διάφορες δραστηριότητες, όπως η καταστροφή ενός εχθρικού σκάφους ή η συλλογή αντικειμένων που *πέφτουν* όταν καταστρέφονται.
- **Ολοκλήρωση ενός επιπέδου**: Αυτό μπορεί να περιλαμβάνει διάφορες συνθήκες, όπως `X` εχθρικά σκάφη που καταστράφηκαν, `Y` πόντους που συλλέχθηκαν ή ίσως τη συλλογή ενός συγκεκριμένου αντικειμένου.
## Επανεκκίνηση
Αν οι άνθρωποι απολαμβάνουν το παιχνίδι σας, είναι πιθανό να θέλουν να το ξαναπαίξουν. Μόλις το παιχνίδι τελειώσει για οποιονδήποτε λόγο, θα πρέπει να προσφέρετε μια επιλογή για επανεκκίνηση.
Αν οι παίκτες απολαμβάνουν το παιχνίδι σας, είναι πιθανό να θέλουν να το παίξουν ξανά. Όταν το παιχνίδι τελειώνει για οποιονδήποτε λόγο, θα πρέπει να προσφέρετε μια επιλογή επανεκκίνησης.
✅ Σκεφτείτε λίγο υπό ποιες συνθήκες τελειώνει ένα παιχνίδι και πώς σας προτρέπουν να το επανεκκινήσετε.
## Τι να δημιουργήσετε
Θα προσθέσετε τους εξής κανόνες στο παιχνίδι σας:
Θα προσθέσετε αυτούς τους κανόνες στο παιχνίδι σας:
1. **Νίκη στο παιχνίδι**. Μόλις όλα τα εχθρικά σκάφη καταστραφούν, κερδίζετε το παιχνίδι. Επιπλέον, εμφανίστε κάποιο μήνυμα νίκης.
1. **Επανεκκίνηση**. Μόλις όλες οι ζωές σας χαθούν ή το παιχνίδι κερδηθεί, θα πρέπει να προσφέρετε έναν τρόπο επανεκκίνησης του παιχνιδιού. Θυμηθείτε! Θα χρειαστεί να επανεκκινήσετε το παιχνίδι και να καθαρίσετε την προηγούμενη κατάσταση του παιχνιδιού.
1. **Νίκη στο παιχνίδι**. Όταν όλα τα εχθρικά σκάφη έχουν καταστραφεί, κερδίζετε το παιχνίδι. Επιπλέον, εμφανίστε κάποιο μήνυμα νίκης.
1. **Επανεκκίνηση**. Όταν όλες οι ζωές σας χαθούν ή το παιχνίδι κερδηθεί, θα πρέπει να προσφέρετε έναν τρόπο επανεκκίνησης του παιχνιδιού. Θυμηθείτε! Θα χρειαστεί να επανεκκινήσετε το παιχνίδι και να καθαρίσετε την προηγούμενη κατάσταση του παιχνιδιού.
## Προτεινόμενα βήματα
Εντοπίστε τα αρχεία που έχουν δημιουργηθεί για εσάς στον υποφάκελο `your-work`. Θα πρέπει να περιέχει τα εξής:
Βρείτε τα αρχεία που έχουν δημιουργηθεί για εσάς στον υποφάκελο `your-work`. Θα πρέπει να περιέχει τα εξής:
```bash
-| assets
@ -55,13 +55,13 @@ cd your-work
npm start
```
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν browser και εισάγετε αυτή τη διεύθυνση. Το παιχνίδι σας θα πρέπει να είναι σε κατάσταση παιχνιδιού.
Το παραπάνω θα ξεκινήσει έναν HTTP Server στη διεύθυνση `http://localhost:5000`. Ανοίξτε έναν περιηγητή και εισάγετε αυτή τη διεύθυνση. Το παιχνίδι σας θα πρέπει να είναι σε κατάσταση που μπορεί να παιχτεί.
> συμβουλή: για να αποφύγετε προειδοποιήσεις στο Visual Studio Code, επεξεργαστείτε τη συνάρτηση `window.onload` ώστε να καλεί το `gameLoopId` όπως είναι (χωρίς `let`) και δηλώστε το `gameLoopId` στην κορυφή του αρχείου, ανεξάρτητα: `let gameLoopId;`
> συμβουλή: για να αποφύγετε προειδοποιήσεις στο Visual Studio Code, επεξεργαστείτε τη συνάρτηση `window.onload` ώστε να καλεί το `gameLoopId` όπως είναι (χωρίς `let`), και δηλώστε το `gameLoopId` στην κορυφή του αρχείου, ανεξάρτητα: `let gameLoopId;`
### Προσθήκη κώδικα
1. **Παρακολούθηση συνθήκης τερματισμού**. Προσθέστε κώδικα που παρακολουθεί τον αριθμό των εχθρών ή αν το σκάφος του ήρωα έχει καταστραφεί, προσθέτοντας αυτές τις δύο συναρτήσεις:
1. **Παρακολούθηση συνθήκης τέλους**. Προσθέστε κώδικα που παρακολουθεί τον αριθμό των εχθρών ή αν το σκάφος του ήρωα έχει καταστραφεί, προσθέτοντας αυτές τις δύο συναρτήσεις:
```javascript
function isHeroDead() {
@ -74,7 +74,7 @@ npm start
}
```
1. **Προσθήκη λογικής στους χειριστές μηνυμάτων**. Επεξεργαστείτε το `eventEmitter` ώστε να χειρίζεται αυτές τις συνθήκες:
1. **Προσθήκη λογικής στους διαχειριστές μηνυμάτων**. Επεξεργαστείτε το `eventEmitter` για να χειρίζεται αυτές τις συνθήκες:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
@ -117,7 +117,7 @@ npm start
2. **Προσθήκη κώδικα επανεκκίνησης** που επανεκκινεί το παιχνίδι με το πάτημα ενός επιλεγμένου κουμπιού.
1. **Ακρόαση για πάτημα πλήκτρου `Enter`**. Επεξεργαστείτε τον eventListener του παραθύρου σας ώστε να ακούει για αυτό το πάτημα:
1. **Ακρόαση για πάτημα πλήκτρου `Enter`**. Επεξεργαστείτε τον eventListener του παραθύρου σας για να ακούει αυτό το πάτημα:
```javascript
else if(evt.key === "Enter") {
@ -131,7 +131,7 @@ npm start
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
```
1. **Υλοποίηση κανόνων παιχνιδιού**. Υλοποιήστε τους εξής κανόνες παιχνιδιού:
1. **Υλοποίηση κανόνων παιχνιδιού**. Υλοποιήστε τους παρακάτω κανόνες παιχνιδιού:
1. **Συνθήκη νίκης παίκτη**. Όταν όλα τα εχθρικά σκάφη καταστραφούν, εμφανίστε ένα μήνυμα νίκης.
@ -171,7 +171,7 @@ npm start
}
```
1. **Λογική επανεκκίνησης**. Όταν όλες οι ζωές χαθούν ή ο παίκτης κερδίσει το παιχνίδι, εμφανίστε ότι το παιχνίδι μπορεί να επανεκκινήσει. Επιπλέον, επανεκκινήστε το παιχνίδι όταν πατηθεί το πλήκτρο *επανεκκίνησης* (μπορείτε να αποφασίσετε ποιο πλήκτρο θα αντιστοιχεί στην επανεκκίνηση).
1. **Λογική επανεκκίνησης**. Όταν όλες οι ζωές χαθούν ή ο παίκτης κερδίσει το παιχνίδι, εμφανίστε ότι το παιχνίδι μπορεί να επανεκκινηθεί. Επιπλέον, επανεκκινήστε το παιχνίδι όταν πατηθεί το πλήκτρο επανεκκίνησης (μπορείτε να αποφασίσετε ποιο πλήκτρο θα αντιστοιχεί στην επανεκκίνηση).
1. Δημιουργήστε τη συνάρτηση `resetGame()`:
@ -194,7 +194,7 @@ npm start
}
```
1. Προσθέστε μια κλήση στο `eventEmitter` για επανεκκίνηση του παιχνιδιού στη `initGame()`:
1. Προσθέστε μια κλήση στο `eventEmitter` για να επανεκκινήσει το παιχνίδι στη `initGame()`:
```javascript
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
@ -210,13 +210,13 @@ npm start
}
```
👽 💥 🚀 Συγχαρητήρια, Καπετάνιε! Το παιχνίδι σας ολοκληρώθηκε! Μπράβο! 🚀 💥 👽
👽 💥 🚀 Συγχαρητήρια, Καπετάνιε! Το παιχνίδι σας είναι ολοκληρωμένο! Μπράβο! 🚀 💥 👽
---
## 🚀 Πρόκληση
Προσθέστε ήχο! Μπορείτε να προσθέσετε ήχο για να βελτιώσετε την εμπειρία παιχνιδιού, ίσως όταν υπάρχει χτύπημα λέιζερ, ή όταν ο ήρωας πεθαίνει ή κερδίζει; Ρίξτε μια ματιά σε αυτό το [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) για να μάθετε πώς να παίζετε ήχο χρησιμοποιώντας JavaScript.
Προσθέστε έναν ήχο! Μπορείτε να προσθέσετε έναν ήχο για να βελτιώσετε την εμπειρία παιχνιδιού, ίσως όταν υπάρχει χτύπημα λέιζερ, ή όταν ο ήρωας πεθαίνει ή κερδίζει; Ρίξτε μια ματιά σε αυτό το [sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) για να μάθετε πώς να παίζετε ήχο χρησιμοποιώντας JavaScript.
## Κουίζ μετά το μάθημα
@ -228,9 +228,9 @@ npm start
## Εργασία
[Δημιουργία Δείγματος Παιχνιδιού](assignment.md)
[Δημιουργία ενός Δείγματος Παιχνιδιού](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,23 +1,23 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "8da1b5e2c63f749808858c53f37b8ce7",
"translation_date": "2025-08-26T23:03:30+00:00",
"original_hash": "8a07db14e75ac62f013b7de5df05981d",
"translation_date": "2025-08-29T07:03:55+00:00",
"source_file": "7-bank-project/1-template-route/README.md",
"language_code": "el"
}
-->
# Δημιουργία Εφαρμογής Τραπεζικής Μέσω Διαδικτύου Μέρος 1: Πρότυπα HTML και Διαδρομές σε Μια Εφαρμογή Ιστού
# Δημιουργία Εφαρμογής Τραπεζικής Μέρος 1: HTML Πρότυπα και Διαδρομές σε Μια Εφαρμογή Ιστού
## Ερωτηματολόγιο Πριν το Μάθημα
## Κουίζ Πριν το Μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/41)
[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/41)
### Εισαγωγή
Από την εμφάνιση της JavaScript στους περιηγητές, οι ιστοσελίδες γίνονται πιο διαδραστικές και πολύπλοκες από ποτέ. Οι τεχνολογίες ιστού χρησιμοποιούνται πλέον ευρέως για τη δημιουργία πλήρως λειτουργικών εφαρμογών που εκτελούνται απευθείας σε έναν περιηγητή, τις οποίες ονομάζουμε [εφαρμογές ιστού](https://en.wikipedia.org/wiki/Web_application). Καθώς οι εφαρμογές ιστού είναι ιδιαίτερα διαδραστικές, οι χρήστες δεν θέλουν να περιμένουν την ανανέωση ολόκληρης της σελίδας κάθε φορά που εκτελείται μια ενέργεια. Γι' αυτό η JavaScript χρησιμοποιείται για την ενημέρωση του HTML απευθείας μέσω του DOM, προσφέροντας μια πιο ομαλή εμπειρία χρήστη.
Από την εμφάνιση της JavaScript στους περιηγητές, οι ιστοσελίδες γίνονται πιο διαδραστικές και πολύπλοκες από ποτέ. Οι τεχνολογίες ιστού χρησιμοποιούνται πλέον ευρέως για τη δημιουργία πλήρως λειτουργικών εφαρμογών που εκτελούνται απευθείας σε έναν περιηγητή, τις οποίες αποκαλούμε [εφαρμογές ιστού](https://en.wikipedia.org/wiki/Web_application). Καθώς οι εφαρμογές ιστού είναι ιδιαίτερα διαδραστικές, οι χρήστες δεν θέλουν να περιμένουν την πλήρη ανανέωση της σελίδας κάθε φορά που εκτελείται μια ενέργεια. Γι' αυτό η JavaScript χρησιμοποιείται για την άμεση ενημέρωση του HTML μέσω του DOM, προσφέροντας μια πιο ομαλή εμπειρία χρήστη.
Σε αυτό το μάθημα, θα θέσουμε τα θεμέλια για τη δημιουργία μιας τραπεζικής εφαρμογής ιστού, χρησιμοποιώντας πρότυπα HTML για τη δημιουργία πολλαπλών οθονών που μπορούν να εμφανίζονται και να ενημερώνονται χωρίς να χρειάζεται να ανανεωθεί ολόκληρη η σελίδα HTML.
Σε αυτό το μάθημα, θα θέσουμε τα θεμέλια για τη δημιουργία μιας τραπεζικής εφαρμογής ιστού, χρησιμοποιώντας HTML πρότυπα για τη δημιουργία πολλαπλών οθονών που μπορούν να εμφανίζονται και να ενημερώνονται χωρίς να χρειάζεται να ανανεωθεί ολόκληρη η HTML σελίδα.
### Προαπαιτούμενα
@ -25,7 +25,7 @@ CO_OP_TRANSLATOR_METADATA:
### Προετοιμασία
Στον υπολογιστή σας, δημιουργήστε έναν φάκελο με όνομα `bank` και ένα αρχείο με όνομα `index.html` μέσα σε αυτόν. Θα ξεκινήσουμε από αυτό το [βασικό πρότυπο](https://en.wikipedia.org/wiki/Boilerplate_code) HTML:
Στον υπολογιστή σας, δημιουργήστε έναν φάκελο με όνομα `bank` και ένα αρχείο με όνομα `index.html` μέσα σε αυτόν. Θα ξεκινήσουμε από αυτό το [βασικό HTML πρότυπο](https://en.wikipedia.org/wiki/Boilerplate_code):
```html
<!DOCTYPE html>
@ -43,28 +43,28 @@ CO_OP_TRANSLATOR_METADATA:
---
## Πρότυπα HTML
## HTML Πρότυπα
Αν θέλετε να δημιουργήσετε πολλαπλές οθόνες για μια ιστοσελίδα, μια λύση θα ήταν να δημιουργήσετε ένα αρχείο HTML για κάθε οθόνη που θέλετε να εμφανίσετε. Ωστόσο, αυτή η λύση έχει κάποια μειονεκτήματα:
Αν θέλετε να δημιουργήσετε πολλαπλές οθόνες για μια ιστοσελίδα, μια λύση θα ήταν να δημιουργήσετε ένα αρχείο HTML για κάθε οθόνη που θέλετε να εμφανίσετε. Ωστόσο, αυτή η λύση έχει κάποιες δυσκολίες:
- Πρέπει να ανανεώνετε ολόκληρο το HTML όταν αλλάζετε οθόνη, κάτι που μπορεί να είναι αργό.
- Είναι δύσκολο να μοιραστείτε δεδομένα μεταξύ των διαφορετικών οθονών.
- Πρέπει να ανανεώνετε ολόκληρη την HTML όταν αλλάζετε οθόνη, κάτι που μπορεί να είναι αργό.
- Είναι δύσκολο να μοιράζεστε δεδομένα μεταξύ των διαφορετικών οθονών.
Μια άλλη προσέγγιση είναι να έχετε μόνο ένα αρχείο HTML και να ορίσετε πολλαπλά [πρότυπα HTML](https://developer.mozilla.org/docs/Web/HTML/Element/template) χρησιμοποιώντας το στοιχείο `<template>`. Ένα πρότυπο είναι ένα επαναχρησιμοποιήσιμο μπλοκ HTML που δεν εμφανίζεται από τον περιηγητή και πρέπει να ενεργοποιηθεί κατά την εκτέλεση μέσω JavaScript.
Μια άλλη προσέγγιση είναι να έχετε μόνο ένα αρχείο HTML και να ορίσετε πολλαπλά [HTML πρότυπα](https://developer.mozilla.org/docs/Web/HTML/Element/template) χρησιμοποιώντας το στοιχείο `<template>`. Ένα πρότυπο είναι ένα επαναχρησιμοποιήσιμο μπλοκ HTML που δεν εμφανίζεται από τον περιηγητή και πρέπει να δημιουργηθεί κατά την εκτέλεση μέσω JavaScript.
### Εργασία
Θα δημιουργήσουμε μια τραπεζική εφαρμογή με δύο οθόνες: τη σελίδα σύνδεσης και τον πίνακα ελέγχου. Αρχικά, ας προσθέσουμε στο σώμα του HTML ένα στοιχείο κράτησης θέσης που θα χρησιμοποιήσουμε για να ενεργοποιήσουμε τις διαφορετικές οθόνες της εφαρμογής μας:
Θα δημιουργήσουμε μια τραπεζική εφαρμογή με δύο οθόνες: τη σελίδα σύνδεσης και τον πίνακα ελέγχου. Αρχικά, ας προσθέσουμε στο σώμα του HTML ένα στοιχείο κράτησης θέσης που θα χρησιμοποιήσουμε για να δημιουργήσουμε τις διαφορετικές οθόνες της εφαρμογής μας:
```html
<div id="app">Loading...</div>
```
Δίνουμε σε αυτό ένα `id` για να είναι πιο εύκολο να το εντοπίσουμε με τη JavaScript αργότερα.
Δίνουμε ένα `id` για να είναι πιο εύκολο να το εντοπίσουμε με τη JavaScript αργότερα.
> Συμβουλή: Επειδή το περιεχόμενο αυτού του στοιχείου θα αντικατασταθεί, μπορούμε να βάλουμε ένα μήνυμα ή έναν δείκτη φόρτωσης που θα εμφανίζεται ενώ η εφαρμογή φορτώνει.
> Συμβουλή: Επειδή το περιεχόμενο αυτού του στοιχείου θα αντικατασταθεί, μπορούμε να βάλουμε ένα μήνυμα ή δείκτη φόρτωσης που θα εμφανίζεται όσο η εφαρμογή φορτώνει.
Στη συνέχεια, ας προσθέσουμε κάτω από αυτό το πρότυπο HTML για τη σελίδα σύνδεσης. Προς το παρόν, θα βάλουμε μόνο έναν τίτλο και μια ενότητα που περιέχει έναν σύνδεσμο που θα χρησιμοποιήσουμε για την πλοήγηση.
Στη συνέχεια, ας προσθέσουμε κάτω από αυτό το HTML πρότυπο για τη σελίδα σύνδεσης. Προς το παρόν, θα βάλουμε μόνο έναν τίτλο και μια ενότητα που περιέχει έναν σύνδεσμο που θα χρησιμοποιήσουμε για την πλοήγηση.
```html
<template id="login">
@ -75,7 +75,7 @@ CO_OP_TRANSLATOR_METADATA:
</template>
```
Έπειτα, θα προσθέσουμε ένα άλλο πρότυπο HTML για τη σελίδα του πίνακα ελέγχου. Αυτή η σελίδα θα περιέχει διαφορετικές ενότητες:
Έπειτα, θα προσθέσουμε ένα άλλο HTML πρότυπο για τη σελίδα του πίνακα ελέγχου. Αυτή η σελίδα θα περιέχει διαφορετικές ενότητες:
- Μια κεφαλίδα με έναν τίτλο και έναν σύνδεσμο αποσύνδεσης
- Το τρέχον υπόλοιπο του τραπεζικού λογαριασμού
@ -106,15 +106,15 @@ CO_OP_TRANSLATOR_METADATA:
</template>
```
> Συμβουλή: Όταν δημιουργείτε πρότυπα HTML, αν θέλετε να δείτε πώς θα φαίνονται, μπορείτε να σχολιάσετε τις γραμμές `<template>` και `</template>` περικλείοντάς τις με `<!-- -->`.
> Συμβουλή: Όταν δημιουργείτε HTML πρότυπα, αν θέλετε να δείτε πώς θα φαίνονται, μπορείτε να σχολιάσετε τις γραμμές `<template>` και `</template>` περικλείοντάς τις με `<!-- -->`.
✅ Γιατί πιστεύετε ότι χρησιμοποιούμε χαρακτηριστικά `id` στα πρότυπα; Θα μπορούσαμε να χρησιμοποιήσουμε κάτι άλλο, όπως κλάσεις;
✅ Γιατί πιστεύετε ότι χρησιμοποιούμε `id` χαρακτηριστικά στα πρότυπα; Θα μπορούσαμε να χρησιμοποιήσουμε κάτι άλλο, όπως κλάσεις;
## Εμφάνιση προτύπων με JavaScript
## Εμφάνιση Προτύπων με JavaScript
Αν δοκιμάσετε το τρέχον αρχείο HTML σε έναν περιηγητή, θα δείτε ότι μένει κολλημένο στο μήνυμα `Loading...`. Αυτό συμβαίνει επειδή πρέπει να προσθέσουμε κάποιον κώδικα JavaScript για να ενεργοποιήσουμε και να εμφανίσουμε τα πρότυπα HTML.
Αν δοκιμάσετε το τρέχον αρχείο HTML σε έναν περιηγητή, θα δείτε ότι μένει κολλημένο στο μήνυμα `Loading...`. Αυτό συμβαίνει επειδή πρέπει να προσθέσουμε κάποιον κώδικα JavaScript για να δημιουργήσουμε και να εμφανίσουμε τα HTML πρότυπα.
Η ενεργοποίηση ενός προτύπου γίνεται συνήθως σε 3 βήματα:
Η δημιουργία ενός προτύπου γίνεται συνήθως σε 3 βήματα:
1. Εντοπισμός του στοιχείου προτύπου στο DOM, για παράδειγμα χρησιμοποιώντας [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Κλωνοποίηση του στοιχείου προτύπου, χρησιμοποιώντας [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
@ -142,7 +142,7 @@ function updateRoute(templateId) {
}
```
Αυτό που κάνουμε εδώ είναι ακριβώς τα 3 βήματα που περιγράφηκαν παραπάνω. Ενεργοποιούμε το πρότυπο με το `id` `templateId` και τοποθετούμε το κλωνοποιημένο περιεχόμενό του μέσα στο στοιχείο κράτησης θέσης της εφαρμογής μας. Σημειώστε ότι πρέπει να χρησιμοποιήσουμε `cloneNode(true)` για να αντιγράψουμε ολόκληρο το υποδέντρο του προτύπου.
Αυτό που κάνουμε εδώ είναι ακριβώς τα 3 βήματα που περιγράφηκαν παραπάνω. Δημιουργούμε το πρότυπο με το `id` `templateId` και τοποθετούμε το κλωνοποιημένο περιεχόμενό του μέσα στο στοιχείο κράτησης θέσης της εφαρμογής μας. Σημειώστε ότι πρέπει να χρησιμοποιήσουμε `cloneNode(true)` για να αντιγράψουμε ολόκληρο το υποδέντρο του προτύπου.
Τώρα καλέστε αυτή τη συνάρτηση με ένα από τα πρότυπα και δείτε το αποτέλεσμα.
@ -150,11 +150,11 @@ function updateRoute(templateId) {
updateRoute('login');
```
✅ Ποιος είναι ο σκοπός αυτού του κώδικα `app.innerHTML = '';`; Τι συμβαίνει χωρίς αυτόν;
✅ Ποιος είναι ο σκοπός αυτού του κώδικα `app.innerHTML = '';`; Τι συμβαίνει χωρίς αυτό;
## Δημιουργία διαδρομών
## Δημιουργία Διαδρομών
Όταν μιλάμε για μια εφαρμογή ιστού, ονομάζουμε *Δρομολόγηση* την πρόθεση να αντιστοιχίσουμε **URLs** σε συγκεκριμένες οθόνες που πρέπει να εμφανίζονται. Σε μια ιστοσελίδα με πολλαπλά αρχεία HTML, αυτό γίνεται αυτόματα καθώς οι διαδρομές των αρχείων αντικατοπτρίζονται στο URL. Για παράδειγμα, με αυτά τα αρχεία στον φάκελο του έργου σας:
Όταν μιλάμε για μια εφαρμογή ιστού, ονομάζουμε *Δρομολόγηση* την πρόθεση να αντιστοιχίσουμε **URLs** σε συγκεκριμένες οθόνες που πρέπει να εμφανιστούν. Σε έναν ιστότοπο με πολλαπλά αρχεία HTML, αυτό γίνεται αυτόματα καθώς τα μονοπάτια των αρχείων αντικατοπτρίζονται στο URL. Για παράδειγμα, με αυτά τα αρχεία στον φάκελο του έργου σας:
```
mywebsite/index.html
@ -162,7 +162,7 @@ mywebsite/login.html
mywebsite/admin/index.html
```
Αν δημιουργήσετε έναν διακομιστή ιστού με ρίζα το `mywebsite`, η αντιστοίχηση URL θα είναι:
Αν δημιουργήσετε έναν διακομιστή ιστού με ρίζα το `mywebsite`, η αντιστοίχιση URL θα είναι:
```
https://site.com --> mywebsite/index.html
@ -174,7 +174,7 @@ https://site.com/admin/ --> mywebsite/admin/index.html
### Εργασία
Θα χρησιμοποιήσουμε ένα απλό αντικείμενο για να υλοποιήσουμε έναν [χάρτη](https://en.wikipedia.org/wiki/Associative_array) μεταξύ διαδρομών URL και των προτύπων μας. Προσθέστε αυτό το αντικείμενο στην κορυφή του αρχείου `app.js`.
Θα χρησιμοποιήσουμε ένα απλό αντικείμενο για να υλοποιήσουμε έναν [χάρτη](https://en.wikipedia.org/wiki/Associative_array) μεταξύ μονοπατιών URL και των προτύπων μας. Προσθέστε αυτό το αντικείμενο στην κορυφή του αρχείου `app.js` σας.
```js
const routes = {
@ -202,7 +202,7 @@ function updateRoute() {
Τι συμβαίνει αν εισάγετε μια άγνωστη διαδρομή στο URL; Πώς θα μπορούσαμε να λύσουμε αυτό το πρόβλημα;
## Προσθήκη πλοήγησης
## Προσθήκη Πλοήγησης
Το επόμενο βήμα για την εφαρμογή μας είναι να προσθέσουμε τη δυνατότητα πλοήγησης μεταξύ των σελίδων χωρίς να χρειάζεται να αλλάζουμε το URL χειροκίνητα. Αυτό συνεπάγεται δύο πράγματα:
@ -228,7 +228,7 @@ function navigate(path) {
Αυτή η μέθοδος πρώτα ενημερώνει το τρέχον URL με βάση τη δοθείσα διαδρομή και στη συνέχεια ενημερώνει το πρότυπο. Η ιδιότητα `window.location.origin` επιστρέφει τη ρίζα του URL, επιτρέποντάς μας να ανακατασκευάσουμε ένα πλήρες URL από μια δοθείσα διαδρομή.
Τώρα που έχουμε αυτή τη συνάρτηση, μπορούμε να φροντίσουμε το πρόβλημα που έχουμε αν μια διαδρομή δεν αντιστοιχεί σε καμία καθορισμένη διαδρομή. Θα τροποποιήσουμε τη συνάρτηση `updateRoute` προσθέτοντας μια εναλλακτική σε μία από τις υπάρχουσες διαδρομές αν δεν μπορούμε να βρούμε αντιστοιχία.
Τώρα που έχουμε αυτή τη συνάρτηση, μπορούμε να αντιμετωπίσουμε το πρόβλημα που έχουμε αν μια διαδρομή δεν αντιστοιχεί σε καμία καθορισμένη διαδρομή. Θα τροποποιήσουμε τη συνάρτηση `updateRoute` προσθέτοντας μια εναλλακτική λύση σε μία από τις υπάρχουσες διαδρομές αν δεν μπορούμε να βρούμε αντιστοιχία.
```js
function updateRoute() {
@ -244,7 +244,7 @@ function updateRoute() {
Αν δεν μπορεί να βρεθεί διαδρομή, τώρα θα ανακατευθυνθούμε στη σελίδα `login`.
Τώρα ας δημιουργήσουμε μια συνάρτηση για να πάρουμε το URL όταν γίνεται κλικ σε έναν σύνδεσμο και να αποτρέψουμε την προεπιλεγμένη συμπεριφορά του περιηγητή για τους συνδέσμους:
Ας δημιουργήσουμε μια συνάρτηση για να πάρουμε το URL όταν γίνεται κλικ σε έναν σύνδεσμο και να αποτρέψουμε την προεπιλεγμένη συμπεριφορά του περιηγητή για τους συνδέσμους:
```js
function onLinkClick(event) {
@ -253,7 +253,7 @@ function onLinkClick(event) {
}
```
Ας ολοκληρώσουμε το σύστημα πλοήγησης προσθέτοντας συνδέσεις στις *Login* και *Logout* συνδέσεις στο HTML.
Ας ολοκληρώσουμε το σύστημα πλοήγησης προσθέτοντας συνδέσεις στις συνδέσεις *Login* και *Logout* στο HTML.
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
@ -269,9 +269,9 @@ function onLinkClick(event) {
Η μέθοδος `history.pushState` είναι μέρος του προτύπου HTML5 και υλοποιείται σε [όλους τους σύγχρονους περιηγητές](https://caniuse.com/?search=pushState). Αν δημιουργείτε μια εφαρμογή ιστού για παλαιότερους περιηγητές, υπάρχει ένα τέχνασμα που μπορείτε να χρησιμοποιήσετε αντί αυτής της API: χρησιμοποιώντας ένα [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) πριν από τη διαδρομή, μπορείτε να υλοποιήσετε δρομολόγηση που λειτουργεί με κανονική πλοήγηση αγκύρωσης και δεν ανανεώνει τη σελίδα, καθώς ο σκοπός του ήταν να δημιουργήσει εσωτερικούς συνδέσμους μέσα σε μια σελίδα.
## Χειρισμός των κουμπιών "Πίσω" και "Εμπρός" του περιηγητή
## Χειρισμός των Κουμπιών Πίσω και Εμπρός του Περιηγητή
Η χρήση του `history.pushState` δημιουργεί νέες καταχωρήσεις στο ιστορικό περιήγησης του περιηγητή. Μπορείτε να το ελέγξετε κρατώντας πατημένο το κουμπί *πίσω* του περιηγητή σας, θα πρέπει να εμφανίζει κάτι σαν αυτό:
Η χρήση του `history.pushState` δημιουργεί νέες καταχωρήσεις στο ιστορικό περιήγησης του περιηγητή. Μπορείτε να το ελέγξετε κρατώντας πατημένο το *κουμπί πίσω* του περιηγητή σας, θα πρέπει να εμφανίζει κάτι σαν αυτό:
![Στιγμιότυπο του ιστορικού πλοήγησης](../../../../translated_images/history.7fdabbafa521e06455b738d3dafa3ff41d3071deae60ead8c7e0844b9ed987d8.el.png)
@ -294,7 +294,7 @@ updateRoute();
[![Συναρτήσεις Βέλους](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Συναρτήσεις Βέλους")
> 🎥 Κάντε κλικ στην παραπάνω εικόνα για ένα βίντεο σχετικά με τις συναρτήσεις βέλους.
> 🎥 Κάντε κλικ στην εικόνα παραπάνω για ένα βίντεο σχετικά με τις συναρτήσεις βέλους.
Τώρα δοκιμάστε να χρησιμοποιήσετε τα κουμπιά πίσω και εμπρός του περιηγητή σας και ελέγξτε ότι η εμφανιζόμενη διαδρομή ενημερώνεται σωστά αυτή τη φορά.
@ -302,15 +302,17 @@ updateRoute();
## 🚀 Πρόκληση
Προσθέστε ένα νέο πρότυπο και μια διαδρομή για μια τρίτη σελίδα που εμφανίζει τα credits αυτής της εφαρμογής.
Προσθέστε ένα νέο πρότυπο και διαδρομή για μια τρίτη σελίδα που εμφανίζει τα credits αυτής της εφαρμογής.
## Ερωτηματολόγιο Μετά το Μάθημα
## Κουίζ Μετά το Μάθημα
[Ερωτηματολόγιο μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/42)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/42)
##
## Ανασκόπηση & Αυτομελέτη
Η δρομολόγηση είναι ένα από τα εκπληκτικά δύσκολα μέρη της ανάπτυξης ιστού, ειδικά καθώς ο ιστός μετακινείται από συμπερι
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "b667b7d601e2ee19acb5aa9d102dc9f3",
"translation_date": "2025-08-26T22:53:05+00:00",
"original_hash": "8baca047d77a5f43fa4099c0578afa42",
"translation_date": "2025-08-29T07:00:27+00:00",
"source_file": "7-bank-project/2-forms/README.md",
"language_code": "el"
}
@ -15,22 +15,22 @@ CO_OP_TRANSLATOR_METADATA:
### Εισαγωγή
Σχεδόν σε όλες τις σύγχρονες διαδικτυακές εφαρμογές, μπορείτε να δημιουργήσετε έναν λογαριασμό για να έχετε τον δικό σας προσωπικό χώρο. Καθώς πολλοί χρήστες μπορούν να έχουν πρόσβαση σε μια εφαρμογή ταυτόχρονα, χρειάζεστε έναν μηχανισμό για να αποθηκεύετε τα προσωπικά δεδομένα κάθε χρήστη ξεχωριστά και να επιλέγετε ποια πληροφορία θα εμφανίζεται. Δεν θα καλύψουμε πώς να διαχειρίζεστε [την ταυτότητα του χρήστη με ασφάλεια](https://en.wikipedia.org/wiki/Authentication), καθώς είναι ένα εκτενές θέμα από μόνο του, αλλά θα διασφαλίσουμε ότι κάθε χρήστης θα μπορεί να δημιουργήσει έναν (ή περισσότερους) τραπεζικούς λογαριασμούς στην εφαρμογή μας.
Σχεδόν σε όλες τις σύγχρονες διαδικτυακές εφαρμογές, μπορείτε να δημιουργήσετε έναν λογαριασμό για να έχετε τον δικό σας προσωπικό χώρο. Καθώς πολλοί χρήστες μπορούν να έχουν πρόσβαση σε μια εφαρμογή ταυτόχρονα, χρειάζεστε έναν μηχανισμό για να αποθηκεύετε τα προσωπικά δεδομένα κάθε χρήστη ξεχωριστά και να επιλέγετε ποια πληροφορία θα εμφανίζεται. Δεν θα καλύψουμε πώς να διαχειριστείτε [την ταυτότητα του χρήστη με ασφάλεια](https://en.wikipedia.org/wiki/Authentication), καθώς είναι ένα εκτενές θέμα από μόνο του, αλλά θα διασφαλίσουμε ότι κάθε χρήστης θα μπορεί να δημιουργήσει έναν (ή περισσότερους) τραπεζικούς λογαριασμούς στην εφαρμογή μας.
Σε αυτό το μέρος, θα χρησιμοποιήσουμε φόρμες HTML για να προσθέσουμε σύνδεση και εγγραφή στην εφαρμογή μας. Θα δούμε πώς να στέλνουμε δεδομένα σε έναν διακομιστή API προγραμματιστικά και, τελικά, πώς να ορίσουμε βασικούς κανόνες επικύρωσης για τις εισόδους των χρηστών.
Σε αυτό το μέρος, θα χρησιμοποιήσουμε φόρμες HTML για να προσθέσουμε σύνδεση και εγγραφή στην εφαρμογή μας. Θα δούμε πώς να στέλνουμε δεδομένα σε έναν server API προγραμματιστικά και, τελικά, πώς να ορίσουμε βασικούς κανόνες επικύρωσης για τις εισόδους των χρηστών.
### Προαπαιτούμενα
Πρέπει να έχετε ολοκληρώσει το μάθημα [Πρότυπα HTML και δρομολόγηση](../1-template-route/README.md) της εφαρμογής. Επίσης, πρέπει να έχετε εγκαταστήσει το [Node.js](https://nodejs.org) και να [εκτελέσετε το API διακομιστή](../api/README.md) τοπικά, ώστε να μπορείτε να στέλνετε δεδομένα για τη δημιουργία λογαριασμών.
Πρέπει να έχετε ολοκληρώσει τα [πρότυπα HTML και τη δρομολόγηση](../1-template-route/README.md) της εφαρμογής για αυτό το μάθημα. Πρέπει επίσης να έχετε εγκαταστήσει το [Node.js](https://nodejs.org) και να [εκτελείτε το server API](../api/README.md) τοπικά, ώστε να μπορείτε να στέλνετε δεδομένα για τη δημιουργία λογαριασμών.
**Σημείωση**
Θα χρειαστεί να έχετε δύο τερματικά ανοιχτά ταυτόχρονα, όπως αναφέρεται παρακάτω:
1. Για την κύρια τραπεζική εφαρμογή που δημιουργήσαμε στο μάθημα [Πρότυπα HTML και δρομολόγηση](../1-template-route/README.md)
2. Για το [API διακομιστή της τραπεζικής εφαρμογής](../api/README.md) που μόλις ρυθμίσαμε παραπάνω.
1. Για την κύρια τραπεζική εφαρμογή που δημιουργήσαμε στο μάθημα [πρότυπα HTML και δρομολόγηση](../1-template-route/README.md)
2. Για το [Bank APP server API](../api/README.md) που μόλις ρυθμίσαμε παραπάνω.
Πρέπει να έχετε και τους δύο διακομιστές σε λειτουργία για να προχωρήσετε με το υπόλοιπο μάθημα. Ακούνε σε διαφορετικές θύρες (θύρα `3000` και θύρα `5000`), οπότε όλα θα λειτουργούν κανονικά.
Πρέπει να έχετε και τους δύο servers σε λειτουργία για να προχωρήσετε με το υπόλοιπο μάθημα. Ακούνε σε διαφορετικές θύρες (θύρα `3000` και θύρα `5000`), οπότε όλα θα λειτουργούν κανονικά.
Μπορείτε να ελέγξετε αν ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό:
Μπορείτε να ελέγξετε ότι ο server λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό:
```sh
curl http://localhost:5000/api
@ -41,7 +41,7 @@ curl http://localhost:5000/api
## Φόρμα και στοιχεία ελέγχου
Το στοιχείο `<form>` περιλαμβάνει μια ενότητα ενός εγγράφου HTML όπου ο χρήστης μπορεί να εισάγει και να υποβάλει δεδομένα μέσω διαδραστικών στοιχείων ελέγχου. Υπάρχουν διάφορα στοιχεία διεπαφής χρήστη (UI) που μπορούν να χρησιμοποιηθούν μέσα σε μια φόρμα, με πιο συνηθισμένα τα στοιχεία `<input>` και `<button>`.
Το στοιχείο `<form>` περιλαμβάνει μια ενότητα ενός εγγράφου HTML όπου ο χρήστης μπορεί να εισάγει και να υποβάλει δεδομένα με διαδραστικά στοιχεία ελέγχου. Υπάρχουν διάφορα στοιχεία διεπαφής χρήστη (UI) που μπορούν να χρησιμοποιηθούν μέσα σε μια φόρμα, με πιο συνηθισμένα τα στοιχεία `<input>` και `<button>`.
Υπάρχουν πολλοί διαφορετικοί [τύποι](https://developer.mozilla.org/docs/Web/HTML/Element/input) του `<input>`. Για παράδειγμα, για να δημιουργήσετε ένα πεδίο όπου ο χρήστης μπορεί να εισάγει το όνομα χρήστη του, μπορείτε να χρησιμοποιήσετε:
@ -49,13 +49,13 @@ curl http://localhost:5000/api
<input id="username" name="username" type="text">
```
Η ιδιότητα `name` θα χρησιμοποιηθεί ως όνομα ιδιότητας όταν τα δεδομένα της φόρμας σταλούν. Η ιδιότητα `id` χρησιμοποιείται για να συσχετίσει μια `<label>` με το στοιχείο ελέγχου της φόρμας.
Η ιδιότητα `name` θα χρησιμοποιηθεί ως το όνομα της ιδιότητας όταν τα δεδομένα της φόρμας σταλούν. Η ιδιότητα `id` χρησιμοποιείται για να συσχετίσει μια `<label>` με το στοιχείο ελέγχου της φόρμας.
> Ρίξτε μια ματιά στη λίστα με όλους τους [τύπους `<input>`](https://developer.mozilla.org/docs/Web/HTML/Element/input) και [άλλα στοιχεία ελέγχου φόρμας](https://developer.mozilla.org/docs/Learn/Forms/Other_form_controls) για να πάρετε μια ιδέα για όλα τα εγγενή στοιχεία UI που μπορείτε να χρησιμοποιήσετε κατά την κατασκευή της διεπαφής σας.
✅ Σημειώστε ότι το `<input>` είναι ένα [κενό στοιχείο](https://developer.mozilla.org/docs/Glossary/Empty_element) στο οποίο *δεν* πρέπει να προσθέσετε αντίστοιχη ετικέτα κλεισίματος. Μπορείτε, ωστόσο, να χρησιμοποιήσετε τη μορφή αυτοκλεισίματος `<input/>`, αλλά δεν είναι απαραίτητο.
Το στοιχείο `<button>` μέσα σε μια φόρμα είναι λίγο ιδιαίτερο. Αν δεν ορίσετε την ιδιότητα `type`, θα υποβάλει αυτόματα τα δεδομένα της φόρμας στον διακομιστή όταν πατηθεί. Εδώ είναι οι δυνατές τιμές για την ιδιότητα `type`:
Το στοιχείο `<button>` μέσα σε μια φόρμα είναι λίγο ιδιαίτερο. Αν δεν καθορίσετε την ιδιότητα `type`, θα υποβάλει αυτόματα τα δεδομένα της φόρμας στον server όταν πατηθεί. Εδώ είναι οι δυνατές τιμές για την ιδιότητα `type`:
- `submit`: Η προεπιλογή μέσα σε μια `<form>`, το κουμπί ενεργοποιεί την ενέργεια υποβολής της φόρμας.
- `reset`: Το κουμπί επαναφέρει όλα τα στοιχεία ελέγχου της φόρμας στις αρχικές τους τιμές.
@ -79,10 +79,10 @@ curl http://localhost:5000/api
</template>
```
Αν παρατηρήσετε προσεκτικά, θα δείτε ότι προσθέσαμε επίσης ένα στοιχείο `<label>` εδώ. Τα στοιχεία `<label>` χρησιμοποιούνται για να προσθέσουν ένα όνομα στα στοιχεία ελέγχου UI, όπως το πεδίο ονόματος χρήστη. Οι ετικέτες είναι σημαντικές για την αναγνωσιμότητα των φορμών σας, αλλά προσφέρουν και πρόσθετα οφέλη:
Αν παρατηρήσετε προσεκτικά, θα δείτε ότι προσθέσαμε επίσης ένα στοιχείο `<label>` εδώ. Τα στοιχεία `<label>` χρησιμοποιούνται για να προσθέσουν ένα όνομα στα στοιχεία UI, όπως το πεδίο ονόματος χρήστη. Οι ετικέτες είναι σημαντικές για την αναγνωσιμότητα των φορμών σας, αλλά προσφέρουν και πρόσθετα οφέλη:
- Με τη συσχέτιση μιας ετικέτας με ένα στοιχείο ελέγχου φόρμας, βοηθάτε τους χρήστες που χρησιμοποιούν τεχνολογίες υποβοήθησης (όπως αναγνώστες οθόνης) να κατανοήσουν ποια δεδομένα πρέπει να παρέχουν.
- Μπορείτε να κάνετε κλικ στην ετικέτα για να εστιάσετε απευθείας στο συσχετισμένο πεδίο, διευκολύνοντας την πρόσβαση σε συσκευές με οθόνη αφής.
- Συνδέοντας μια ετικέτα με ένα στοιχείο ελέγχου φόρμας, βοηθάτε τους χρήστες που χρησιμοποιούν τεχνολογίες υποβοήθησης (όπως αναγνώστες οθόνης) να κατανοήσουν ποια δεδομένα αναμένεται να παρέχουν.
- Μπορείτε να κάνετε κλικ στην ετικέτα για να εστιάσετε απευθείας στο συνδεδεμένο πεδίο, διευκολύνοντας την πρόσβαση σε συσκευές με οθόνη αφής.
> [Η προσβασιμότητα](https://developer.mozilla.org/docs/Learn/Accessibility/What_is_accessibility) στον ιστό είναι ένα πολύ σημαντικό θέμα που συχνά παραβλέπεται. Χάρη στα [σημασιολογικά στοιχεία HTML](https://developer.mozilla.org/docs/Learn/Accessibility/HTML), δεν είναι δύσκολο να δημιουργήσετε προσβάσιμο περιεχόμενο αν τα χρησιμοποιήσετε σωστά. Μπορείτε να [διαβάσετε περισσότερα για την προσβασιμότητα](https://developer.mozilla.org/docs/Web/Accessibility) για να αποφύγετε κοινά λάθη και να γίνετε υπεύθυνος προγραμματιστής.
@ -104,26 +104,25 @@ curl http://localhost:5000/api
</form>
```
Χρησιμοποιώντας την ιδιότητα `value`, μπορούμε να ορίσουμε μια προεπιλεγμένη τιμή για ένα συγκεκριμένο πεδίο εισόδου.
Παρατηρήστε επίσης ότι το πεδίο εισόδου για το `balance` έχει τον τύπο `number`. Φαίνεται διαφορετικό από τα άλλα πεδία; Δοκιμάστε να αλληλεπιδράσετε μαζί του.
Χρησιμοποιώντας την ιδιότητα `value`, μπορούμε να ορίσουμε μια προεπιλεγμένη τιμή για ένα συγκεκριμένο πεδίο. Παρατηρήστε επίσης ότι το πεδίο για το `balance` έχει τον τύπο `number`. Φαίνεται διαφορετικό από τα άλλα πεδία; Δοκιμάστε να αλληλεπιδράσετε μαζί του.
✅ Μπορείτε να περιηγηθείτε και να αλληλεπιδράσετε με τις φόρμες χρησιμοποιώντας μόνο το πληκτρολόγιο; Πώς θα το κάνατε αυτό;
## Υποβολή δεδομένων στον διακομιστή
## Υποβολή δεδομένων στον server
Τώρα που έχουμε μια λειτουργική διεπαφή χρήστη, το επόμενο βήμα είναι να στείλουμε τα δεδομένα στον διακομιστή. Ας κάνουμε μια γρήγορη δοκιμή χρησιμοποιώντας τον τρέχοντα κώδικα: τι συμβαίνει αν κάνετε κλικ στο κουμπί *Σύνδεση* ή *Εγγραφή*;
Τώρα που έχουμε μια λειτουργική διεπαφή χρήστη, το επόμενο βήμα είναι να στείλουμε τα δεδομένα στον server. Ας κάνουμε μια γρήγορη δοκιμή χρησιμοποιώντας τον τρέχοντα κώδικά μας: τι συμβαίνει αν κάνετε κλικ στο κουμπί *Σύνδεση* ή *Εγγραφή*;
Παρατηρήσατε την αλλαγή στη διεύθυνση URL του προγράμματος περιήγησης;
Παρατηρήσατε την αλλαγή στην ενότητα URL του προγράμματος περιήγησης;
![Στιγμιότυπο οθόνης της αλλαγής URL του προγράμματος περιήγησης μετά το κλικ στο κουμπί Εγγραφή](../../../../translated_images/click-register.e89a30bf0d4bc9ca867dc537c4cea679a7c26368bd790969082f524fed2355bc.el.png)
![Στιγμιότυπο οθόνης της αλλαγής του URL του προγράμματος περιήγησης μετά το πάτημα του κουμπιού Εγγραφή](../../../../translated_images/click-register.e89a30bf0d4bc9ca867dc537c4cea679a7c26368bd790969082f524fed2355bc.el.png)
Η προεπιλεγμένη ενέργεια για μια `<form>` είναι να υποβάλει τη φόρμα στη διεύθυνση URL του τρέχοντος διακομιστή χρησιμοποιώντας τη [μέθοδο GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3), προσθέτοντας τα δεδομένα της φόρμας απευθείας στη διεύθυνση URL. Ωστόσο, αυτή η μέθοδος έχει ορισμένα μειονεκτήματα:
Η προεπιλεγμένη ενέργεια για μια `<form>` είναι να υποβάλει τη φόρμα στη διεύθυνση URL του τρέχοντος server χρησιμοποιώντας τη [μέθοδο GET](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3), προσθέτοντας τα δεδομένα της φόρμας απευθείας στη διεύθυνση URL. Ωστόσο, αυτή η μέθοδος έχει ορισμένα μειονεκτήματα:
- Τα δεδομένα που αποστέλλονται είναι πολύ περιορισμένα σε μέγεθος (περίπου 2000 χαρακτήρες).
- Τα δεδομένα είναι άμεσα ορατά στη διεύθυνση URL (όχι ιδανικό για κωδικούς πρόσβασης).
- Δεν λειτουργεί με μεταφορτώσεις αρχείων.
Γι' αυτό μπορείτε να την αλλάξετε ώστε να χρησιμοποιεί τη [μέθοδο POST](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5), η οποία στέλνει τα δεδομένα της φόρμας στον διακομιστή στο σώμα του αιτήματος HTTP, χωρίς κανέναν από τους προηγούμενους περιορισμούς.
Γι' αυτό μπορείτε να την αλλάξετε ώστε να χρησιμοποιεί τη [μέθοδο POST](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5), η οποία στέλνει τα δεδομένα της φόρμας στον server στο σώμα του αιτήματος HTTP, χωρίς κανέναν από τους προηγούμενους περιορισμούς.
> Ενώ η POST είναι η πιο συχνά χρησιμοποιούμενη μέθοδος για την αποστολή δεδομένων, [σε ορισμένα συγκεκριμένα σενάρια](https://www.w3.org/2001/tag/doc/whenToUseGet.html) είναι προτιμότερο να χρησιμοποιείται η μέθοδος GET, όπως για την υλοποίηση ενός πεδίου αναζήτησης.
@ -135,23 +134,23 @@ curl http://localhost:5000/api
<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">
```
Τώρα δοκιμάστε να εγγραφείτε με το όνομά σας. Μετά το κλικ στο κουμπί *Εγγραφή*, θα πρέπει να δείτε κάτι σαν αυτό:
Δοκιμάστε τώρα να εγγραφείτε με το όνομά σας. Μετά το πάτημα του κουμπιού *Εγγραφή*, θα πρέπει να δείτε κάτι σαν αυτό:
![Παράθυρο προγράμματος περιήγησης στη διεύθυνση localhost:5000/api/accounts, που εμφανίζει μια συμβολοσειρά JSON με δεδομένα χρήστη](../../../../translated_images/form-post.61de4ca1b964d91a9e338416e19f218504dd0af5f762fbebabfe7ae80edf885f.el.png)
Αν όλα πάνε καλά, ο διακομιστής θα απαντήσει στο αίτημά σας με μια [JSON](https://www.json.org/json-en.html) απόκριση που περιέχει τα δεδομένα του λογαριασμού που δημιουργήθηκε.
Αν όλα πάνε καλά, ο server θα απαντήσει στο αίτημά σας με μια [JSON](https://www.json.org/json-en.html) απόκριση που περιέχει τα δεδομένα του λογαριασμού που δημιουργήθηκε.
✅ Δοκιμάστε να εγγραφείτε ξανά με το ίδιο όνομα. Τι συμβαίνει;
## Υποβολή δεδομένων χωρίς ανανέωση της σελίδας
Όπως πιθανώς παρατηρήσατε, υπάρχει ένα μικρό πρόβλημα με την προσέγγιση που μόλις χρησιμοποιήσαμε: όταν υποβάλλουμε τη φόρμα, βγαίνουμε από την εφαρμογή μας και το πρόγραμμα περιήγησης ανακατευθύνεται στη διεύθυνση URL του διακομιστή. Προσπαθούμε να αποφύγουμε όλες τις ανανεώσεις σελίδων στην εφαρμογή μας, καθώς δημιουργούμε μια [Εφαρμογή Μίας Σελίδας (SPA)](https://en.wikipedia.org/wiki/Single-page_application).
Όπως πιθανώς παρατηρήσατε, υπάρχει ένα μικρό πρόβλημα με την προσέγγιση που μόλις χρησιμοποιήσαμε: κατά την υποβολή της φόρμας, βγαίνουμε από την εφαρμογή μας και το πρόγραμμα περιήγησης ανακατευθύνεται στη διεύθυνση URL του server. Προσπαθούμε να αποφύγουμε όλες τις ανανεώσεις σελίδων με την εφαρμογή μας, καθώς δημιουργούμε μια [Εφαρμογή Μίας Σελίδας (SPA)](https://en.wikipedia.org/wiki/Single-page_application).
Για να στείλουμε τα δεδομένα της φόρμας στον διακομιστή χωρίς να αναγκάσουμε την ανανέωση της σελίδας, πρέπει να χρησιμοποιήσουμε κώδικα JavaScript. Αντί να βάζετε μια διεύθυνση URL στην ιδιότητα `action` ενός στοιχείου `<form>`, μπορείτε να χρησιμοποιήσετε οποιονδήποτε κώδικα JavaScript που ξεκινά με τη συμβολοσειρά `javascript:` για να εκτελέσετε μια προσαρμοσμένη ενέργεια. Χρησιμοποιώντας αυτό, σημαίνει επίσης ότι θα πρέπει να υλοποιήσετε ορισμένες εργασίες που προηγουμένως γίνονταν αυτόματα από το πρόγραμμα περιήγησης:
Για να στείλουμε τα δεδομένα της φόρμας στον server χωρίς να αναγκάσουμε την ανανέωση της σελίδας, πρέπει να χρησιμοποιήσουμε κώδικα JavaScript. Αντί να βάζετε μια διεύθυνση URL στην ιδιότητα `action` ενός στοιχείου `<form>`, μπορείτε να χρησιμοποιήσετε οποιονδήποτε κώδικα JavaScript που ξεκινά με τη συμβολοσειρά `javascript:` για να εκτελέσετε μια προσαρμοσμένη ενέργεια. Χρησιμοποιώντας αυτό, σημαίνει επίσης ότι θα πρέπει να υλοποιήσετε ορισμένες εργασίες που προηγουμένως γίνονταν αυτόματα από το πρόγραμμα περιήγησης:
- Ανάκτηση των δεδομένων της φόρμας.
- Μετατροπή και κωδικοποίηση των δεδομένων της φόρμας σε κατάλληλη μορφή.
- Δημιουργία του αιτήματος HTTP και αποστολή του στον διακομιστή.
- Ανάκτηση των δεδομένων της φόρμας
- Μετατροπή και κωδικοποίηση των δεδομένων της φόρμας σε κατάλληλη μορφή
- Δημιουργία του αιτήματος HTTP και αποστολή του στον server
### Εργασία
@ -172,9 +171,9 @@ function register() {
}
```
Εδώ ανακτούμε το στοιχείο της φόρμας χρησιμοποιώντας το `getElementById()` και χρησιμοποιούμε τον βοηθό [`FormData`](https://developer.mozilla.org/docs/Web/API/FormData) για να εξάγουμε τις τιμές από τα στοιχεία ελέγχου της φόρμας ως ένα σύνολο ζευγών κλειδιού/τιμής. Στη συνέχεια, μετατρέπουμε τα δεδομένα σε ένα κανονικό αντικείμενο χρησιμοποιώντας το [`Object.fromEntries()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) και τελικά τα σειριοποιούμε σε [JSON](https://www.json.org/json-en.html), μια μορφή που χρησιμοποιείται συνήθως για την ανταλλαγή δεδομένων στον ιστό.
Εδώ ανακτούμε το στοιχείο της φόρμας χρησιμοποιώντας το `getElementById()` και χρησιμοποιούμε τον βοηθό [`FormData`](https://developer.mozilla.org/docs/Web/API/FormData) για να εξαγάγουμε τις τιμές από τα στοιχεία ελέγχου της φόρμας ως ένα σύνολο ζευγών κλειδιού/τιμής. Στη συνέχεια, μετατρέπουμε τα δεδομένα σε ένα κανονικό αντικείμενο χρησιμοποιώντας το [`Object.fromEntries()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) και τελικά τα σειριοποιούμε σε [JSON](https://www.json.org/json-en.html), μια μορφή που χρησιμοποιείται συνήθως για την ανταλλαγή δεδομένων στον ιστό.
Τα δεδομένα είναι τώρα έτοιμα να σταλούν στον διακομιστή. Δημιουργήστε μια νέα συνάρτηση με όνομα `createAccount`:
Τα δεδομένα είναι τώρα έτοιμα να σταλούν στον server. Δημιουργήστε μια νέα συνάρτηση με όνομα `createAccount`:
```js
async function createAccount(account) {
@ -191,20 +190,20 @@ async function createAccount(account) {
}
```
Τι κάνει αυτή η συνάρτηση; Πρώτα, παρατηρήστε τη λέξη-κλειδί `async` εδώ. Αυτό σημαίνει ότι η συνάρτηση περιέχει κώδικα που θα εκτελεστεί [**ασύγχρονα**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Όταν χρησιμοποιείται μαζί με τη λέξη-κλειδί `await`, επιτρέπει την αναμονή για την εκτέλεση ασύγχρονου κώδικα - όπως η αναμονή για την απόκριση του διακομιστή εδώ - πριν συνεχίσει.
Τι κάνει αυτή η συνάρτηση; Πρώτα, παρατηρήστε τη λέξη-κλειδί `async` εδώ. Αυτό σημαίνει ότι η συνάρτηση περιέχει κώδικα που θα εκτελεστεί [**ασύγχρονα**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function). Όταν χρησιμοποιείται μαζί με τη λέξη-κλειδί `await`, επιτρέπει την αναμονή για την εκτέλεση ασύγχρονου κώδικα - όπως η αναμονή για την απόκριση του server εδώ - πριν συνεχίσει.
Ακολουθεί ένα σύντομο βίντεο για τη χρήση του `async/await`:
Εδώ είναι ένα γρήγορο βίντεο για τη χρήση του `async/await`:
[![Async και Await για τη διαχείριση υποσχέσεων](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async και Await για τη διαχείριση υποσχέσεων")
> 🎥 Κάντε κλικ στην εικόνα παραπάνω για ένα βίντεο σχετικά με το async/await.
Χρησιμοποιούμε το API `fetch()` για να στείλουμε δεδομένα JSON στον διακομιστή. Αυτή η μέθοδος παίρνει 2 παραμέτρους:
Χρησιμοποιούμε το API `fetch()` για να στείλουμε δεδομένα JSON στον server. Αυτή η μέθοδος παίρνει 2 παραμέτρους:
- Τη διεύθυνση URL του διακομιστή, οπότε βάζουμε ξανά το `//localhost:5000/api/accounts` εδώ.
- Τις ρυθμίσεις του αιτήματος. Εκεί ορίζουμε τη μέθοδο σε `POST` και παρέχουμε το `body` για το αίτημα. Καθώς στέλνουμε δεδομένα JSON στον διακομιστή, πρέπει επίσης να ορίσουμε την κεφαλίδα `Content-Type` σε `application/json`, ώστε ο διακομιστής να γνωρίζει πώς να ερμηνεύσει το περιεχόμενο.
- Τη διεύθυνση URL του server, οπότε βάζουμε ξανά το `//localhost:5000/api/accounts` εδώ.
- Τις ρυθμίσεις του αιτήματος. Εκεί ορίζουμε τη μέθοδο σε `POST` και παρέχουμε το `body` για το αίτημα. Καθώς στέλνουμε δεδομένα JSON στον server, πρέπει επίσης να ορίσουμε την κεφαλίδα `Content-Type` σε `application/json`, ώστε ο server να γνωρίζει πώς να ερμηνεύσει το περιεχόμενο.
Καθώς ο διακομιστής θα απαντήσει στο αίτημα με JSON, μπορούμε να χρησιμοποιήσουμε το `await response.json()` για να αναλύσουμε το περιεχόμενο JSON και να επιστρέψουμε το αποτέλεσμα ως αντικείμενο. Σημειώστε ότι αυτή η μέθοδος είναι ασύγχρονη, οπότε χρησιμοποιούμε τη λέξη-κλειδί `await` εδώ πριν επιστρέψουμε, για να διασφαλίσουμε ότι τυχόν σφάλματα κατά την ανάλυση θα πιαστούν επίσης.
Καθώς ο server θα απαντήσει στο αίτημα με JSON, μπορούμε να χρησιμοποιήσουμε το `await response.json()` για να αναλύσουμε το περιεχόμενο JSON και να επιστρέψουμε το αποτέλεσμα ως αντικείμενο. Σημειώστε ότι αυτή η μέθοδος είναι ασύγχρονη, οπότε χρησιμοποιούμε τη λέξη-κλειδί `await` εδώ πριν επιστρέψουμε για να διασφαλίσουμε ότι τυχόν σφάλματα κατά την ανάλυση θα πιαστούν επίσης.
Τώρα προσθέστε λίγο κώδικα στη συνάρτηση `register` για να καλέσετε το `createAccount()`:
@ -235,11 +234,15 @@ async function register() {
}
```
Ήταν λίγο μακρύ, αλλά τα καταφέραμε! Αν ανοίξετε τα [εργαλεία προγραμματιστή του προγράμματος περιήγησης](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools) και δοκιμάσετε να εγγραφείτε σε
> Συμβουλή: μπορείτε να προσαρμόσετε την εμφάνιση των στοιχείων ελέγχου της φόρμας σας ανάλογα με το αν είναι έγκυρα ή όχι, χρησιμοποιώντας τις ψευδο-κλάσεις CSS `:valid` και `:invalid`.
Ήταν λίγο μακρύ, αλλά τα καταφέραμε! Αν ανοίξετε τα [εργαλεία προγραμματιστή του προγράμματος περιήγησης](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools) και δοκιμάσετε να εγγραφείτε σε έναν νέο λογαριασμό, δεν θα δείτε καμία αλλαγή στη σελίδα, αλλά ένα μήνυμα θα εμφανιστεί στην κονσόλα επιβεβαιώνοντας ότι όλα λειτουργούν.
![Στιγμιότυπο οθόνης που δείχνει μήνυμα καταγραφής στην κονσόλα του προγράμματος περιήγησης](../../../../translated_images/browser-console.efaf0b51aaaf67782a29e1a0bb32cc063f189b18e894eb5926e02f1abe864ec2.el.png)
✅ Πιστεύετε ότι τα δεδομένα αποστέλλονται
> Συμβουλή: μπορείτε να προσαρμόσετε την εμφάνιση των στοιχείων ελέγχου της φόρμας σας ανάλογα με το αν είναι έγκυρα ή όχι, χρησιμοποιώντας τις ψευδοκλάσεις CSS `:valid` και `:invalid`.
### Εργασία
Υπάρχουν 2 απαιτούμενα πεδία για τη δημιουργία ενός έγκυρου νέου λογαριασμού, το όνομα χρήστη και το νόμισμα, ενώ τα υπόλοιπα πεδία είναι προαιρετικά. Ενημερώστε το HTML της φόρμας, χρησιμοποιώντας τόσο το χαρακτηριστικό `required` όσο και το κείμενο στην ετικέτα του πεδίου ώστε να:
Υπάρχουν 2 απαιτούμενα πεδία για τη δημιουργία ενός έγκυρου νέου λογαριασμού: το όνομα χρήστη και το νόμισμα, ενώ τα υπόλοιπα πεδία είναι προαιρετικά. Ενημερώστε το HTML της φόρμας, χρησιμοποιώντας τόσο το χαρακτηριστικό `required` όσο και το κείμενο στην ετικέτα του πεδίου ώστε να:
```html
<label for="user">Username (required)</label>
@ -261,13 +264,13 @@ async function register() {
<input id="description" name="description" type="text" maxlength="100">
```
Τώρα, αν πατήσετε το κουμπί *Εγγραφή* και κάποιο πεδίο δεν πληροί έναν από τους κανόνες επικύρωσης που ορίσαμε, θα πρέπει να δείτε κάτι σαν αυτό:
Τώρα, αν πατήσετε το κουμπί *Εγγραφή* και κάποιο πεδίο δεν πληροί έναν από τους κανόνες επικύρωσης που ορίσαμε, θα δείτε κάτι σαν αυτό:
![Στιγμιότυπο οθόνης που δείχνει το σφάλμα επικύρωσης όταν προσπαθείτε να υποβάλετε τη φόρμα](../../../../translated_images/validation-error.8bd23e98d416c22f80076d04829a4bb718e0e550fd622862ef59008ccf0d5dce.el.png)
Η επικύρωση όπως αυτή που πραγματοποιείται *πριν* σταλούν δεδομένα στον διακομιστή ονομάζεται **επικύρωση από την πλευρά του πελάτη** (client-side validation). Αλλά σημειώστε ότι δεν είναι πάντα δυνατό να πραγματοποιηθούν όλοι οι έλεγχοι χωρίς την αποστολή δεδομένων. Για παράδειγμα, δεν μπορούμε να ελέγξουμε εδώ αν υπάρχει ήδη λογαριασμός με το ίδιο όνομα χρήστη χωρίς να στείλουμε ένα αίτημα στον διακομιστή. Πρόσθετη επικύρωση που πραγματοποιείται στον διακομιστή ονομάζεται **επικύρωση από την πλευρά του διακομιστή** (server-side validation).
Η επικύρωση που πραγματοποιείται *πριν* σταλούν δεδομένα στον διακομιστή ονομάζεται **επικύρωση από την πλευρά του πελάτη** (client-side validation). Ωστόσο, σημειώστε ότι δεν είναι πάντα δυνατό να πραγματοποιηθούν όλοι οι έλεγχοι χωρίς την αποστολή δεδομένων. Για παράδειγμα, δεν μπορούμε να ελέγξουμε εδώ αν υπάρχει ήδη λογαριασμός με το ίδιο όνομα χρήστη χωρίς να στείλουμε ένα αίτημα στον διακομιστή. Η πρόσθετη επικύρωση που πραγματοποιείται στον διακομιστή ονομάζεται **επικύρωση από την πλευρά του διακομιστή** (server-side validation).
Συνήθως, και οι δύο τύποι επικύρωσης πρέπει να υλοποιούνται. Ενώ η χρήση επικύρωσης από την πλευρά του πελάτη βελτιώνει την εμπειρία του χρήστη παρέχοντας άμεση ανατροφοδότηση, η επικύρωση από την πλευρά του διακομιστή είναι κρίσιμη για να διασφαλιστεί ότι τα δεδομένα του χρήστη που επεξεργάζεστε είναι έγκυρα και ασφαλή.
Συνήθως, και οι δύο μέθοδοι πρέπει να υλοποιούνται. Ενώ η χρήση της επικύρωσης από την πλευρά του πελάτη βελτιώνει την εμπειρία του χρήστη παρέχοντας άμεση ανατροφοδότηση, η επικύρωση από την πλευρά του διακομιστή είναι κρίσιμη για να διασφαλιστεί ότι τα δεδομένα του χρήστη που επεξεργάζεστε είναι έγκυρα και ασφαλή.
---
@ -285,7 +288,7 @@ async function register() {
## Ανασκόπηση & Αυτομελέτη
Οι προγραμματιστές έχουν γίνει πολύ δημιουργικοί στις προσπάθειές τους για τη δημιουργία φορμών, ειδικά όσον αφορά τις στρατηγικές επικύρωσης. Μάθετε για διαφορετικές ροές φορμών κοιτάζοντας το [CodePen](https://codepen.com). Μπορείτε να βρείτε κάποιες ενδιαφέρουσες και εμπνευσμένες φόρμες;
Οι προγραμματιστές έχουν γίνει πολύ δημιουργικοί στις προσπάθειές τους για τη δημιουργία φορμών, ειδικά όσον αφορά τις στρατηγικές επικύρωσης. Μάθετε για διαφορετικές ροές φορμών εξετάζοντας το [CodePen](https://codepen.com). Μπορείτε να βρείτε ενδιαφέρουσες και εμπνευσμένες φόρμες;
## Εργασία
@ -293,5 +296,5 @@ async function register() {
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε κάθε προσπάθεια για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,29 +1,29 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "f587e913e3f7c0b1c549a05dd74ee8e5",
"translation_date": "2025-08-26T22:59:05+00:00",
"original_hash": "89d0df9854ed020f155e94882ae88d4c",
"translation_date": "2025-08-29T06:59:20+00:00",
"source_file": "7-bank-project/3-data/README.md",
"language_code": "el"
}
-->
# Δημιουργία Εφαρμογής Τραπεζικής Διαχείρισης Μέρος 3: Μέθοδοι Ανάκτησης και Χρήσης Δεδομένων
# Δημιουργία Εφαρμογής Τραπεζικής Μέρος 3: Μέθοδοι Ανάκτησης και Χρήσης Δεδομένων
## Ερωτηματολόγιο Πριν το Μάθημα
[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/45)
[Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/45)
### Εισαγωγή
Στον πυρήνα κάθε διαδικτυακής εφαρμογής βρίσκονται τα *δεδομένα*. Τα δεδομένα μπορούν να έχουν πολλές μορφές, αλλά ο κύριος σκοπός τους είναι πάντα να εμφανίζουν πληροφορίες στον χρήστη. Με τις διαδικτυακές εφαρμογές να γίνονται όλο και πιο διαδραστικές και πολύπλοκες, το πώς ο χρήστης αποκτά πρόσβαση και αλληλεπιδρά με τις πληροφορίες αποτελεί πλέον βασικό μέρος της ανάπτυξης ιστοσελίδων.
Στον πυρήνα κάθε διαδικτυακής εφαρμογής βρίσκονται τα *δεδομένα*. Τα δεδομένα μπορούν να έχουν πολλές μορφές, αλλά ο κύριος σκοπός τους είναι πάντα να εμφανίζουν πληροφορίες στον χρήστη. Με τις διαδικτυακές εφαρμογές να γίνονται όλο και πιο διαδραστικές και πολύπλοκες, ο τρόπος με τον οποίο ο χρήστης αποκτά πρόσβαση και αλληλεπιδρά με τις πληροφορίες αποτελεί πλέον βασικό μέρος της ανάπτυξης ιστοσελίδων.
Σε αυτό το μάθημα, θα δούμε πώς να ανακτούμε δεδομένα από έναν διακομιστή ασύγχρονα και να χρησιμοποιούμε αυτά τα δεδομένα για να εμφανίζουμε πληροφορίες σε μια ιστοσελίδα χωρίς να χρειάζεται να ανανεώνουμε το HTML.
Σε αυτό το μάθημα, θα δούμε πώς να ανακτούμε δεδομένα από έναν διακομιστή ασύγχρονα και να χρησιμοποιούμε αυτά τα δεδομένα για να εμφανίζουμε πληροφορίες σε μια ιστοσελίδα χωρίς να χρειάζεται να φορτώσουμε ξανά το HTML.
### Προαπαιτούμενα
Πρέπει να έχετε δημιουργήσει το [Φόρμα Εισόδου και Εγγραφής](../2-forms/README.md) μέρος της διαδικτυακής εφαρμογής για αυτό το μάθημα. Επίσης, πρέπει να έχετε εγκαταστήσει το [Node.js](https://nodejs.org) και να [εκτελέσετε το API του διακομιστή](../api/README.md) τοπικά ώστε να αποκτήσετε δεδομένα λογαριασμού.
Πρέπει να έχετε δημιουργήσει τη [Φόρμα Εισόδου και Εγγραφής](../2-forms/README.md) της διαδικτυακής εφαρμογής για αυτό το μάθημα. Επίσης, πρέπει να εγκαταστήσετε το [Node.js](https://nodejs.org) και να [εκτελέσετε το API του διακομιστή](../api/README.md) τοπικά ώστε να αποκτήσετε δεδομένα λογαριασμού.
Μπορείτε να ελέγξετε αν ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό:
Μπορείτε να δοκιμάσετε ότι ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό:
```sh
curl http://localhost:5000/api
@ -34,17 +34,17 @@ curl http://localhost:5000/api
## AJAX και ανάκτηση δεδομένων
Οι παραδοσιακές ιστοσελίδες ενημερώνουν το περιεχόμενο που εμφανίζεται όταν ο χρήστης επιλέγει έναν σύνδεσμο ή υποβάλλει δεδομένα μέσω μιας φόρμας, ανανεώνοντας ολόκληρη τη σελίδα HTML. Κάθε φορά που χρειάζονται νέα δεδομένα, ο διακομιστής επιστρέφει μια ολοκαίνουργια σελίδα HTML που πρέπει να επεξεργαστεί ο περιηγητής, διακόπτοντας τη δράση του χρήστη και περιορίζοντας τις αλληλεπιδράσεις κατά τη διάρκεια της ανανέωσης. Αυτή η ροή εργασίας ονομάζεται επίσης *Εφαρμογή Πολλαπλών Σελίδων* ή *MPA*.
Οι παραδοσιακές ιστοσελίδες ενημερώνουν το περιεχόμενο που εμφανίζεται όταν ο χρήστης επιλέγει έναν σύνδεσμο ή υποβάλλει δεδομένα μέσω μιας φόρμας, φορτώνοντας ξανά ολόκληρη τη σελίδα HTML. Κάθε φορά που χρειάζονται νέα δεδομένα, ο διακομιστής επιστρέφει μια ολοκαίνουργια σελίδα HTML που πρέπει να επεξεργαστεί ο περιηγητής, διακόπτοντας την τρέχουσα ενέργεια του χρήστη και περιορίζοντας τις αλληλεπιδράσεις κατά τη διάρκεια της φόρτωσης. Αυτή η ροή εργασίας ονομάζεται επίσης *Εφαρμογή Πολλαπλών Σελίδων* ή *MPA*.
![Ροή ενημέρωσης σε εφαρμογή πολλαπλών σελίδων](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.el.png)
Όταν οι διαδικτυακές εφαρμογές άρχισαν να γίνονται πιο πολύπλοκες και διαδραστικές, εμφανίστηκε μια νέα τεχνική που ονομάζεται [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Αυτή η τεχνική επιτρέπει στις διαδικτυακές εφαρμογές να στέλνουν και να ανακτούν δεδομένα από έναν διακομιστή ασύγχρονα χρησιμοποιώντας JavaScript, χωρίς να χρειάζεται να ανανεώνεται η σελίδα HTML, με αποτέλεσμα ταχύτερες ενημερώσεις και ομαλότερες αλληλεπιδράσεις χρήστη. Όταν λαμβάνονται νέα δεδομένα από τον διακομιστή, η τρέχουσα σελίδα HTML μπορεί επίσης να ενημερωθεί με JavaScript χρησιμοποιώντας το [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) API. Με την πάροδο του χρόνου, αυτή η προσέγγιση εξελίχθηκε σε αυτό που τώρα ονομάζεται [*Εφαρμογή Μίας Σελίδας* ή *SPA*](https://en.wikipedia.org/wiki/Single-page_application).
Όταν οι διαδικτυακές εφαρμογές άρχισαν να γίνονται πιο πολύπλοκες και διαδραστικές, εμφανίστηκε μια νέα τεχνική που ονομάζεται [AJAX (Asynchronous JavaScript and XML)](https://en.wikipedia.org/wiki/Ajax_(programming)). Αυτή η τεχνική επιτρέπει στις διαδικτυακές εφαρμογές να στέλνουν και να ανακτούν δεδομένα από έναν διακομιστή ασύγχρονα χρησιμοποιώντας JavaScript, χωρίς να χρειάζεται να φορτώσουν ξανά τη σελίδα HTML, με αποτέλεσμα ταχύτερες ενημερώσεις και πιο ομαλές αλληλεπιδράσεις χρήστη. Όταν λαμβάνονται νέα δεδομένα από τον διακομιστή, η τρέχουσα σελίδα HTML μπορεί επίσης να ενημερωθεί με JavaScript χρησιμοποιώντας το [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) API. Με την πάροδο του χρόνου, αυτή η προσέγγιση εξελίχθηκε σε αυτό που τώρα ονομάζεται [*Εφαρμογή Μίας Σελίδας* ή *SPA*](https://en.wikipedia.org/wiki/Single-page_application).
![Ροή ενημέρωσης σε εφαρμογή μίας σελίδας](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.el.png)
Όταν το AJAX εισήχθη για πρώτη φορά, η μόνη διαθέσιμη API για ασύγχρονη ανάκτηση δεδομένων ήταν το [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Ωστόσο, οι σύγχρονοι περιηγητές υλοποιούν πλέον και την πιο βολική και ισχυρή [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), η οποία χρησιμοποιεί promises και είναι καλύτερα προσαρμοσμένη για τη διαχείριση δεδομένων JSON.
Όταν το AJAX πρωτοεμφανίστηκε, η μόνη διαθέσιμη API για ασύγχρονη ανάκτηση δεδομένων ήταν το [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Ωστόσο, οι σύγχρονοι περιηγητές πλέον υλοποιούν επίσης την πιο βολική και ισχυρή [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), η οποία χρησιμοποιεί υποσχέσεις (promises) και είναι καλύτερα προσαρμοσμένη για χειρισμό δεδομένων JSON.
> Παρόλο που όλοι οι σύγχρονοι περιηγητές υποστηρίζουν το `Fetch API`, αν θέλετε η διαδικτυακή σας εφαρμογή να λειτουργεί σε παλαιότερους περιηγητές, είναι πάντα καλή ιδέα να ελέγχετε πρώτα τον [πίνακα συμβατότητας στο caniuse.com](https://caniuse.com/fetch).
> Παρόλο που όλοι οι σύγχρονοι περιηγητές υποστηρίζουν το `Fetch API`, αν θέλετε η διαδικτυακή σας εφαρμογή να λειτουργεί σε παλαιότερους περιηγητές, είναι πάντα καλή ιδέα να ελέγξετε πρώτα τον [πίνακα συμβατότητας στο caniuse.com](https://caniuse.com/fetch).
### Εργασία
@ -57,9 +57,9 @@ async function login() {
}
```
Ξεκινάμε ανακτώντας το στοιχείο της φόρμας με τη μέθοδο `getElementById()`, και στη συνέχεια παίρνουμε το όνομα χρήστη από την είσοδο με `loginForm.user.value`. Κάθε στοιχείο φόρμας μπορεί να προσπελαστεί μέσω του ονόματός του (που ορίζεται στο HTML με το χαρακτηριστικό `name`) ως ιδιότητα της φόρμας.
Ξεκινάμε ανακτώντας το στοιχείο της φόρμας με το `getElementById()`, και στη συνέχεια παίρνουμε το όνομα χρήστη από την είσοδο με το `loginForm.user.value`. Κάθε στοιχείο φόρμας μπορεί να προσπελαστεί μέσω του ονόματός του (που ορίζεται στο HTML χρησιμοποιώντας το χαρακτηριστικό `name`) ως ιδιότητα της φόρμας.
Με παρόμοιο τρόπο με αυτόν που χρησιμοποιήσαμε για την εγγραφή, θα δημιουργήσουμε μια άλλη συνάρτηση για να εκτελέσουμε ένα αίτημα στον διακομιστή, αλλά αυτή τη φορά για την ανάκτηση των δεδομένων του λογαριασμού:
Με παρόμοιο τρόπο όπως κάναμε για την εγγραφή, θα δημιουργήσουμε μια άλλη συνάρτηση για την εκτέλεση αιτήματος στον διακομιστή, αλλά αυτή τη φορά για την ανάκτηση των δεδομένων του λογαριασμού:
```js
async function getAccount(user) {
@ -72,11 +72,11 @@ async function getAccount(user) {
}
```
Χρησιμοποιούμε το `fetch` API για να ζητήσουμε δεδομένα ασύγχρονα από τον διακομιστή, αλλά αυτή τη φορά δεν χρειαζόμαστε επιπλέον παραμέτρους πέρα από το URL που θα καλέσουμε, καθώς απλώς ζητάμε δεδομένα. Από προεπιλογή, το `fetch` δημιουργεί ένα HTTP αίτημα [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), το οποίο είναι αυτό που χρειαζόμαστε εδώ.
Χρησιμοποιούμε το `fetch` API για να ζητήσουμε δεδομένα ασύγχρονα από τον διακομιστή, αλλά αυτή τη φορά δεν χρειαζόμαστε επιπλέον παραμέτρους εκτός από το URL που θα καλέσουμε, καθώς απλώς ζητάμε δεδομένα. Από προεπιλογή, το `fetch` δημιουργεί ένα HTTP αίτημα [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), το οποίο είναι αυτό που χρειαζόμαστε εδώ.
Η `encodeURIComponent()` είναι μια συνάρτηση που διαφεύγει ειδικούς χαρακτήρες για URL. Τι προβλήματα θα μπορούσαμε να έχουμε αν δεν καλέσουμε αυτή τη συνάρτηση και χρησιμοποιήσουμε απευθείας την τιμή `user` στο URL;
Το `encodeURIComponent()` είναι μια συνάρτηση που διαφεύγει ειδικούς χαρακτήρες για το URL. Τι προβλήματα θα μπορούσαμε να έχουμε αν δεν καλέσουμε αυτή τη συνάρτηση και χρησιμοποιήσουμε απευθείας την τιμή `user` στο URL;
Ας ενημερώσουμε τώρα τη συνάρτηση `login` για να χρησιμοποιεί τη `getAccount`:
Ας ενημερώσουμε τώρα τη συνάρτηση `login` για να χρησιμοποιεί το `getAccount`:
```js
async function login() {
@ -93,7 +93,7 @@ async function login() {
}
```
Αρχικά, επειδή η `getAccount` είναι μια ασύγχρονη συνάρτηση, πρέπει να τη συνδυάσουμε με τη λέξη-κλειδί `await` για να περιμένουμε το αποτέλεσμα του διακομιστή. Όπως με κάθε αίτημα στον διακομιστή, πρέπει επίσης να διαχειριστούμε περιπτώσεις σφαλμάτων. Προς το παρόν, θα προσθέσουμε μόνο ένα μήνυμα καταγραφής για να εμφανίσουμε το σφάλμα και θα επιστρέψουμε σε αυτό αργότερα.
Πρώτα, καθώς το `getAccount` είναι μια ασύγχρονη συνάρτηση, πρέπει να το ταιριάξουμε με τη λέξη-κλειδί `await` για να περιμένουμε το αποτέλεσμα του διακομιστή. Όπως με κάθε αίτημα στον διακομιστή, πρέπει επίσης να χειριστούμε περιπτώσεις σφαλμάτων. Προς το παρόν, θα προσθέσουμε μόνο ένα μήνυμα καταγραφής για να εμφανίσουμε το σφάλμα και θα επιστρέψουμε σε αυτό αργότερα.
Στη συνέχεια, πρέπει να αποθηκεύσουμε τα δεδομένα κάπου ώστε να μπορούμε να τα χρησιμοποιήσουμε αργότερα για να εμφανίσουμε τις πληροφορίες του πίνακα ελέγχου. Επειδή η μεταβλητή `account` δεν υπάρχει ακόμα, θα δημιουργήσουμε μια καθολική μεταβλητή στην κορυφή του αρχείου μας:
@ -118,25 +118,25 @@ account = result;
navigate('/dashboard');
```
✅ Γνωρίζατε ότι από προεπιλογή, μπορείτε να καλέσετε APIs διακομιστή μόνο από τον *ίδιο τομέα και θύρα* με τη σελίδα που βλέπετε; Αυτός είναι ένας μηχανισμός ασφαλείας που επιβάλλεται από τους περιηγητές. Αλλά περιμένετε, η διαδικτυακή μας εφαρμογή εκτελείται στο `localhost:3000` ενώ το API του διακομιστή εκτελείται στο `localhost:5000`, γιατί λειτουργεί; Χρησιμοποιώντας μια τεχνική που ονομάζεται [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/docs/Web/HTTP/CORS), είναι δυνατό να εκτελούνται αιτήματα HTTP μεταξύ διαφορετικών προελεύσεων αν ο διακομιστής προσθέσει ειδικές κεφαλίδες στην απάντηση, επιτρέποντας εξαιρέσεις για συγκεκριμένους τομείς.
✅ Γνωρίζατε ότι από προεπιλογή, μπορείτε να καλείτε APIs διακομιστή μόνο από τον *ίδιο τομέα και θύρα* με τη σελίδα που βλέπετε; Αυτός είναι ένας μηχανισμός ασφαλείας που επιβάλλεται από τους περιηγητές. Αλλά περιμένετε, η διαδικτυακή μας εφαρμογή εκτελείται στο `localhost:3000` ενώ το API του διακομιστή εκτελείται στο `localhost:5000`, γιατί λειτουργεί; Χρησιμοποιώντας μια τεχνική που ονομάζεται [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/docs/Web/HTTP/CORS), είναι δυνατόν να εκτελούνται αιτήματα HTTP μεταξύ διαφορετικών προελεύσεων αν ο διακομιστής προσθέσει ειδικές κεφαλίδες στην απάντηση, επιτρέποντας εξαιρέσεις για συγκεκριμένους τομείς.
> Μάθετε περισσότερα για τα APIs παρακολουθώντας αυτό το [μάθημα](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon)
## Ενημέρωση HTML για εμφάνιση δεδομένων
Τώρα που έχουμε τα δεδομένα του χρήστη, πρέπει να ενημερώσουμε το υπάρχον HTML για να τα εμφανίσουμε. Ήδη γνωρίζουμε πώς να ανακτούμε ένα στοιχείο από το DOM χρησιμοποιώντας, για παράδειγμα, το `document.getElementById()`. Αφού έχετε ένα βασικό στοιχείο, εδώ είναι μερικά APIs που μπορείτε να χρησιμοποιήσετε για να το τροποποιήσετε ή να προσθέσετε παιδιά σε αυτό:
Τώρα που έχουμε τα δεδομένα του χρήστη, πρέπει να ενημερώσουμε το υπάρχον HTML για να τα εμφανίσουμε. Ήδη γνωρίζουμε πώς να ανακτούμε ένα στοιχείο από το DOM χρησιμοποιώντας για παράδειγμα το `document.getElementById()`. Αφού έχετε ένα βασικό στοιχείο, εδώ είναι μερικά APIs που μπορείτε να χρησιμοποιήσετε για να το τροποποιήσετε ή να προσθέσετε παιδικά στοιχεία σε αυτό:
- Χρησιμοποιώντας την ιδιότητα [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) μπορείτε να αλλάξετε το κείμενο ενός στοιχείου. Σημειώστε ότι η αλλαγή αυτής της τιμής αφαιρεί όλα τα παιδιά του στοιχείου (αν υπάρχουν) και τα αντικαθιστά με το παρεχόμενο κείμενο. Ως εκ τούτου, είναι επίσης μια αποδοτική μέθοδος για να αφαιρέσετε όλα τα παιδιά ενός δεδομένου στοιχείου αναθέτοντας μια κενή συμβολοσειρά `''` σε αυτό.
- Χρησιμοποιώντας την ιδιότητα [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) μπορείτε να αλλάξετε το κείμενο ενός στοιχείου. Σημειώστε ότι η αλλαγή αυτής της τιμής αφαιρεί όλα τα παιδιά του στοιχείου (αν υπάρχουν) και τα αντικαθιστά με το παρεχόμενο κείμενο. Ως εκ τούτου, είναι επίσης μια αποτελεσματική μέθοδος για την αφαίρεση όλων των παιδιών ενός δεδομένου στοιχείου αναθέτοντας μια κενή συμβολοσειρά `''` σε αυτό.
- Χρησιμοποιώντας το [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) μαζί με τη μέθοδο [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) μπορείτε να δημιουργήσετε και να επισυνάψετε ένα ή περισσότερα νέα παιδιά.
- Χρησιμοποιώντας το [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) μαζί με τη μέθοδο [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append) μπορείτε να δημιουργήσετε και να επισυνάψετε ένα ή περισσότερα νέα παιδικά στοιχεία.
✅ Χρησιμοποιώντας την ιδιότητα [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) ενός στοιχείου είναι επίσης δυνατό να αλλάξετε τα HTML περιεχόμενά του, αλλά αυτή η μέθοδος πρέπει να αποφεύγεται καθώς είναι ευάλωτη σε επιθέσεις [cross-site scripting (XSS)](https://developer.mozilla.org/docs/Glossary/Cross-site_scripting).
✅ Χρησιμοποιώντας την ιδιότητα [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) ενός στοιχείου είναι επίσης δυνατό να αλλάξετε τα HTML περιεχόμενά του, αλλά αυτή πρέπει να αποφεύγεται καθώς είναι ευάλωτη σε επιθέσεις [cross-site scripting (XSS)](https://developer.mozilla.org/docs/Glossary/Cross-site_scripting).
### Εργασία
Πριν προχωρήσουμε στην οθόνη του πίνακα ελέγχου, υπάρχει κάτι ακόμα που πρέπει να κάνουμε στη σελίδα *login*. Προς το παρόν, αν προσπαθήσετε να συνδεθείτε με ένα όνομα χρήστη που δεν υπάρχει, εμφανίζεται ένα μήνυμα στην κονσόλα, αλλά για έναν κανονικό χρήστη δεν αλλάζει τίποτα και δεν ξέρετε τι συμβαίνει.
Πριν προχωρήσουμε στην οθόνη του πίνακα ελέγχου, υπάρχει κάτι ακόμα που πρέπει να κάνουμε στη σελίδα *login*. Προς το παρόν, αν προσπαθήσετε να συνδεθείτε με ένα όνομα χρήστη που δεν υπάρχει, εμφανίζεται ένα μήνυμα στην κονσόλα αλλά για έναν κανονικό χρήστη τίποτα δεν αλλάζει και δεν ξέρετε τι συμβαίνει.
Ας προσθέσουμε ένα στοιχείο κράτησης θέσης στη φόρμα εισόδου όπου μπορούμε να εμφανίσουμε ένα μήνυμα σφάλματος αν χρειαστεί. Ένα καλό σημείο θα ήταν ακριβώς πριν από το κουμπί `<button>`:
Ας προσθέσουμε ένα στοιχείο κράτησης θέσης στη φόρμα εισόδου όπου μπορούμε να εμφανίσουμε ένα μήνυμα σφάλματος αν χρειαστεί. Ένα καλό μέρος θα ήταν ακριβώς πριν το κουμπί εισόδου `<button>`:
```html
...
@ -145,7 +145,7 @@ navigate('/dashboard');
...
```
Αυτό το στοιχείο `<div>` είναι κενό, που σημαίνει ότι τίποτα δεν θα εμφανιστεί στην οθόνη μέχρι να προσθέσουμε κάποιο περιεχόμενο σε αυτό. Του δίνουμε επίσης ένα `id` ώστε να μπορούμε να το ανακτήσουμε εύκολα με JavaScript.
Αυτό το στοιχείο `<div>` είναι κενό, που σημαίνει ότι τίποτα δεν θα εμφανίζεται στην οθόνη μέχρι να προσθέσουμε κάποιο περιεχόμενο σε αυτό. Του δίνουμε επίσης ένα `id` ώστε να μπορούμε να το ανακτήσουμε εύκολα με JavaScript.
Επιστρέψτε στο αρχείο `app.js` και δημιουργήστε μια νέα βοηθητική συνάρτηση `updateElement`:
@ -156,7 +156,7 @@ function updateElement(id, text) {
}
```
Αυτή είναι αρκετά απλή: δεδομένου ενός *id* στοιχείου και ενός *text*, θα ενημερώσει το περιεχόμενο κειμένου του στοιχείου DOM με το αντίστοιχο `id`. Ας χρησιμοποιήσουμε αυτή τη μέθοδο στη θέση του προηγούμενου μηνύματος σφάλματος στη συνάρτηση `login`:
Αυτή είναι αρκετά απλή: δεδομένου ενός *id* στοιχείου και *κειμένου*, θα ενημερώσει το περιεχόμενο κειμένου του στοιχείου DOM με το αντίστοιχο `id`. Ας χρησιμοποιήσουμε αυτή τη μέθοδο αντί για το προηγούμενο μήνυμα σφάλματος στη συνάρτηση `login`:
```js
if (data.error) {
@ -164,11 +164,11 @@ if (data.error) {
}
```
Τώρα, αν προσπαθήσετε να συνδεθείτε με έναν μη έγκυρο λογαριασμό, θα πρέπει να δείτε κάτι σαν αυτό:
Τώρα αν προσπαθήσετε να συνδεθείτε με έναν μη έγκυρο λογαριασμό, θα πρέπει να δείτε κάτι σαν αυτό:
![Στιγμιότυπο οθόνης που δείχνει το μήνυμα σφάλματος κατά τη σύνδεση](../../../../translated_images/login-error.416fe019b36a63276764c2349df5d99e04ebda54fefe60c715ee87a28d5d4ad0.el.png)
Τώρα έχουμε κείμενο σφάλματος που εμφανίζεται οπτικά, αλλά αν το δοκιμάσετε με έναν αναγνώστη οθόνης, θα παρατηρήσετε ότι δεν ανακοινώνεται τίποτα. Για να ανακοινωθεί το κείμενο που προστίθεται δυναμικά σε μια σελίδα από τους αναγνώστες οθόνης, θα χρειαστεί να χρησιμοποιήσουμε κάτι που ονομάζεται [Live Region](https://developer.mozilla.org/docs/Web/Accessibility/ARIA/ARIA_Live_Regions). Εδώ θα χρησιμοποιήσουμε έναν συγκεκριμένο τύπο live region που ονομάζεται alert:
Τώρα έχουμε κείμενο σφάλματος που εμφανίζεται οπτικά, αλλά αν το δοκιμάσετε με έναν αναγνώστη οθόνης θα παρατηρήσετε ότι τίποτα δεν ανακοινώνεται. Για να ανακοινωθεί το κείμενο που προστίθεται δυναμικά σε μια σελίδα από τους αναγνώστες οθόνης, θα χρειαστεί να χρησιμοποιήσει κάτι που ονομάζεται [Live Region](https://developer.mozilla.org/docs/Web/Accessibility/ARIA/ARIA_Live_Regions). Εδώ θα χρησιμοποιήσουμε έναν συγκεκριμένο τύπο live region που ονομάζεται alert:
```html
<div id="loginError" role="alert"></div>
@ -180,7 +180,7 @@ if (data.error) {
Χρησιμοποιώντας τις ίδιες τεχνικές που μόλις είδαμε, θα φροντίσουμε επίσης να εμφανίσουμε τις πληροφορίες του λογαριασμού στη σελίδα του πίνακα ελέγχου.
Αυτό είναι ένα αντικείμενο λογαριασμού που λαμβάνεται από τον διακομιστή:
Αυτό είναι το πώς μοιάζει ένα αντικείμενο λογαριασμού που λαμβάνεται από τον διακομιστή:
```json
{
@ -196,11 +196,11 @@ if (data.error) {
}
```
> Σημείωση: για να διευκολύνετε τη ζωή σας, μπορείτε να χρησιμοποιήσετε τον προϋπάρχοντα λογαριασμό `test` που είναι ήδη γεμάτος με δεδομένα.
> Σημείωση: για να κάνετε τη ζωή σας ευκολότερη, μπορείτε να χρησιμοποιήσετε τον προϋπάρχοντα λογαριασμό `test` που είναι ήδη γεμάτος με δεδομένα.
### Εργασία
Ας ξεκινήσουμε αντικαθιστώντας την ενότητα "Υπόλοιπο" στο HTML για να προσθέσουμε στοιχεία κράτησης θέσης:
Ας ξεκινήσουμε αντικαθιστώντας την ενότητα "Balance" στο HTML για να προσθέσουμε στοιχεία κράτησης θέσης:
```html
<section>
@ -208,15 +208,15 @@ if (data.error) {
</section>
```
Θα προσθέσουμε επίσης μια νέα ενότητα ακριβώς από κάτω για να εμφανίσουμε την περιγραφή του λογαριασμού:
Θα προσθέσουμε επίσης μια νέα ενότητα ακριβώς κάτω για να εμφανίσουμε την περιγραφή του λογαριασμού:
```html
<h2 id="description"></h2>
```
✅ Επειδή η περιγραφή του λογαριασμού λειτουργεί ως τίτλος για το περιεχόμενο από κάτω, έχει μορφοποιηθεί σημασιολογικά ως επικεφαλίδα. Μάθετε περισσότερα για το πώς η [δομή επικεφαλίδων](https://www.nomensa.com/blog/2017/how-structure-headings-web-accessibility) είναι σημαντική για την προσβασιμότητα και εξετάστε κριτικά τη σελίδα για να προσδιορίσετε τι άλλο θα μπορούσε να είναι επικεφαλίδα.
✅ Επειδή η περιγραφή του λογαριασμού λειτουργεί ως τίτλος για το περιεχόμενο από κάτω, έχει μορφοποιηθεί σημασιολογικά ως επικεφαλίδα. Μάθετε περισσότερα για το πώς [η δομή των επικεφαλίδων](https://www.nomensa.com/blog/2017/how-structure-headings-web-accessibility) είναι σημαντική για την προσβασιμότητα και εξετάστε κριτικά τη σελίδα για να προσδιορίσετε τι άλλο θα μπορούσε να είναι επικεφαλίδα.
Στη συνέχεια, θα δημιουργήσουμε μια νέα συνάρτηση στο `app.js` για να συμπληρώσουμε τα στοιχεία κράτησης θέσης:
Στη συνέχεια, θα δημιουργήσουμε μια νέα συνάρτηση στο `app.js` για να γεμίσουμε τα στοιχεία κράτησης θέσης:
```js
function updateDashboard() {
@ -230,11 +230,11 @@ function updateDashboard() {
}
```
Αρχικά, ελέγχουμε ότι έχουμε τα δεδομένα λογαριασμού που χρειαζόμαστε πριν προχωρήσουμε. Στη συνέχεια, χρησιμοποιούμε τη συνάρτηση `updateElement()` που δημιουργήσαμε νωρίτερα για να ενημερώσουμε το HTML.
Πρώτα, ελέγχουμε ότι έχουμε τα δεδομένα του λογαριασμού που χρειαζόμαστε πριν προχωρήσουμε. Στη συνέχεια, χρησιμοποιούμε τη συνάρτηση `updateElement()` που δημιουργήσαμε νωρίτερα για να ενημερώσουμε το HTML.
> Για να κάνουμε την εμφάνιση του υπολοίπου πιο όμορφη, χρησιμοποιούμε τη μέθοδο [`toFixed(2)`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) για να εμφανίσουμε την τιμή με 2 δεκαδικά ψηφία.
Τώρα πρέπει να καλέσουμε τη συνάρτηση `updateDashboard()` κάθε φορά που φορτώνεται ο πίνακας ελέγχου. Αν έχετε ήδη ολοκληρώσει την [εργασία του μαθήματος 1](../1-template-route/assignment.md), αυτό θα πρέπει να είναι απλό, διαφορετικά μπορείτε να χρησιμοποιήσετε την παρακάτω υλοποίηση.
Τώρα πρέπει να καλέσουμε τη συνάρτηση `updateDashboard()` κάθε φορά που φορτώνεται η σελίδα του πίνακα ελέγχου. Αν έχετε ήδη ολοκληρώσει την [εργασία του μαθήματος 1](../1-template-route/assignment.md) αυτό θα πρέπει να είναι απλό, διαφορετικά μπορείτε να χρησιμοποιήσετε την παρακάτω υλοποίηση.
Προσθέστε αυτόν τον κώδικα στο τέλος της συνάρτησης `updateRoute()`:
@ -255,28 +255,28 @@ const routes = {
Με αυτήν την αλλαγή, κάθε φορά που εμφανίζεται η σελίδα του πίνακα ελέγχου, καλείται η συνάρτηση `updateDashboard()`. Μετά από μια σύνδεση, θα πρέπει τότε να μπορείτε να δείτε το υπόλοιπο του λογαριασμού, το νόμισμα και την περιγραφή.
## Δημιουργία γραμμών πίνακα
## Δημιουργία γραμμών πίνακα δυναμικά με
Αν προσπαθήσετε να συνδεθείτε χρησιμοποιώντας τον λογαριασμό `test`, θα πρέπει τώρα να δείτε μια λίστα συναλλαγών στον πίνακα ελέγχου 🎉.
---
## 🚀 Πρόκληση
Συνεργαστείτε για να κάνετε τη σελίδα του πίνακα ελέγχου να μοιάζει με μια πραγματική εφαρμογή τραπεζικής. Εάν έχετε ήδη σχεδιάσει την εφαρμογή σας, δοκιμάστε να χρησιμοποιήσετε [media queries](https://developer.mozilla.org/docs/Web/CSS/Media_Queries) για να δημιουργήσετε έναν [responsive σχεδιασμό](https://developer.mozilla.org/docs/Web/Progressive_web_apps/Responsive/responsive_design_building_blocks) που λειτουργεί καλά τόσο σε επιτραπέζιους υπολογιστές όσο και σε κινητές συσκευές.
Συνεργαστείτε για να κάνετε τη σελίδα του πίνακα ελέγχου να μοιάζει με μια πραγματική εφαρμογή τραπεζικής. Αν έχετε ήδη διαμορφώσει την εφαρμογή σας, δοκιμάστε να χρησιμοποιήσετε [media queries](https://developer.mozilla.org/docs/Web/CSS/Media_Queries) για να δημιουργήσετε έναν [responsive σχεδιασμό](https://developer.mozilla.org/docs/Web/Progressive_web_apps/Responsive/responsive_design_building_blocks) που να λειτουργεί καλά τόσο σε επιτραπέζιους υπολογιστές όσο και σε κινητές συσκευές.
Ακολουθεί ένα παράδειγμα μιας σχεδιασμένης σελίδας πίνακα ελέγχου:
Ακολουθεί ένα παράδειγμα μιας διαμορφωμένης σελίδας πίνακα ελέγχου:
![Στιγμιότυπο οθόνης ενός παραδείγματος αποτελέσματος του πίνακα ελέγχου μετά τη σχεδίαση](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.el.png)
![Στιγμιότυπο οθόνης ενός παραδείγματος αποτελέσματος του πίνακα ελέγχου μετά τη διαμόρφωση](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.el.png)
## Κουίζ μετά τη διάλεξη
## Κουίζ μετά το μάθημα
[Κουίζ μετά τη διάλεξη](https://ff-quizzes.netlify.app/web/quiz/46)
[Κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/quiz/46)
## Εργασία
## Ανάθεση
[Αναδιαμορφώστε και σχολιάστε τον κώδικά σας](assignment.md)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "4fa20c513e367e9cdd401bf49ae16e33",
"translation_date": "2025-08-26T23:08:56+00:00",
"original_hash": "5d2efabbc8f94d89f4317ee8646c3ce9",
"translation_date": "2025-08-29T07:02:48+00:00",
"source_file": "7-bank-project/4-state-management/README.md",
"language_code": "el"
}
@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA:
### Εισαγωγή
Καθώς μια διαδικτυακή εφαρμογή μεγαλώνει, γίνεται πρόκληση να παρακολουθείς όλες τις ροές δεδομένων. Ποιος κώδικας λαμβάνει τα δεδομένα, ποια σελίδα τα καταναλώνει, πού και πότε πρέπει να ενημερωθούν... είναι εύκολο να καταλήξεις με ακατάστατο κώδικα που είναι δύσκολο να συντηρηθεί. Αυτό ισχύει ιδιαίτερα όταν χρειάζεται να μοιραστείς δεδομένα μεταξύ διαφορετικών σελίδων της εφαρμογής σου, όπως δεδομένα χρήστη. Η έννοια της *διαχείρισης κατάστασης* υπήρχε πάντα σε κάθε είδους προγράμματα, αλλά καθώς οι διαδικτυακές εφαρμογές συνεχίζουν να αυξάνονται σε πολυπλοκότητα, τώρα είναι ένα βασικό σημείο που πρέπει να σκεφτείς κατά την ανάπτυξη.
Καθώς μια διαδικτυακή εφαρμογή μεγαλώνει, γίνεται πρόκληση να παρακολουθείς όλες τις ροές δεδομένων. Ποιος κώδικας λαμβάνει τα δεδομένα, ποια σελίδα τα χρησιμοποιεί, πού και πότε πρέπει να ενημερωθούν... είναι εύκολο να καταλήξεις με ακατάστατο κώδικα που είναι δύσκολο να συντηρηθεί. Αυτό ισχύει ιδιαίτερα όταν χρειάζεται να μοιραστείς δεδομένα μεταξύ διαφορετικών σελίδων της εφαρμογής σου, όπως τα δεδομένα χρήστη. Η έννοια της *διαχείρισης κατάστασης* υπήρχε πάντα σε κάθε είδους προγράμματα, αλλά καθώς οι διαδικτυακές εφαρμογές γίνονται όλο και πιο περίπλοκες, είναι πλέον ένα βασικό σημείο που πρέπει να λαμβάνεται υπόψη κατά την ανάπτυξη.
Σε αυτό το τελευταίο μέρος, θα εξετάσουμε την εφαρμογή που δημιουργήσαμε για να επανεξετάσουμε πώς διαχειρίζεται η κατάσταση, επιτρέποντας την υποστήριξη ανανέωσης του προγράμματος περιήγησης οποιαδήποτε στιγμή και τη διατήρηση δεδομένων μεταξύ των συνεδριών χρήστη.
### Προαπαιτούμενα
Πρέπει να έχεις ολοκληρώσει το μέρος [ανάκτησης δεδομένων](../3-data/README.md) της διαδικτυακής εφαρμογής για αυτό το μάθημα. Πρέπει επίσης να εγκαταστήσεις το [Node.js](https://nodejs.org) και να [εκτελέσεις το API του διακομιστή](../api/README.md) τοπικά ώστε να μπορείς να διαχειριστείς δεδομένα λογαριασμού.
Πρέπει να έχεις ολοκληρώσει το μέρος [ανάκτησης δεδομένων](../3-data/README.md) της διαδικτυακής εφαρμογής για αυτό το μάθημα. Πρέπει επίσης να εγκαταστήσεις το [Node.js](https://nodejs.org) και να [εκτελέσεις το API του διακομιστή](../api/README.md) τοπικά ώστε να μπορείς να διαχειριστείς τα δεδομένα λογαριασμού.
Μπορείς να δοκιμάσεις ότι ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό:
@ -51,13 +51,13 @@ curl http://localhost:5000/api
- Πώς να διατηρήσουμε τις ροές δεδομένων σε μια εφαρμογή κατανοητές;
- Πώς να διατηρήσουμε τα δεδομένα κατάστασης πάντα συγχρονισμένα με τη διεπαφή χρήστη (και αντίστροφα);
Μόλις φροντίσεις αυτά, οποιαδήποτε άλλα προβλήματα μπορεί να έχεις είτε θα έχουν ήδη λυθεί είτε θα έχουν γίνει ευκολότερα να λυθούν. Υπάρχουν πολλές πιθανές προσεγγίσεις για την επίλυση αυτών των προβλημάτων, αλλά θα ακολουθήσουμε μια κοινή λύση που συνίσταται στο **να κεντροποιήσουμε τα δεδομένα και τους τρόπους αλλαγής τους**. Οι ροές δεδομένων θα λειτουργούν ως εξής:
Μόλις φροντίσεις αυτά τα ζητήματα, οποιαδήποτε άλλα προβλήματα μπορεί να έχεις είτε θα έχουν ήδη λυθεί είτε θα έχουν γίνει ευκολότερα να λυθούν. Υπάρχουν πολλές πιθανές προσεγγίσεις για την επίλυση αυτών των προβλημάτων, αλλά θα ακολουθήσουμε μια κοινή λύση που συνίσταται στο **να κεντροποιήσουμε τα δεδομένα και τους τρόπους αλλαγής τους**. Οι ροές δεδομένων θα λειτουργούν ως εξής:
![Σχήμα που δείχνει τις ροές δεδομένων μεταξύ του HTML, των ενεργειών χρήστη και της κατάστασης](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.el.png)
> Δεν θα καλύψουμε εδώ το μέρος όπου τα δεδομένα ενεργοποιούν αυτόματα την ενημέρωση της προβολής, καθώς αυτό συνδέεται με πιο προχωρημένες έννοιες του [Αντιδραστικού Προγραμματισμού](https://en.wikipedia.org/wiki/Reactive_programming). Είναι ένα καλό θέμα για περαιτέρω εμβάθυνση αν είσαι έτοιμος για μια βαθύτερη μελέτη.
> Δεν θα καλύψουμε εδώ το μέρος όπου τα δεδομένα ενεργοποιούν αυτόματα την ενημέρωση της προβολής, καθώς αυτό συνδέεται με πιο προχωρημένες έννοιες του [Αντιδραστικού Προγραμματισμού](https://en.wikipedia.org/wiki/Reactive_programming). Είναι ένα καλό θέμα για περαιτέρω εμβάθυνση αν ενδιαφέρεσαι.
✅ Υπάρχουν πολλές βιβλιοθήκες εκεί έξω με διαφορετικές προσεγγίσεις στη διαχείριση κατάστασης, με το [Redux](https://redux.js.org) να είναι μια δημοφιλής επιλογή. Ρίξε μια ματιά στις έννοιες και τα πρότυπα που χρησιμοποιούνται, καθώς συχνά είναι ένας καλός τρόπος να μάθεις ποια πιθανά προβλήματα μπορεί να αντιμετωπίσεις σε μεγάλες διαδικτυακές εφαρμογές και πώς μπορούν να λυθούν.
✅ Υπάρχουν πολλές βιβλιοθήκες εκεί έξω με διαφορετικές προσεγγίσεις στη διαχείριση κατάστασης, με το [Redux](https://redux.js.org) να είναι μια δημοφιλής επιλογή. Ρίξε μια ματιά στις έννοιες και τα μοτίβα που χρησιμοποιούνται, καθώς συχνά είναι ένας καλός τρόπος να μάθεις ποια πιθανά προβλήματα μπορεί να αντιμετωπίσεις σε μεγάλες διαδικτυακές εφαρμογές και πώς μπορούν να λυθούν.
### Εργασία
@ -89,9 +89,9 @@ const account = state.account;
## Παρακολούθηση αλλαγών δεδομένων
Τώρα που έχουμε θέσει το αντικείμενο `state` για την αποθήκευση των δεδομένων μας, το επόμενο βήμα είναι να κεντροποιήσουμε τις ενημερώσεις. Στόχος είναι να γίνει ευκολότερη η παρακολούθηση οποιωνδήποτε αλλαγών και πότε συμβαίνουν.
Τώρα που έχουμε θέσει το αντικείμενο `state` για την αποθήκευση των δεδομένων μας, το επόμενο βήμα είναι να κεντροποιήσουμε τις ενημερώσεις. Στόχος είναι να γίνει ευκολότερο να παρακολουθούμε οποιεσδήποτε αλλαγές και πότε συμβαίνουν.
Για να αποφύγουμε την πραγματοποίηση αλλαγών στο αντικείμενο `state`, είναι επίσης καλή πρακτική να το θεωρούμε [*αμετάβλητο*](https://en.wikipedia.org/wiki/Immutable_object), που σημαίνει ότι δεν μπορεί να τροποποιηθεί καθόλου. Αυτό σημαίνει επίσης ότι πρέπει να δημιουργήσεις ένα νέο αντικείμενο κατάστασης αν θέλεις να αλλάξεις κάτι σε αυτό. Με αυτόν τον τρόπο, δημιουργείς προστασία από πιθανές ανεπιθύμητες [παρενέργειες](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) και ανοίγεις δυνατότητες για νέες λειτουργίες στην εφαρμογή σου, όπως η υλοποίηση αναίρεσης/επανάληψης, ενώ ταυτόχρονα διευκολύνεις την αποσφαλμάτωση. Για παράδειγμα, θα μπορούσες να καταγράψεις κάθε αλλαγή που γίνεται στην κατάσταση και να διατηρήσεις ένα ιστορικό των αλλαγών για να κατανοήσεις την πηγή ενός σφάλματος.
Για να αποφύγουμε την πραγματοποίηση αλλαγών στο αντικείμενο `state`, είναι επίσης καλή πρακτική να το θεωρούμε [*αμετάβλητο*](https://en.wikipedia.org/wiki/Immutable_object), που σημαίνει ότι δεν μπορεί να τροποποιηθεί καθόλου. Αυτό σημαίνει επίσης ότι πρέπει να δημιουργήσεις ένα νέο αντικείμενο κατάστασης αν θέλεις να αλλάξεις κάτι σε αυτό. Με αυτόν τον τρόπο, δημιουργείς προστασία από πιθανές ανεπιθύμητες [παρενέργειες](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) και ανοίγεις δυνατότητες για νέες λειτουργίες στην εφαρμογή σου, όπως η υλοποίηση undo/redo, ενώ ταυτόχρονα διευκολύνεις την αποσφαλμάτωση. Για παράδειγμα, θα μπορούσες να καταγράψεις κάθε αλλαγή που γίνεται στην κατάσταση και να διατηρήσεις ένα ιστορικό των αλλαγών για να κατανοήσεις την πηγή ενός σφάλματος.
Στην JavaScript, μπορείς να χρησιμοποιήσεις το [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) για να δημιουργήσεις μια αμετάβλητη έκδοση ενός αντικειμένου. Αν προσπαθήσεις να κάνεις αλλαγές σε ένα αμετάβλητο αντικείμενο, θα προκληθεί εξαίρεση.
@ -110,7 +110,7 @@ function updateState(property, newData) {
}
```
Σε αυτή τη συνάρτηση, δημιουργούμε ένα νέο αντικείμενο κατάστασης και αντιγράφουμε δεδομένα από την προηγούμενη κατάσταση χρησιμοποιώντας τον [*τελεστή διάδοσης (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Στη συνέχεια, αντικαθιστούμε μια συγκεκριμένη ιδιότητα του αντικειμένου κατάστασης με τα νέα δεδομένα χρησιμοποιώντας τη [σημειογραφία αγκύλης](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` για την ανάθεση. Τέλος, κλειδώνουμε το αντικείμενο για να αποτρέψουμε τροποποιήσεις χρησιμοποιώντας το `Object.freeze()`. Προς το παρόν, έχουμε μόνο την ιδιότητα `account` αποθηκευμένη στην κατάσταση, αλλά με αυτήν την προσέγγιση μπορείς να προσθέσεις όσες ιδιότητες χρειάζεσαι στην κατάσταση.
Σε αυτή τη συνάρτηση, δημιουργούμε ένα νέο αντικείμενο κατάστασης και αντιγράφουμε δεδομένα από την προηγούμενη κατάσταση χρησιμοποιώντας τον [*τελεστή spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Στη συνέχεια, αντικαθιστούμε μια συγκεκριμένη ιδιότητα του αντικειμένου κατάστασης με τα νέα δεδομένα χρησιμοποιώντας τη [σημειογραφία αγκύλης](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` για την ανάθεση. Τέλος, κλειδώνουμε το αντικείμενο για να αποτρέψουμε τροποποιήσεις χρησιμοποιώντας το `Object.freeze()`. Προς το παρόν, έχουμε μόνο την ιδιότητα `account` αποθηκευμένη στην κατάσταση, αλλά με αυτήν την προσέγγιση μπορείς να προσθέσεις όσες ιδιότητες χρειάζεσαι στην κατάσταση.
Θα ενημερώσουμε επίσης την αρχικοποίηση της `state` για να βεβαιωθούμε ότι η αρχική κατάσταση είναι επίσης κλειδωμένη:
@ -153,9 +153,9 @@ function logout() {
Οι περισσότερες διαδικτυακές εφαρμογές χρειάζονται να διατηρούν δεδομένα για να λειτουργούν σωστά. Όλα τα κρίσιμα δεδομένα συνήθως αποθηκεύονται σε μια βάση δεδομένων και προσπελάζονται μέσω ενός API διακομιστή, όπως τα δεδομένα λογαριασμού χρήστη στην περίπτωσή μας. Αλλά μερικές φορές, είναι επίσης ενδιαφέρον να διατηρείς κάποια δεδομένα στην εφαρμογή πελάτη που εκτελείται στο πρόγραμμα περιήγησης, για καλύτερη εμπειρία χρήστη ή για βελτίωση της απόδοσης φόρτωσης.
Όταν θέλεις να διατηρήσεις δεδομένα στο πρόγραμμα περιήγησης, υπάρχουν μερικές σημαντικές ερωτήσεις που πρέπει να κάνεις στον εαυτό σου:
Όταν θέλεις να διατηρήσεις δεδομένα στο πρόγραμμα περιήγησης, υπάρχουν μερικές σημαντικές ερωτήσεις που πρέπει να κάνεις:
- *Είναι τα δεδομένα ευαίσθητα;* Πρέπει να αποφεύγεις την αποθήκευση οποιωνδήποτε ευαίσθητων δεδομένων στον πελάτη, όπως κωδικούς πρόσβασης χρηστών.
- *Είναι τα δεδομένα ευαίσθητα;* Θα πρέπει να αποφεύγεις την αποθήκευση οποιωνδήποτε ευαίσθητων δεδομένων στον πελάτη, όπως κωδικούς πρόσβασης χρηστών.
- *Για πόσο καιρό χρειάζεσαι να διατηρήσεις αυτά τα δεδομένα;* Σκοπεύεις να προσπελάσεις αυτά τα δεδομένα μόνο για την τρέχουσα συνεδρία ή θέλεις να αποθηκευτούν για πάντα;
Υπάρχουν πολλοί τρόποι αποθήκευσης πληροφοριών μέσα σε μια διαδικτυακή εφαρμογή, ανάλογα με το τι θέλεις να επιτύχεις. Για παράδειγμα, μπορείς να χρησιμοποιήσεις τις διευθύνσεις URL για να αποθηκεύσεις ένα ερώτημα αναζήτησης και να το κάνεις κοινόχρηστο μεταξύ χρηστών. Μπορείς επίσης να χρησιμοποιήσεις [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) αν τα δεδομένα χρειάζεται να μοιραστούν με τον διακομιστή, όπως πληροφορίες [αυθεντικοποίησης](https://en.wikipedia.org/wiki/Authentication).
@ -167,11 +167,11 @@ function logout() {
Σημείωσε ότι και οι δύο αυτές APIs επιτρέπουν μόνο την αποθήκευση [συμβολοσειρών](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Αν θέλεις να αποθηκεύσεις σύνθετα αντικείμενα, θα χρειαστεί να τα σειριοποιήσεις στη μορφή [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) χρησιμοποιώντας το [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
Αν θέλεις να δημιουργήσεις μια διαδικτυακή εφαρμογή που δεν λειτουργεί με διακομιστή, είναι επίσης δυνατό να δημιουργήσεις μια βάση δεδομένων στον πελάτη χρησιμοποιώντας το API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Αυτό προορίζεται για προχωρημένες περιπτώσεις χρήσης ή αν χρειάζεσαι να αποθηκεύσεις σημαντική ποσότητα δεδομένων, καθώς είναι πιο περίπλοκο στη χρήση.
Αν θέλεις να δημιουργήσεις μια διαδικτυακή εφαρμογή που δεν λειτουργεί με διακομιστή, είναι επίσης δυνατό να δημιουργήσεις μια βάση δεδομένων στον πελάτη χρησιμοποιώντας το [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Αυτό προορίζεται για προχωρημένες περιπτώσεις χρήσης ή αν χρειάζεσαι να αποθηκεύσεις σημαντική ποσότητα δεδομένων, καθώς είναι πιο περίπλοκο στη χρήση.
### Εργασία
Θέλουμε οι χρήστες μας να παραμένουν συνδεδεμένοι μέχρι να κάνουν ρητά κλικ στο κουμπί *Αποσύνδεση*, οπότε θα χρησιμοποιήσουμε το `localStorage` για να αποθηκεύσουμε τα δεδομένα του λογαριασμού. Πρώτα, ας ορίσουμε ένα κλειδί που θα χρησιμοποιήσουμε για την αποθήκευση των δεδομένων μας.
Θέλουμε οι χρήστες μας να παραμένουν συνδεδεμένοι μέχρι να κάνουν ρητά κλικ στο κουμπί *Αποσύνδεση*, οπότε θα χρησιμοποιήσουμε το `localStorage` για να αποθηκεύσουμε τα δεδομένα λογαριασμού. Πρώτα, ας ορίσουμε ένα κλειδί που θα χρησιμοποιήσουμε για την αποθήκευση των δεδομένων μας.
```js
const storageKey = 'savedAccount';
@ -183,9 +183,9 @@ const storageKey = 'savedAccount';
localStorage.setItem(storageKey, JSON.stringify(state.account));
```
Με αυτό, τα δεδομένα του λογαριασμού χρήστη θα διατηρούνται και θα είναι πάντα ενημερωμένα καθώς κεντροποιήσαμε προηγουμένως όλες τις ενημερώσεις κατάστασης. Εδώ αρχίζουμε να επωφελούμαστε από όλες τις προηγούμενες αναδιαρθρώσεις μας 🙂.
Με αυτό, τα δεδομένα λογαριασμού χρήστη θα διατηρούνται και θα είναι πάντα ενημερωμένα καθώς κεντροποιήσαμε προηγουμένως όλες τις ενημερώσεις κατάστασης. Εδώ αρχίζουμε να επωφελούμαστε από όλες τις προηγούμενες αναδιαρθρώσεις μας 🙂.
Καθώς τα δεδομένα αποθηκεύονται, πρέπει επίσης να φροντίσουμε να τα επαναφέρουμε όταν φορτώνεται η εφαρμογή. Επειδή αρχίζουμε να έχουμε περισσότερο κώδικα αρχικοποίησης, μπορεί να είναι καλή ιδέα να δημιουργήσουμε μια νέα συνάρτηση `init`, που περιλαμβάνει επίσης τον προηγούμενο κώδικα στο κάτω μέρος του `app.js`:
Καθώς τα δεδομένα αποθηκεύονται, πρέπει επίσης να φροντίσουμε να τα επαναφέρουμε όταν φορτώνεται η εφαρμογή. Επειδή θα αρχίσουμε να έχουμε περισσότερο κώδικα αρχικοποίησης, μπορεί να είναι καλή ιδέα να δημιουργήσουμε μια νέα συνάρτηση `init`, που περιλαμβάνει επίσης τον προηγούμενο κώδικα στο κάτω μέρος του `app.js`:
```js
function init() {
@ -204,18 +204,14 @@ init();
Εδώ ανακτούμε τα αποθηκευμένα δεδομένα και, αν υπάρχουν, ενημερώνουμε την κατάσταση ανάλογα. Είναι σημαντικό να το κάνουμε *πριν* ενημερώσουμε τη διαδρομή, καθώς μπορεί να υπάρχει κώδικας που βασίζεται στην κατάσταση κατά την ενημέρωση της σελίδας.
Μπορούμε επίσης να κάνουμε τη σελίδα *Πίνακας Ελέγχου* την προεπιλεγμένη σελίδα της εφαρμογής μας, καθώς τώρα διατηρούμε τα δεδομένα του λογαριασμού. Αν δεν βρεθούν δεδομένα, ο πίνακας ελέγχου φροντίζει να ανακατευθύνει στη σελίδα *Σύνδεση* ούτως ή άλλως
[Κουίζ μετά τη διάλεξη](https://ff-quizzes.netlify.app/web/quiz/48)
## Εργασία
[Υλοποιήστε το διάλογο "Προσθήκη συναλλαγής"](assignment.md)
Μπορούμε επίσης να κάνουμε τη σελίδα *Πίνακας Ελέγχου* την προεπιλεγμένη σελίδα της εφαρμογής μας, καθώς τώρα διατηρούμε τα δεδομένα λογαριασμού. Αν δεν βρεθούν δεδομένα, ο πίνακας ελέγχου φροντίζει να ανακατευθύνει στη σελίδα *Σύνδεση* ούτως ή άλλως. Στην `updateRoute()`, αντικατάστησε την εναλλακτική `return navigate('/login');` με `return navigate('/dashboard
[Υλοποίηση του διαλόγου "Προσθήκη συναλλαγής"](assignment.md)
Ακολουθεί ένα παράδειγμα αποτελέσματος μετά την ολοκλήρωση της εργασίας:
![Στιγμιότυπο οθόνης που δείχνει ένα παράδειγμα διαλόγου "Προσθήκη συναλλαγής"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.el.png)
![Στιγμιότυπο που δείχνει ένα παράδειγμα διαλόγου "Προσθήκη συναλλαγής"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.el.png)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε κάθε προσπάθεια για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "7aa6e4f270d38d9cb17f2b5bd86b863d",
"translation_date": "2025-08-26T22:25:47+00:00",
"original_hash": "1ba61d96a11309a2a6ea507496dcf7e5",
"translation_date": "2025-08-29T07:17:30+00:00",
"source_file": "8-code-editor/1-using-a-code-editor/README.md",
"language_code": "el"
}
@ -29,19 +29,19 @@ CO_OP_TRANSLATOR_METADATA:
## Ξεκινώντας με το VSCode.dev
Το [VSCode.dev](https://vscode.dev) είναι ένας επεξεργαστής κώδικα στον ιστό. Δεν χρειάζεται να εγκαταστήσετε τίποτα για να το χρησιμοποιήσετε, όπως ακριβώς ανοίγετε οποιονδήποτε άλλο ιστότοπο. Για να ξεκινήσετε με τον επεξεργαστή, ανοίξτε τον παρακάτω σύνδεσμο: [https://vscode.dev](https://vscode.dev). Αν δεν είστε συνδεδεμένοι στο [GitHub](https://github.com/), ακολουθήστε τις οδηγίες για να συνδεθείτε ή να δημιουργήσετε έναν νέο λογαριασμό και στη συνέχεια να συνδεθείτε.
Το [VSCode.dev](https://vscode.dev) είναι ένας επεξεργαστής κώδικα στον ιστό. Δεν χρειάζεται να εγκαταστήσετε τίποτα για να το χρησιμοποιήσετε, όπως ακριβώς ανοίγετε οποιονδήποτε άλλο ιστότοπο. Για να ξεκινήσετε με τον επεξεργαστή, ανοίξτε τον παρακάτω σύνδεσμο: [https://vscode.dev](https://vscode.dev). Αν δεν έχετε συνδεθεί στο [GitHub](https://github.com/), ακολουθήστε τις οδηγίες για να συνδεθείτε ή να δημιουργήσετε έναν νέο λογαριασμό και στη συνέχεια συνδεθείτε.
Μόλις φορτώσει, θα πρέπει να μοιάζει με την παρακάτω εικόνα:
![Προεπιλεγμένο VSCode.dev](../../../../translated_images/default-vscode-dev.5d06881d65c1b3234ce50cd9ed3b0028e6031ad5f5b441bcbed96bfa6311f6d0.el.png)
Υπάρχουν τρία κύρια τμήματα, ξεκινώντας από τα αριστερά και προχωρώντας προς τα δεξιά:
Υπάρχουν τρεις κύριες ενότητες, ξεκινώντας από τα αριστερά και προχωρώντας προς τα δεξιά:
1. Η _γραμμή δραστηριοτήτων_ που περιλαμβάνει μερικά εικονίδια, όπως ο μεγεθυντικός φακός 🔎, το γρανάζι ⚙️, και μερικά άλλα.
2. Η επεκταμένη γραμμή δραστηριοτήτων που από προεπιλογή είναι ο _Εξερευνητής_, ονομάζεται _πλευρική γραμμή_.
1. Η _γραμμή δραστηριοτήτων_ που περιλαμβάνει μερικά εικονίδια, όπως ο μεγεθυντικός φακός 🔎, το γρανάζι ⚙️ και μερικά άλλα.
2. Η επεκταμένη γραμμή δραστηριοτήτων που από προεπιλογή εμφανίζει τον _Εξερευνητή_, που ονομάζεται _πλευρική γραμμή_.
3. Και τέλος, η περιοχή κώδικα στα δεξιά.
Κάντε κλικ σε κάθε ένα από τα εικονίδια για να εμφανίσετε ένα διαφορετικό μενού. Μόλις τελειώσετε, κάντε κλικ στον _Εξερευνητή_ για να επιστρέψετε εκεί που ξεκινήσατε.
Κάντε κλικ σε κάθε ένα από τα εικονίδια για να εμφανίσετε διαφορετικά μενού. Όταν τελειώσετε, κάντε κλικ στον _Εξερευνητή_ για να επιστρέψετε εκεί που ξεκινήσατε.
Όταν αρχίσετε να δημιουργείτε ή να τροποποιείτε κώδικα, αυτό θα συμβεί στη μεγαλύτερη περιοχή στα δεξιά. Θα χρησιμοποιήσετε αυτήν την περιοχή για να δείτε και τον υπάρχοντα κώδικα, κάτι που θα κάνετε στη συνέχεια.
@ -55,7 +55,7 @@ CO_OP_TRANSLATOR_METADATA:
![Άνοιγμα απομακρυσμένου αποθετηρίου](../../../../translated_images/open-remote-repository.bd9c2598b8949e7fc283cdfc8f4050c6205a7c7c6d3f78c4b135115d037d6fa2.el.png)
Μπορείτε επίσης να χρησιμοποιήσετε την παλέτα εντολών. Η παλέτα εντολών είναι ένα πλαίσιο εισαγωγής όπου μπορείτε να πληκτρολογήσετε οποιαδήποτε λέξη που αποτελεί μέρος μιας εντολής ή μιας ενέργειας για να βρείτε τη σωστή εντολή για εκτέλεση. Χρησιμοποιήστε το μενού στην επάνω αριστερή γωνία, επιλέξτε _View_ και στη συνέχεια επιλέξτε _Command Palette_, ή χρησιμοποιήστε τη συντόμευση πληκτρολογίου: Ctrl-Shift-P (σε MacOS θα ήταν Command-Shift-P).
Μπορείτε επίσης να χρησιμοποιήσετε την παλέτα εντολών. Η παλέτα εντολών είναι ένα πλαίσιο εισαγωγής όπου μπορείτε να πληκτρολογήσετε οποιαδήποτε λέξη που αποτελεί μέρος μιας εντολής ή μιας ενέργειας για να βρείτε τη σωστή εντολή προς εκτέλεση. Χρησιμοποιήστε το μενού επάνω αριστερά, επιλέξτε _View_ και στη συνέχεια επιλέξτε _Command Palette_, ή χρησιμοποιήστε τη συντόμευση πληκτρολογίου: Ctrl-Shift-P (σε MacOS είναι Command-Shift-P).
![Μενού Παλέτας](../../../../translated_images/palette-menu.4946174e07f426226afcdad707d19b8d5150e41591c751c45b5dee213affef91.el.png)
@ -65,15 +65,15 @@ CO_OP_TRANSLATOR_METADATA:
https://github.com/microsoft/Web-Dev-For-Beginners
```
Αν είναι επιτυχές, θα δείτε όλα τα αρχεία αυτού του αποθετηρίου να φορτώνονται στον επεξεργαστή κειμένου.
Αν η διαδικασία είναι επιτυχής, θα δείτε όλα τα αρχεία αυτού του αποθετηρίου να φορτώνονται στον επεξεργαστή κειμένου.
### 2. Χρησιμοποιώντας το URL
Μπορείτε επίσης να χρησιμοποιήσετε ένα URL απευθείας για να φορτώσετε ένα αποθετήριο. Για παράδειγμα, το πλήρες URL για το τρέχον αποθετήριο είναι [https://github.com/microsoft/Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners), αλλά μπορείτε να αντικαταστήσετε τον τομέα του GitHub με `VSCode.dev/github` και να φορτώσετε το αποθετήριο απευθείας. Το προκύπτον URL θα ήταν [https://vscode.dev/github/microsoft/Web-Dev-For-Beginners](https://vscode.dev/github/microsoft/Web-Dev-For-Beginners).
Μπορείτε επίσης να χρησιμοποιήσετε ένα URL απευθείας για να φορτώσετε ένα αποθετήριο. Για παράδειγμα, το πλήρες URL για το τρέχον αποθετήριο είναι [https://github.com/microsoft/Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners), αλλά μπορείτε να αντικαταστήσετε τον τομέα GitHub με `VSCode.dev/github` και να φορτώσετε το αποθετήριο απευθείας. Το προκύπτον URL θα είναι [https://vscode.dev/github/microsoft/Web-Dev-For-Beginners](https://vscode.dev/github/microsoft/Web-Dev-For-Beginners).
## Επεξεργασία αρχείων
Μόλις ανοίξετε το αποθετήριο στον περιηγητή/vscode.dev, το επόμενο βήμα είναι να κάνετε ενημερώσεις ή αλλαγές στο έργο.
Αφού ανοίξετε το αποθετήριο στον περιηγητή/ vscode.dev, το επόμενο βήμα είναι να κάνετε ενημερώσεις ή αλλαγές στο έργο.
### 1. Δημιουργία νέου αρχείου
@ -91,26 +91,26 @@ https://github.com/microsoft/Web-Dev-For-Beginners
Μόλις ολοκληρώσετε την ενημέρωση του έργου σας, επιλέξτε το εικονίδιο _`source control`_ που περιέχει όλες τις νέες αλλαγές που έχετε κάνει στο αποθετήριο.
Για να δείτε τις αλλαγές που κάνατε στο έργο σας, επιλέξτε το(τα) αρχείο(α) στον φάκελο `Changes` στην επεκταμένη γραμμή δραστηριοτήτων. Αυτό θα ανοίξει ένα 'Working Tree' για να δείτε οπτικά τις αλλαγές που κάνατε στο αρχείο. Το κόκκινο δείχνει μια αφαίρεση από το έργο, ενώ το πράσινο υποδηλώνει μια προσθήκη.
Για να δείτε τις αλλαγές που κάνατε στο έργο σας, επιλέξτε το(α) αρχείο(α) στον φάκελο `Changes` στην επεκταμένη γραμμή δραστηριοτήτων. Αυτό θα ανοίξει ένα 'Working Tree' για να δείτε οπτικά τις αλλαγές που κάνατε στο αρχείο. Το κόκκινο δείχνει μια αφαίρεση από το έργο, ενώ το πράσινο υποδηλώνει μια προσθήκη.
![Προβολή αλλαγών](../../../../translated_images/working-tree.c58eec08e6335c79cc708c0c220c0b7fea61514bd3c7fb7471905a864aceac7c.el.png)
Αν είστε ικανοποιημένοι με τις αλλαγές που κάνατε, περάστε τον δείκτη πάνω από τον φάκελο `Changes` και κάντε κλικ στο κουμπί `+` για να προετοιμάσετε τις αλλαγές. Η προετοιμασία σημαίνει απλώς την προετοιμασία των αλλαγών σας για να τις δεσμεύσετε στο GitHub.
Αν είστε ικανοποιημένοι με τις αλλαγές που κάνατε, τοποθετήστε τον δείκτη του ποντικιού πάνω από τον φάκελο `Changes` και κάντε κλικ στο κουμπί `+` για να προετοιμάσετε τις αλλαγές. Η προετοιμασία σημαίνει απλώς την προετοιμασία των αλλαγών σας για να τις δεσμεύσετε στο GitHub.
Αν, ωστόσο, δεν είστε άνετοι με κάποιες αλλαγές και θέλετε να τις απορρίψετε, περάστε τον δείκτη πάνω από τον φάκελο `Changes` και επιλέξτε το εικονίδιο `undo`.
Αν, ωστόσο, δεν είστε άνετοι με κάποιες αλλαγές και θέλετε να τις απορρίψετε, τοποθετήστε τον δείκτη του ποντικιού πάνω από τον φάκελο `Changes` και επιλέξτε το εικονίδιο `undo`.
Στη συνέχεια, πληκτρολογήστε ένα `commit message` _(Μια περιγραφή της αλλαγής που κάνατε στο έργο)_, κάντε κλικ στο εικονίδιο `check` για να δεσμεύσετε και να προωθήσετε τις αλλαγές σας.
Μόλις τελειώσετε με το έργο σας, επιλέξτε το εικονίδιο `hamburger menu` στην επάνω αριστερή γωνία για να επιστρέψετε στο αποθετήριο στο github.com.
Μόλις τελειώσετε με το έργο σας, επιλέξτε το εικονίδιο `hamburger menu` επάνω αριστερά για να επιστρέψετε στο αποθετήριο στο github.com.
![Προετοιμασία & δέσμευση αλλαγών](../../../../8-code-editor/images/edit-vscode.dev.gif)
## Χρήση επεκτάσεων
Η εγκατάσταση επεκτάσεων στο VSCode σας επιτρέπει να προσθέσετε νέες δυνατότητες και επιλογές προσαρμογής στο περιβάλλον ανάπτυξης του επεξεργαστή σας για να βελτιώσετε τη ροή εργασίας σας. Αυτές οι επεκτάσεις βοηθούν επίσης στην προσθήκη υποστήριξης για πολλές γλώσσες προγραμματισμού και είναι συχνά είτε γενικές επεκτάσεις είτε επεκτάσεις βασισμένες σε γλώσσες.
Η εγκατάσταση επεκτάσεων στο VSCode σας επιτρέπει να προσθέσετε νέες δυνατότητες και επιλογές προσαρμογής του περιβάλλοντος ανάπτυξης στον επεξεργαστή σας, βελτιώνοντας τη ροή εργασίας ανάπτυξης. Αυτές οι επεκτάσεις βοηθούν επίσης στην προσθήκη υποστήριξης για πολλές γλώσσες προγραμματισμού και είναι συχνά είτε γενικές επεκτάσεις είτε επεκτάσεις βασισμένες σε γλώσσες.
Για να περιηγηθείτε στη λίστα όλων των διαθέσιμων επεκτάσεων, κάντε κλικ στο εικονίδιο _`Extensions`_ στη γραμμή δραστηριοτήτων και αρχίστε να πληκτρολογείτε το όνομα της επέκτασης στο πεδίο κειμένου με την ετικέτα _'Search Extensions in Marketplace'_.
Θα δείτε μια λίστα επεκτάσεων, καθεμία από τις οποίες περιέχει **το όνομα της επέκτασης, το όνομα του εκδότη, μια περιγραφή μίας πρότασης, τον αριθμό λήψεων** και **μια βαθμολογία με αστέρια**.
Για να περιηγηθείτε στη λίστα όλων των διαθέσιμων επεκτάσεων, κάντε κλικ στο εικονίδιο _`Extensions`_ στη γραμμή δραστηριοτήτων και αρχίστε να πληκτρολογείτε το όνομα της επέκτασης στο πεδίο κειμένου με την ένδειξη _'Search Extensions in Marketplace'_.
Θα δείτε μια λίστα επεκτάσεων, καθεμία από τις οποίες περιέχει **το όνομα της επέκτασης, το όνομα του εκδότη, μια περιγραφή μιας πρότασης, τον αριθμό λήψεων** και **μια βαθμολογία με αστέρια**.
![Λεπτομέρειες επέκτασης](../../../../translated_images/extension-details.9f8f1fd4e9eb2de5069ae413119eb8ee43172776383ebe2f7cf640e11df2e106.el.png)
@ -118,29 +118,29 @@ https://github.com/microsoft/Web-Dev-For-Beginners
![Προβολή επεκτάσεων](../../../../translated_images/extensions.eca0e0c7f59a10b5c88be7fe24b3e32cca6b6058b35a49026c3a9d80b1813b7c.el.png)
### 1. Εγκατάσταση Επεκτάσεων
### 1. Εγκατάσταση επεκτάσεων
Για να εγκαταστήσετε μια επέκταση, πληκτρολογήστε το όνομα της επέκτασης στο πεδίο αναζήτησης και κάντε κλικ σε αυτήν για να δείτε πρόσθετες πληροφορίες σχετικά με την επέκταση στην περιοχή κώδικα μόλις εμφανιστεί στη διευρυμένη γραμμή δραστηριοτήτων.
Για να εγκαταστήσετε μια επέκταση, πληκτρολογήστε το όνομα της επέκτασης στο πεδίο αναζήτησης και κάντε κλικ πάνω της για να δείτε πρόσθετες πληροφορίες σχετικά με την επέκταση στην περιοχή κώδικα μόλις εμφανιστεί στην επεκταμένη γραμμή δραστηριοτήτων.
Μπορείτε είτε να κάνετε κλικ στο _μπλε κουμπί εγκατάστασης_ στη διευρυμένη γραμμή δραστηριοτήτων για να την εγκαταστήσετε είτε να χρησιμοποιήσετε το κουμπί εγκατάστασης που εμφανίζεται στην περιοχή κώδικα μόλις επιλέξετε την επέκταση για να φορτώσετε πρόσθετες πληροφορίες.
Μπορείτε είτε να κάνετε κλικ στο _μπλε κουμπί εγκατάστασης_ στην επεκταμένη γραμμή δραστηριοτήτων για να την εγκαταστήσετε είτε να χρησιμοποιήσετε το κουμπί εγκατάστασης που εμφανίζεται στην περιοχή κώδικα μόλις επιλέξετε την επέκταση για να φορτώσετε πρόσθετες πληροφορίες.
![Εγκατάσταση επεκτάσεων](../../../../8-code-editor/images/install-extension.gif)
### 2. Προσαρμογή Επεκτάσεων
### 2. Προσαρμογή επεκτάσεων
Μετά την εγκατάσταση της επέκτασης, ίσως χρειαστεί να τροποποιήσετε τη συμπεριφορά της και να την προσαρμόσετε με βάση τις προτιμήσεις σας. Για να το κάνετε αυτό, επιλέξτε το εικονίδιο Επεκτάσεων και αυτή τη φορά, η επέκταση σας θα εμφανιστεί στον φάκελο _Installed_, κάντε κλικ στο _**Gear icon**_ και μεταβείτε στις _Extensions Setting_.
Μετά την εγκατάσταση της επέκτασης, ίσως χρειαστεί να τροποποιήσετε τη συμπεριφορά της και να την προσαρμόσετε με βάση τις προτιμήσεις σας. Για να το κάνετε αυτό, επιλέξτε το εικονίδιο Extensions και αυτή τη φορά η επέκταση σας θα εμφανιστεί στον φάκελο _Installed_, κάντε κλικ στο _**Gear icon**_ και μεταβείτε στις _Extensions Setting_.
![Τροποποίηση ρυθμίσεων επέκτασης](../../../../translated_images/extension-settings.21c752ae4f4cdb78a867f140ccd0680e04619d0c44bb4afb26373e54b829d934.el.png)
### 3. Διαχείριση Επεκτάσεων
### 3. Διαχείριση επεκτάσεων
Μετά την εγκατάσταση και χρήση της επέκτασης, το vscode.dev προσφέρει επιλογές για τη διαχείριση της επέκτασης με βάση διαφορετικές ανάγκες. Για παράδειγμα, μπορείτε να επιλέξετε να:
- **Απενεργοποιήσετε:** _(Μπορείτε προσωρινά να απενεργοποιήσετε μια επέκταση όταν δεν τη χρειάζεστε πλέον αλλά δεν θέλετε να την απεγκαταστήσετε εντελώς)_
Επιλέξτε την εγκατεστημένη επέκταση στη διευρυμένη γραμμή δραστηριοτήτων > κάντε κλικ στο Gear icon > επιλέξτε 'Disable' ή 'Disable (Workspace)' **Ή** Ανοίξτε την επέκταση στην περιοχή κώδικα και κάντε κλικ στο μπλε κουμπί Disable.
Επιλέξτε την εγκατεστημένη επέκταση στην επεκταμένη γραμμή δραστηριοτήτων > κάντε κλικ στο Gear icon > επιλέξτε 'Disable' ή 'Disable (Workspace)' **Ή** Ανοίξτε την επέκταση στην περιοχή κώδικα και κάντε κλικ στο μπλε κουμπί Disable.
- **Απεγκαταστήσετε:** Επιλέξτε την εγκατεστημένη επέκταση στη διευρυμένη γραμμή δραστηριοτήτων > κάντε κλικ στο Gear icon > επιλέξτε 'Uninstall' **Ή** Ανοίξτε την επέκταση στην περιοχή κώδικα και κάντε κλικ στο μπλε κουμπί Uninstall.
- **Απεγκαταστήσετε:** Επιλέξτε την εγκατεστημένη επέκταση στην επεκταμένη γραμμή δραστηριοτήτων > κάντε κλικ στο Gear icon > επιλέξτε 'Uninstall' **Ή** Ανοίξτε την επέκταση στην περιοχή κώδικα και κάντε κλικ στο μπλε κουμπί Uninstall.
---
@ -154,5 +154,5 @@ https://github.com/microsoft/Web-Dev-For-Beginners
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,19 +1,25 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2fcb983b8dbadadb1bc2e97f8c12dac5",
"translation_date": "2025-08-26T22:28:20+00:00",
"original_hash": "bd3aa6d2b879c30ea496c43aec1c49ed",
"translation_date": "2025-08-29T07:18:16+00:00",
"source_file": "8-code-editor/1-using-a-code-editor/assignment.md",
"language_code": "el"
}
-->
# Δημιουργία ιστοσελίδας βιογραφικού χρησιμοποιώντας το vscode.dev
_Πόσο ωραίο θα ήταν να ζητήσει ένας υπεύθυνος προσλήψεων το βιογραφικό σας και να του στείλετε ένα url;_ 😎
_Πόσο ωραίο θα ήταν να ζητήσει ένας υπεύθυνος προσλήψεων το βιογραφικό σας και να του στείλετε έναν σύνδεσμο;_ 😎
<!----
TODO: προσθέστε μια προαιρετική εικόνα
![Χρήση ενός code editor](../../../../translated_images/webdev101-vscode-dev.f53c14e8dad231ea09d9e07a2db4a01551d2dc6cdf21225038389e11156af023.el.png)
> Σκίτσο από τον [Όνομα Συγγραφέα](https://example.com)
---->
## Στόχοι
Μετά από αυτή την εργασία, θα μάθετε πώς να:
Μετά από αυτήν την εργασία, θα μάθετε πώς να:
- Δημιουργήσετε μια ιστοσελίδα για να παρουσιάσετε το βιογραφικό σας
@ -23,9 +29,9 @@ _Πόσο ωραίο θα ήταν να ζητήσει ένας υπεύθυνο
## Βήματα
**Βήμα 1:** Δημιουργήστε ένα νέο αποθετήριο στο GitHub και δώστε του το όνομα `my-resume`
**Βήμα 1:** Δημιουργήστε ένα νέο αποθετήριο GitHub και δώστε του το όνομα `my-resume`
**Βήμα 2:** Δημιουργήστε ένα αρχείο `index.html` στο αποθετήριο σας. Θα προσθέσουμε τουλάχιστον ένα αρχείο ενώ βρισκόμαστε ακόμα στο github.com, γιατί δεν μπορείτε να ανοίξετε ένα κενό αποθετήριο στο vscode.dev.
**Βήμα 2:** Δημιουργήστε ένα αρχείο `index.html` στο αποθετήριό σας. Θα προσθέσουμε τουλάχιστον ένα αρχείο ενώ βρισκόμαστε ακόμα στο github.com, γιατί δεν μπορείτε να ανοίξετε ένα κενό αποθετήριο στο vscode.dev.
Κάντε κλικ στον σύνδεσμο `creating a new file`, πληκτρολογήστε το όνομα `index.html` και επιλέξτε το κουμπί `Commit new file`.
@ -33,7 +39,7 @@ _Πόσο ωραίο θα ήταν να ζητήσει ένας υπεύθυνο
**Βήμα 3:** Ανοίξτε το [VSCode.dev](https://vscode.dev) και επιλέξτε το κουμπί `Open Remote Repository`.
Αντιγράψτε το url του αποθετηρίου που μόλις δημιουργήσατε για την ιστοσελίδα του βιογραφικού σας και επικολλήστε το στο πλαίσιο εισαγωγής:
Αντιγράψτε το URL του αποθετηρίου που μόλις δημιουργήσατε για την ιστοσελίδα του βιογραφικού σας και επικολλήστε το στο πλαίσιο εισαγωγής:
_Αντικαταστήστε το `your-username` με το όνομα χρήστη σας στο GitHub._
@ -41,11 +47,11 @@ _Αντικαταστήστε το `your-username` με το όνομα χρήσ
https://github.com/your-username/my-resume
```
Αν είναι επιτυχές, θα δείτε το έργο σας και το αρχείο index.html να ανοίγουν στον επεξεργαστή κειμένου στον browser.
Εάν η διαδικασία ήταν επιτυχής, θα δείτε το έργο σας και το αρχείο index.html να ανοίγουν στον επεξεργαστή κειμένου στον περιηγητή.
![Δημιουργία νέου αρχείου](../../../../translated_images/project-on-vscode.dev.e79815a9a95ee7feac72ebe5c941c91279716be37c575dbdbf2f43bea2c7d8b6.el.png)
**Βήμα 4:** Ανοίξτε το αρχείο `index.html`, επικολλήστε τον παρακάτω κώδικα στην περιοχή του κώδικα σας και αποθηκεύστε.
**Βήμα 4:** Ανοίξτε το αρχείο `index.html`, επικολλήστε τον παρακάτω κώδικα στην περιοχή του κώδικα και αποθηκεύστε.
<details>
<summary><b>HTML κώδικας υπεύθυνος για το περιεχόμενο της ιστοσελίδας του βιογραφικού σας.</b></summary>
@ -59,7 +65,7 @@ https://github.com/your-username/my-resume
</head>
<body>
<header id="header">
<!-- Επικεφαλίδα βιογραφικού με το όνομά σας και τον τίτλο σας -->
<!-- κεφαλίδα βιογραφικού με το όνομά σας και τον τίτλο σας -->
<h1>Το Όνομά Σας Εδώ!</h1>
<hr>
Ο Ρόλος Σας!
@ -69,7 +75,7 @@ https://github.com/your-username/my-resume
<article id="mainLeft">
<section>
<h2>ΕΠΙΚΟΙΝΩΝΙΑ</h2>
<!-- Πληροφορίες επικοινωνίας, συμπεριλαμβανομένων των κοινωνικών δικτύων -->
<!-- στοιχεία επικοινωνίας, συμπεριλαμβανομένων των social media -->
<p>
<i class="fa fa-envelope" aria-hidden="true"></i>
<a href="mailto:username@domain.top-level domain">Γράψτε το email σας εδώ</a>
@ -85,7 +91,7 @@ https://github.com/your-username/my-resume
</section>
<section>
<h2>ΔΕΞΙΟΤΗΤΕΣ</h2>
<!-- Οι δεξιότητές σας -->
<!-- οι δεξιότητές σας -->
<ul>
<li>Δεξιότητα 1!</li>
<li>Δεξιότητα 2!</li>
@ -95,10 +101,10 @@ https://github.com/your-username/my-resume
</section>
<section>
<h2>ΕΚΠΑΙΔΕΥΣΗ</h2>
<!-- Η εκπαίδευσή σας -->
<!-- η εκπαίδευσή σας -->
<h3>Γράψτε το πρόγραμμα σπουδών σας εδώ!</h3>
<p>
Γράψτε το εκπαιδευτικό ίδρυμα σας εδώ!
Γράψτε το εκπαιδευτικό ίδρυμα εδώ!
</p>
<p>
Ημερομηνία Έναρξης - Ημερομηνία Λήξης
@ -108,20 +114,20 @@ https://github.com/your-username/my-resume
<article id="mainRight">
<section>
<h2>ΣΧΕΤΙΚΑ</h2>
<!-- Σχετικά με εσάς -->
<!-- λίγα λόγια για εσάς -->
<p>Γράψτε μια σύντομη περιγραφή για τον εαυτό σας!</p>
</section>
<section>
<h2>ΕΡΓΑΣΙΑΚΗ ΕΜΠΕΙΡΙΑ</h2>
<!-- Η εργασιακή σας εμπειρία -->
<h2>ΕΠΑΓΓΕΛΜΑΤΙΚΗ ΕΜΠΕΙΡΙΑ</h2>
<!-- η επαγγελματική σας εμπειρία -->
<h3>Τίτλος Εργασίας</h3>
<p>
Όνομα Οργανισμού | Μήνας Έναρξης Μήνας Λήξης
</p>
<ul>
<li>Εργασία 1 - Γράψτε τι κάνατε!</li>
<li>Εργασία 2 - Γράψτε τι κάνατε!</li>
<li>Γράψτε τα αποτελέσματα/την επίδραση της συνεισφοράς σας</li>
<li>Καθήκον 1 - Γράψτε τι κάνατε!</li>
<li>Καθήκον 2 - Γράψτε τι κάνατε!</li>
<li>Γράψτε τα αποτελέσματα/τον αντίκτυπο της συνεισφοράς σας</li>
</ul>
<h3>Τίτλος Εργασίας 2</h3>
@ -129,9 +135,9 @@ https://github.com/your-username/my-resume
Όνομα Οργανισμού | Μήνας Έναρξης Μήνας Λήξης
</p>
<ul>
<li>Εργασία 1 - Γράψτε τι κάνατε!</li>
<li>Εργασία 2 - Γράψτε τι κάνατε!</li>
<li>Γράψτε τα αποτελέσματα/την επίδραση της συνεισφοράς σας</li>
<li>Καθήκον 1 - Γράψτε τι κάνατε!</li>
<li>Καθήκον 2 - Γράψτε τι κάνατε!</li>
<li>Γράψτε τα αποτελέσματα/τον αντίκτυπο της συνεισφοράς σας</li>
</ul>
</section>
@ -141,9 +147,9 @@ https://github.com/your-username/my-resume
</html>
</details>
Προσθέστε τις λεπτομέρειες του βιογραφικού σας αντικαθιστώντας το _κείμενο placeholder_ στον HTML κώδικα.
Προσθέστε τα στοιχεία του βιογραφικού σας για να αντικαταστήσετε το _κείμενο υποδείγματος_ στον HTML κώδικα.
**Βήμα 5:** Περάστε πάνω από τον φάκελο My-Resume, κάντε κλικ στο εικονίδιο `New File ...` και δημιουργήστε 2 νέα αρχεία στο έργο σας: `style.css` και `codeswing.json`.
**Βήμα 5:** Τοποθετήστε τον δείκτη πάνω στον φάκελο My-Resume, κάντε κλικ στο εικονίδιο `New File ...` και δημιουργήστε 2 νέα αρχεία στο έργο σας: `style.css` και `codeswing.json`.
**Βήμα 6:** Ανοίξτε το αρχείο `style.css`, επικολλήστε τον παρακάτω κώδικα και αποθηκεύστε.
@ -217,9 +223,9 @@ https://github.com/your-username/my-resume
"styles": []
}
**Βήμα 7:** Εγκαταστήστε την επέκταση `Codeswing` για να δείτε την ιστοσελίδα του βιογραφικού σας στην περιοχή του κώδικα.
**Βήμα 7:** Εγκαταστήστε την επέκταση `Codeswing` για να δείτε την ιστοσελίδα του βιογραφικού σας στον χώρο του κώδικα.
Κάντε κλικ στο εικονίδιο _`Extensions`_ στη γραμμή δραστηριοτήτων και πληκτρολογήστε Codeswing. Είτε κάντε κλικ στο _μπλε κουμπί εγκατάστασης_ στη διευρυμένη γραμμή δραστηριοτήτων για να εγκαταστήσετε είτε χρησιμοποιήστε το κουμπί εγκατάστασης που εμφανίζεται στην περιοχή του κώδικα μόλις επιλέξετε την επέκταση για να φορτώσετε πρόσθετες πληροφορίες. Αμέσως μετά την εγκατάσταση της επέκτασης, παρατηρήστε την περιοχή του κώδικα σας για να δείτε τις αλλαγές στο έργο σας 😃
Κάντε κλικ στο εικονίδιο _`Extensions`_ στη γραμμή δραστηριοτήτων και πληκτρολογήστε Codeswing. Είτε κάντε κλικ στο _μπλε κουμπί εγκατάστασης_ στη διευρυμένη γραμμή δραστηριοτήτων για να εγκαταστήσετε είτε χρησιμοποιήστε το κουμπί εγκατάστασης που εμφανίζεται στον χώρο του κώδικα μόλις επιλέξετε την επέκταση για να φορτώσετε πρόσθετες πληροφορίες. Αμέσως μετά την εγκατάσταση της επέκτασης, παρατηρήστε τον χώρο του κώδικα για να δείτε τις αλλαγές στο έργο σας 😃.
![Εγκατάσταση επεκτάσεων](../../../../8-code-editor/images/install-extension.gif)
@ -227,9 +233,9 @@ https://github.com/your-username/my-resume
![Η επέκταση Codeswing σε δράση](../../../../translated_images/after-codeswing-extension-pb.0ebddddcf73b550994947a9084e35e2836c713ae13839d49628e3c764c1cfe83.el.png)
Αν είστε ικανοποιημένοι με τις αλλαγές που κάνατε, περάστε πάνω από τον φάκελο `Changes` και κάντε κλικ στο κουμπί `+` για να σταδιοποιήσετε τις αλλαγές.
Εάν είστε ικανοποιημένοι με τις αλλαγές που κάνατε, τοποθετήστε τον δείκτη πάνω στον φάκελο `Changes` και κάντε κλικ στο κουμπί `+` για να σταδιοποιήσετε τις αλλαγές.
Πληκτρολογήστε ένα μήνυμα commit _(Μια περιγραφή της αλλαγής που κάνατε στο έργο)_ και κάντε commit τις αλλαγές σας κάνοντας κλικ στο `check`. Μόλις τελειώσετε με το έργο σας, επιλέξτε το εικονίδιο του μενού hamburger στην επάνω αριστερή γωνία για να επιστρέψετε στο αποθετήριο στο GitHub.
Πληκτρολογήστε ένα μήνυμα δέσμευσης _(Μια περιγραφή της αλλαγής που κάνατε στο έργο)_ και δεσμεύστε τις αλλαγές σας κάνοντας κλικ στο `check`. Όταν τελειώσετε με το έργο σας, επιλέξτε το εικονίδιο του μενού hamburger πάνω αριστερά για να επιστρέψετε στο αποθετήριο στο GitHub.
Συγχαρητήρια 🎉 Μόλις δημιουργήσατε την ιστοσελίδα του βιογραφικού σας χρησιμοποιώντας το vscode.dev σε λίγα βήματα.
@ -243,5 +249,5 @@ https://github.com/your-username/my-resume
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
**Αποποίηση Ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -0,0 +1,389 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "cf15ff7770c5a484349383bb27d1131f",
"translation_date": "2025-08-29T09:44:48+00:00",
"source_file": "9-chat-project/README.md",
"language_code": "el"
}
-->
# Έργο Συνομιλίας
Αυτό το έργο συνομιλίας δείχνει πώς να δημιουργήσετε έναν Βοηθό Συνομιλίας χρησιμοποιώντας τα GitHub Models.
Δείτε πώς μοιάζει το τελικό έργο:
<div>
<img src="./assets/screenshot.png" alt="Εφαρμογή συνομιλίας" width="600">
</div>
Λίγα λόγια για το πλαίσιο: η δημιουργία βοηθών συνομιλίας με τη χρήση γενετικής AI είναι ένας εξαιρετικός τρόπος για να ξεκινήσετε να μαθαίνετε για την AI. Σε αυτό το μάθημα, θα μάθετε πώς να ενσωματώνετε γενετική AI σε μια εφαρμογή ιστού. Ας ξεκινήσουμε.
## Σύνδεση με γενετική AI
Για το backend, χρησιμοποιούμε τα GitHub Models. Είναι μια εξαιρετική υπηρεσία που σας επιτρέπει να χρησιμοποιείτε AI δωρεάν. Μεταβείτε στο playground της και πάρτε τον κώδικα που αντιστοιχεί στη γλώσσα backend που επιλέξατε. Δείτε πώς φαίνεται στο [GitHub Models Playground](https://github.com/marketplace/models/azure-openai/gpt-4o-mini/playground)
<div>
<img src="./assets/playground.png" alt="GitHub Models AI Playground" with="600">
</div>
Όπως είπαμε, επιλέξτε την καρτέλα "Code" και το runtime που προτιμάτε.
<div>
<img src="./assets/playground-choice.png" alt="playground choice" with="600">
</div>
Σε αυτή την περίπτωση, επιλέγουμε Python, που σημαίνει ότι θα πάρουμε τον εξής κώδικα:
```python
"""Run this model in Python
> pip install openai
"""
import os
from openai import OpenAI
# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
client = OpenAI(
base_url="https://models.github.ai/inference",
api_key=os.environ["GITHUB_TOKEN"],
)
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "",
},
{
"role": "user",
"content": "What is the capital of France?",
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
print(response.choices[0].message.content)
```
Ας καθαρίσουμε λίγο αυτόν τον κώδικα ώστε να είναι επαναχρησιμοποιήσιμος:
```python
def call_llm(prompt: str, system_message: str):
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": system_message,
},
{
"role": "user",
"content": prompt,
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
return response.choices[0].message.content
```
Με αυτή τη συνάρτηση `call_llm`, μπορούμε τώρα να δώσουμε ένα prompt και ένα system prompt, και η συνάρτηση θα επιστρέψει το αποτέλεσμα.
### Προσαρμογή του Βοηθού AI
Αν θέλετε να προσαρμόσετε τον βοηθό AI, μπορείτε να καθορίσετε πώς θέλετε να συμπεριφέρεται, γεμίζοντας το system prompt όπως παρακάτω:
```python
call_llm("Tell me about you", "You're Albert Einstein, you only know of things in the time you were alive")
```
## Έκθεση μέσω Web API
Ωραία, ολοκληρώσαμε το μέρος της AI. Ας δούμε πώς μπορούμε να το ενσωματώσουμε σε ένα Web API. Για το Web API, επιλέγουμε να χρησιμοποιήσουμε Flask, αλλά οποιοδήποτε web framework θα ήταν κατάλληλο. Δείτε τον κώδικα:
```python
# api.py
from flask import Flask, request, jsonify
from llm import call_llm
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # * example.com
@app.route("/", methods=["GET"])
def index():
return "Welcome to this API. Call POST /hello with 'message': 'my message' as JSON payload"
@app.route("/hello", methods=["POST"])
def hello():
# get message from request body { "message": "do this taks for me" }
data = request.get_json()
message = data.get("message", "")
response = call_llm(message, "You are a helpful assistant.")
return jsonify({
"response": response
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
```
Εδώ, δημιουργούμε ένα API με Flask και ορίζουμε μια προεπιλεγμένη διαδρομή "/" και "/chat". Η δεύτερη προορίζεται για χρήση από το frontend μας, ώστε να περνάει ερωτήσεις σε αυτό.
Για να ενσωματώσουμε το *llm.py*, πρέπει να κάνουμε τα εξής:
- Εισαγωγή της συνάρτησης `call_llm`:
```python
from llm import call_llm
from flask import Flask, request
```
- Κλήση της από τη διαδρομή "/chat":
```python
@app.route("/hello", methods=["POST"])
def hello():
# get message from request body { "message": "do this taks for me" }
data = request.get_json()
message = data.get("message", "")
response = call_llm(message, "You are a helpful assistant.")
return jsonify({
"response": response
})
```
Εδώ αναλύουμε το εισερχόμενο αίτημα για να ανακτήσουμε την ιδιότητα `message` από το σώμα JSON. Στη συνέχεια, καλούμε το LLM με την εξής κλήση:
```python
response = call_llm(message, "You are a helpful assistant")
# return the response as JSON
return jsonify({
"response": response
})
```
Ωραία, τώρα έχουμε ολοκληρώσει ό,τι χρειαζόμαστε.
### Ρύθμιση Cors
Πρέπει να αναφέρουμε ότι ρυθμίσαμε κάτι σαν το CORS (cross-origin resource sharing). Αυτό σημαίνει ότι, επειδή το backend και το frontend μας θα τρέχουν σε διαφορετικές θύρες, πρέπει να επιτρέψουμε στο frontend να καλεί το backend. Υπάρχει ένα κομμάτι κώδικα στο *api.py* που το ρυθμίζει:
```python
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # * example.com
```
Αυτή τη στιγμή έχει ρυθμιστεί να επιτρέπει "*" (όλες τις προελεύσεις), κάτι που είναι λίγο ανασφαλές. Πρέπει να το περιορίσουμε όταν πάμε σε παραγωγή.
## Εκτέλεση του έργου σας
Εντάξει, έχουμε τα *llm.py* και *api.py*. Πώς μπορούμε να τα κάνουμε να λειτουργήσουν με ένα backend; Υπάρχουν δύο πράγματα που πρέπει να κάνουμε:
- Εγκατάσταση εξαρτήσεων:
```sh
cd backend
python -m venv venv
source ./venv/bin/activate
pip install openai flask flask-cors openai
```
- Εκκίνηση του API:
```sh
python api.py
```
Αν βρίσκεστε σε Codespaces, πρέπει να μεταβείτε στις Θύρες στο κάτω μέρος του επεξεργαστή, να κάνετε δεξί κλικ και να επιλέξετε "Port Visibility" και να επιλέξετε "Public".
### Δημιουργία frontend
Τώρα που έχουμε ένα API σε λειτουργία, ας δημιουργήσουμε ένα frontend για αυτό. Ένα ελάχιστο frontend που θα βελτιώσουμε σταδιακά. Στον φάκελο *frontend*, δημιουργήστε τα εξής:
```text
backend/
frontend/
index.html
app.js
styles.css
```
Ας ξεκινήσουμε με το **index.html**:
```html
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<form>
<textarea id="messages"></textarea>
<input id="input" type="text" />
<button type="submit" id="sendBtn">Send</button>
</form>
<script src="app.js" />
</body>
</html>
```
Το παραπάνω είναι το απολύτως ελάχιστο που χρειάζεστε για να υποστηρίξετε ένα παράθυρο συνομιλίας, καθώς αποτελείται από ένα textarea όπου θα εμφανίζονται τα μηνύματα, ένα input για να πληκτρολογείτε το μήνυμα και ένα κουμπί για να στέλνετε το μήνυμά σας στο backend. Ας δούμε τον JavaScript κώδικα στο *app.js*.
**app.js**
```js
// app.js
(function(){
// 1. set up elements
const messages = document.getElementById("messages");
const form = document.getElementById("form");
const input = document.getElementById("input");
const BASE_URL = "change this";
const API_ENDPOINT = `${BASE_URL}/hello`;
// 2. create a function that talks to our backend
async function callApi(text) {
const response = await fetch(API_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text })
});
let json = await response.json();
return json.response;
}
// 3. add response to our textarea
function appendMessage(text, role) {
const el = document.createElement("div");
el.className = `message ${role}`;
el.innerHTML = text;
messages.appendChild(el);
}
// 4. listen to submit events
form.addEventListener("submit", async(e) => {
e.preventDefault();
// someone clicked the button in the form
// get input
const text = input.value.trim();
appendMessage(text, "user")
// reset it
input.value = '';
const reply = await callApi(text);
// add to messages
appendMessage(reply, "assistant");
})
})();
```
Ας δούμε τον κώδικα ανά ενότητα:
- 1) Εδώ παίρνουμε αναφορές σε όλα τα στοιχεία που θα χρησιμοποιήσουμε αργότερα στον κώδικα.
- 2) Σε αυτή την ενότητα, δημιουργούμε μια συνάρτηση που χρησιμοποιεί τη μέθοδο `fetch` για να καλεί το backend μας.
- 3) Η `appendMessage` βοηθά στην προσθήκη απαντήσεων καθώς και των μηνυμάτων που πληκτρολογεί ο χρήστης.
- 4) Εδώ ακούμε το γεγονός υποβολής και διαβάζουμε το πεδίο εισόδου, τοποθετούμε το μήνυμα του χρήστη στο textarea, καλούμε το API και εμφανίζουμε την απάντηση στο textarea.
Ας δούμε το styling στη συνέχεια. Εδώ μπορείτε να γίνετε δημιουργικοί και να το κάνετε να μοιάζει όπως θέλετε, αλλά εδώ είναι μερικές προτάσεις:
**styles.css**
```
.message {
background: #222;
box-shadow: 0 0 0 10px orange;
padding: 10px:
margin: 5px;
}
.message.user {
background: blue;
}
.message.assistant {
background: grey;
}
```
Με αυτές τις τρεις κλάσεις, θα στυλιζάρετε τα μηνύματα διαφορετικά ανάλογα με το αν προέρχονται από τον βοηθό ή από εσάς ως χρήστη. Αν θέλετε έμπνευση, δείτε τον φάκελο `solution/frontend/styles.css`.
### Αλλαγή της Βασικής Διεύθυνσης URL
Υπάρχει κάτι που δεν ρυθμίσαμε, και αυτό είναι το `BASE_URL`. Αυτό δεν είναι γνωστό μέχρι να ξεκινήσει το backend σας. Για να το ρυθμίσετε:
- Αν τρέχετε το API τοπικά, θα πρέπει να είναι κάτι σαν `http://localhost:5000`.
- Αν τρέχετε σε Codespaces, θα πρέπει να μοιάζει με "[name]app.github.dev".
## Εργασία
Δημιουργήστε τον δικό σας φάκελο *project* με περιεχόμενο όπως παρακάτω:
```text
project/
frontend/
index.html
app.js
styles.css
backend/
api.py
llm.py
```
Αντιγράψτε το περιεχόμενο από ό,τι περιγράφηκε παραπάνω, αλλά προσαρμόστε το όπως θέλετε.
## Λύση
[Λύση](./solution/README.md)
## Bonus
Δοκιμάστε να αλλάξετε την προσωπικότητα του βοηθού AI. Όταν καλείτε τη `call_llm` στο *api.py*, μπορείτε να αλλάξετε το δεύτερο όρισμα όπως θέλετε, για παράδειγμα:
```python
call_llm(message, "You are Captain Picard")
```
Αλλάξτε επίσης το CSS και το κείμενο όπως θέλετε, κάνοντας αλλαγές στα *index.html* και *styles.css*.
## Περίληψη
Ωραία, μάθατε από την αρχή πώς να δημιουργήσετε έναν προσωπικό βοηθό χρησιμοποιώντας AI. Το κάναμε αυτό χρησιμοποιώντας τα GitHub Models, ένα backend σε Python και ένα frontend σε HTML, CSS και JavaScript.
## Ρύθμιση με Codespaces
- Μεταβείτε στο: [Web Dev For Beginners repo](https://github.com/microsoft/Web-Dev-For-Beginners)
- Δημιουργήστε από ένα πρότυπο (βεβαιωθείτε ότι έχετε συνδεθεί στο GitHub) στην επάνω δεξιά γωνία:
![Create from template](../../../translated_images/template.67ad477109d29a2b04599a83c964c87fcde041256d4f04d3589cbb00c696f76c.el.png)
- Μόλις βρεθείτε στο αποθετήριό σας, δημιουργήστε ένα Codespace:
![Create codespace](../../../translated_images/codespace.bcecbdf5d2747d3d17da67a78ad911c8853d68102e34748ec372cde1e9236e1d.el.png)
Αυτό θα ξεκινήσει ένα περιβάλλον με το οποίο μπορείτε τώρα να εργαστείτε.
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -0,0 +1,55 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "a7b7f54b13f9e6683a844d173ffdd766",
"translation_date": "2025-08-29T09:48:32+00:00",
"source_file": "9-chat-project/solution/README.md",
"language_code": "el"
}
-->
# Εκτέλεση κώδικα
## Ρύθμιση
Δημιουργήστε εικονικό περιβάλλον
```sh
cd backend
python -m venv venv
source ./venv/bin/activate
```
## Εγκατάσταση εξαρτήσεων
```sh
pip install openai flask flask-cors
```
## Εκτέλεση API
```sh
python api.py
```
## Εκτέλεση frontend
Βεβαιωθείτε ότι βρίσκεστε στον φάκελο του frontend
Εντοπίστε το *app.js*, αλλάξτε το `BASE_URL` στη διεύθυνση URL του backend σας
Εκτελέστε το
```
npx http-server -p 8000
```
Δοκιμάστε να πληκτρολογήσετε ένα μήνυμα στη συνομιλία, θα πρέπει να δείτε μια απάντηση (υπό την προϋπόθεση ότι το εκτελείτε σε ένα Codespace ή έχετε ρυθμίσει ένα access token).
## Ρύθμιση access token (αν δεν το εκτελείτε σε ένα Codespace)
Δείτε [Set up PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε κάθε προσπάθεια για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,30 +1,30 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "efa251c5fc089367f0a81c572874afca",
"translation_date": "2025-08-28T02:54:23+00:00",
"original_hash": "687c62646ad5595f1ba733edc294cdae",
"translation_date": "2025-08-29T06:55:58+00:00",
"source_file": "README.md",
"language_code": "el"
}
-->
[![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/)
[![Άδεια GitHub](https://img.shields.io/github/license/microsoft/Web-Dev-For-Beginners.svg)](https://github.com/microsoft/Web-Dev-For-Beginners/blob/master/LICENSE)
[![Συνεισφέροντες GitHub](https://img.shields.io/github/contributors/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/graphs/contributors/)
[![Θέματα GitHub](https://img.shields.io/github/issues/microsoft/Web-Dev-For-Beginners.svg)](https://GitHub.com/microsoft/Web-Dev-For-Beginners/issues/)
[![Αιτήματα έλξης GitHub](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](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/)
[![Forks GitHub](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](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/)
[![](https://dcbadge.vercel.app/api/server/ByRwuEEgH4)](https://discord.gg/zxKYvhSnVp?WT.mc_id=academic-000002-leestott)
[![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)
[![Άνοιγμα στο 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)
[![Microsoft Azure AI Foundry Discord](https://dcbadge.limes.pink/api/server/ByRwuEEgH4)](https://discord.com/invite/ByRwuEEgH4)
Ακολουθήστε αυτά τα βήματα για να ξεκινήσετε να χρησιμοποιείτε αυτούς τους πόρους:
1. **Κάντε Fork το Αποθετήριο**: Πατήστε [![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)
1. **Κάντε Fork το Αποθετήριο**: Πατήστε [![Forks GitHub](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. **Κλωνοποιήστε το Αποθετήριο**: `git clone https://github.com/microsoft/Web-Dev-For-Beginners.git`
3. [**Γίνετε μέλος στο Azure AI Foundry Discord και γνωρίστε ειδικούς και άλλους προγραμματιστές**](https://discord.com/invite/ByRwuEEgH4)
@ -32,26 +32,38 @@ CO_OP_TRANSLATOR_METADATA:
Μάθετε τα βασικά της ανάπτυξης ιστού με το 12-εβδομάδων ολοκληρωμένο μάθημα από τους Microsoft Cloud Advocates. Κάθε ένα από τα 24 μαθήματα εστιάζει σε JavaScript, CSS και HTML μέσω πρακτικών έργων όπως τεραριούμ, επεκτάσεις προγράμματος περιήγησης και παιχνίδια διαστήματος. Συμμετέχετε σε κουίζ, συζητήσεις και πρακτικές εργασίες. Βελτιώστε τις δεξιότητές σας και ενισχύστε τη διατήρηση της γνώσης σας με την αποτελεσματική παιδαγωγική μας που βασίζεται σε έργα. Ξεκινήστε το ταξίδι σας στον προγραμματισμό σήμερα!
### 🌐 Υποστήριξη Πολλαπλών Γλωσσών
#### Υποστηρίζεται μέσω GitHub Action (Αυτοματοποιημένο & Πάντα Ενημερωμένο)
[Γαλλικά](../fr/README.md) | [Ισπανικά](../es/README.md) | [Γερμανικά](../de/README.md) | [Ρωσικά](../ru/README.md) | [Αραβικά](../ar/README.md) | [Περσικά (Φαρσί)](../fa/README.md) | [Ουρντού](../ur/README.md) | [Κινέζικα (Απλοποιημένα)](../zh/README.md) | [Κινέζικα (Παραδοσιακά, Μακάο)](../mo/README.md) | [Κινέζικα (Παραδοσιακά, Χονγκ Κονγκ)](../hk/README.md) | [Κινέζικα (Παραδοσιακά, Ταϊβάν)](../tw/README.md) | [Ιαπωνικά](../ja/README.md) | [Κορεατικά](../ko/README.md) | [Χίντι](../hi/README.md) | [Βεγγαλικά](../bn/README.md) | [Μαραθικά](../mr/README.md) | [Νεπαλικά](../ne/README.md) | [Παντζάμπι (Γκουρμούκι)](../pa/README.md) | [Πορτογαλικά (Πορτογαλία)](../pt/README.md) | [Πορτογαλικά (Βραζιλία)](../br/README.md) | [Ιταλικά](../it/README.md) | [Πολωνικά](../pl/README.md) | [Τουρκικά](../tr/README.md) | [Ελληνικά](./README.md) | [Ταϊλανδικά](../th/README.md) | [Σουηδικά](../sv/README.md) | [Δανικά](../da/README.md) | [Νορβηγικά](../no/README.md) | [Φινλανδικά](../fi/README.md) | [Ολλανδικά](../nl/README.md) | [Εβραϊκά](../he/README.md) | [Βιετναμέζικα](../vi/README.md) | [Ινδονησιακά](../id/README.md) | [Μαλαισιακά](../ms/README.md) | [Ταγκάλογκ (Φιλιππινέζικα)](../tl/README.md) | [Σουαχίλι](../sw/README.md) | [Ουγγρικά](../hu/README.md) | [Τσέχικα](../cs/README.md) | [Σλοβακικά](../sk/README.md) | [Ρουμανικά](../ro/README.md) | [Βουλγαρικά](../bg/README.md) | [Σερβικά (Κυριλλικά)](../sr/README.md) | [Κροατικά](../hr/README.md) | [Σλοβενικά](../sl/README.md) | [Ουκρανικά](../uk/README.md) | [Βιρμανικά (Μιανμάρ)](../my/README.md)
**Αν θέλετε να υποστηριχθούν επιπλέον γλώσσες, οι διαθέσιμες γλώσσες αναφέρονται [εδώ](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
#### 🧑‍🎓 _Είστε φοιτητής;_
Επισκεφθείτε τη [**σελίδα Student Hub**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon) όπου θα βρείτε πόρους για αρχάριους, πακέτα για φοιτητές και ακόμη και τρόπους για να αποκτήσετε δωρεάν κουπόνι πιστοποίησης. Αυτή είναι η σελίδα που θέλετε να προσθέσετε στους σελιδοδείκτες σας και να ελέγχετε τακτικά, καθώς αλλάζουμε το περιεχόμενο κάθε μήνα.
Επισκεφθείτε τη [**Σελίδα Φοιτητών**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon) όπου θα βρείτε πόρους για αρχάριους, πακέτα φοιτητών και ακόμη και τρόπους για να αποκτήσετε δωρεάν κουπόνι πιστοποίησης. Αυτή είναι η σελίδα που θέλετε να αποθηκεύσετε και να ελέγχετε τακτικά, καθώς το περιεχόμενο αλλάζει μηνιαία.
### 📣 Ανακοίνωση - _Νέο Πρόγραμμα Σπουδών_ για Γενετική Τεχνητή Νοημοσύνη με JavaScript μόλις κυκλοφόρησε
### 📣 Ανακοίνωση - _Νέο Έργο για Δημιουργία με Γενετική Τεχνητή Νοημοσύνη_
Προστέθηκε νέο έργο AI Assistant, δείτε το [έργο](./09-chat-project/README.md)
### 📣 Ανακοίνωση - _Νέο Πρόγραμμα Σπουδών_ για Γενετική Τεχνητή Νοημοσύνη με JavaScript
Μην χάσετε το νέο μας πρόγραμμα σπουδών για Γενετική Τεχνητή Νοημοσύνη!
Επισκεφθείτε [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course) για να ξεκινήσετε!
![Background](../../translated_images/background.148a8d43afde57303419a663f50daf586681bc2fabf833f66ef6954073983c66.el.png)
![Φόντο](../../translated_images/background.148a8d43afde57303419a663f50daf586681bc2fabf833f66ef6954073983c66.el.png)
- Μαθήματα που καλύπτουν τα πάντα, από τα βασικά έως το RAG.
- Αλληλεπιδράστε με ιστορικές προσωπικότητες χρησιμοποιώντας το GenAI και την εφαρμογή συνοδού μας.
- Αλληλεπιδράστε με ιστορικές προσωπικότητες χρησιμοποιώντας το GenAI και την εφαρμογή συνοδείας μας.
- Διασκεδαστική και συναρπαστική αφήγηση, θα ταξιδέψετε στον χρόνο!
![character](../../translated_images/character.5c0dd8e067ffd693c16e2c5b7412ab075a2215ce31f998305639fa3a05e14fbe.el.png)
![χαρακτήρας](../../translated_images/character.5c0dd8e067ffd693c16e2c5b7412ab075a2215ce31f998305639fa3a05e14fbe.el.png)
Κάθε μάθημα περιλαμβάνει μια εργασία για ολοκλήρωση, έναν έλεγχο γνώσεων και μια πρόκληση για να σας καθοδηγήσει σε θέματα όπως:
- Δημιουργία προτροπών και μηχανική προτροπών
- Δημιουργία και βελτιστοποίηση προτροπών
- Δημιουργία εφαρμογών κειμένου και εικόνας
- Εφαρμογές αναζήτησης
@ -59,17 +71,17 @@ CO_OP_TRANSLATOR_METADATA:
## 🌱 Ξεκινώντας
> **Καθηγητές**, έχουμε [συμπεριλάβει κάποιες προτάσεις](for-teachers.md) για το πώς να χρησιμοποιήσετε αυτό το πρόγραμμα σπουδών. Θα θέλαμε πολύ τα σχόλιά σας [στο φόρουμ συζητήσεων μας](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
> **Καθηγητές**, έχουμε [συμπεριλάβει κάποιες προτάσεις](for-teachers.md) για το πώς να χρησιμοποιήσετε αυτό το πρόγραμμα σπουδών. Θα θέλαμε τα σχόλιά σας [στο φόρουμ συζητήσεων](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
**[Μαθητές](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, για κάθε μάθημα, ξεκινήστε με ένα κουίζ πριν το μάθημα και συνεχίστε διαβάζοντας το υλικό του μαθήματος, ολοκληρώνοντας τις διάφορες δραστηριότητες και ελέγξτε την κατανόησή σας με το κουίζ μετά το μάθημα.
**[Μαθητές](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, για κάθε μάθημα, ξεκινήστε με ένα κουίζ πριν τη διάλεξη και συνεχίστε διαβάζοντας το υλικό της διάλεξης, ολοκληρώνοντας τις διάφορες δραστηριότητες και ελέγξτε την κατανόησή σας με το κουίζ μετά τη διάλεξη.
Για να βελτιώσετε την εμπειρία μάθησής σας, συνδεθείτε με τους συναδέλφους σας για να δουλέψετε μαζί στα έργα! Οι συζητήσεις ενθαρρύνονται στο [φόρουμ συζητήσεων μας](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), όπου η ομάδα των συντονιστών μας θα είναι διαθέσιμη για να απαντήσει στις ερωτήσεις σας.
Για να βελτιώσετε την εμπειρία μάθησής σας, συνδεθείτε με τους συναδέλφους σας για να εργαστείτε μαζί στα έργα! Ενθαρρύνονται οι συζητήσεις στο [φόρουμ συζητήσεων](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), όπου η ομάδα των συντονιστών μας θα είναι διαθέσιμη να απαντήσει στις ερωτήσεις σας.
Για να προχωρήσετε την εκπαίδευσή σας, συνιστούμε ανεπιφύλακτα να εξερευνήσετε το [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) για επιπλέον υλικό μελέτης.
### 📋 Ρύθμιση του περιβάλλοντός σας
Αυτό το πρόγραμμα σπουδών έχει ένα έτοιμο περιβάλλον ανάπτυξης! Καθώς ξεκινάτε, μπορείτε να επιλέξετε να εκτελέσετε το πρόγραμμα σπουδών σε ένα [Codespace](https://github.com/features/codespaces/) (_ένα περιβάλλον που βασίζεται σε πρόγραμμα περιήγησης, χωρίς ανάγκη εγκατάστασης_), ή τοπικά στον υπολογιστή σας χρησιμοποιώντας έναν επεξεργαστή κειμένου όπως το [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
Αυτό το πρόγραμμα σπουδών έχει ένα περιβάλλον ανάπτυξης έτοιμο για χρήση! Καθώς ξεκινάτε, μπορείτε να επιλέξετε να εκτελέσετε το πρόγραμμα σπουδών σε ένα [Codespace](https://github.com/features/codespaces/) (_ένα περιβάλλον βασισμένο σε πρόγραμμα περιήγησης, χωρίς ανάγκη εγκαταστάσεων_), ή τοπικά στον υπολογιστή σας χρησιμοποιώντας έναν επεξεργαστή κειμένου όπως το [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
#### Δημιουργήστε το αποθετήριό σας
Για να αποθηκεύσετε εύκολα τη δουλειά σας, συνιστάται να δημιουργήσετε το δικό σας αντίγραφο αυτού του αποθετηρίου. Μπορείτε να το κάνετε πατώντας το κουμπί **Use this template** στην κορυφή της σελίδας. Αυτό θα δημιουργήσει ένα νέο αποθετήριο στον λογαριασμό σας στο GitHub με ένα αντίγραφο του προγράμματος σπουδών.
@ -80,7 +92,7 @@ CO_OP_TRANSLATOR_METADATA:
#### Εκτέλεση του προγράμματος σπουδών σε ένα Codespace
Στο αντίγραφο αυτού του αποθετηρίου που δημιουργήσατε, πατήστε το κουμπί **Code** και επιλέξτε **Open with Codespaces**. Αυτό θα δημιουργήσει ένα νέο Codespace για να δουλέψετε.
Στο αντίγραφο αυτού του αποθετηρίου που δημιουργήσατε, πατήστε το κουμπί **Code** και επιλέξτε **Open with Codespaces**. Αυτό θα δημιουργήσει ένα νέο Codespace για να εργαστείτε.
[!Codespace](../..)./images/createcodespace.png)
@ -88,123 +100,107 @@ CO_OP_TRANSLATOR_METADATA:
Για να εκτελέσετε αυτό το πρόγραμμα σπουδών τοπικά στον υπολογιστή σας, θα χρειαστείτε έναν επεξεργαστή κειμένου, ένα πρόγραμμα περιήγησης και ένα εργαλείο γραμμής εντολών. Το πρώτο μας μάθημα, [Εισαγωγή στις Γλώσσες Προγραμματισμού και τα Εργαλεία του Επαγγέλματος](../../1-getting-started-lessons/1-intro-to-programming-languages), θα σας καθοδηγήσει στις διάφορες επιλογές για καθένα από αυτά τα εργαλεία, ώστε να επιλέξετε αυτό που σας ταιριάζει καλύτερα.
Η πρότασή μας είναι να χρησιμοποιήσετε το [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) ως επεξεργαστή, το οποίο διαθέτει επίσης ενσωματωμένο [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).
Η πρότασή μας είναι να χρησιμοποιήσετε το [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) ως τον επεξεργαστή σας, ο οποίος διαθέτει επίσης ενσωματωμένο [Τερματικό](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).
1. Κλωνοποιήστε το αποθετήριό σας στον υπολογιστή σας. Μπορείτε να το κάνετε πατώντας το κουμπί **Code** και αντιγράφοντας το URL:
[!CodeSpace](./images/createcodespace.png)
Στη συνέχεια, ανοίξτε το [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) και εκτελέστε την παρακάτω εντολή, αντικαθιστώντας το `<your-repository-url>` με το URL που μόλις αντιγράψατε:
Στη συνέχεια, ανοίξτε το [Τερματικό](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) και εκτελέστε την παρακάτω εντολή, αντικαθιστώντας το `<your-repository-url>` με το URL που μόλις αντιγράψατε:
```bash
git clone <your-repository-url>
```
2. Ανοίξτε τον φάκελο στο Visual Studio Code. Μπορείτε να το κάνετε πατώντας **File** > **Open Folder** και επιλέγοντας τον φάκελο που μόλις κλωνοποιήσατε.
> Συνιστώμενες επεκτάσεις για το Visual Studio Code:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - για προεπισκόπηση σελίδων HTML μέσα από το Visual Studio Code
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - για να σας βοηθήσει να γράφετε κώδικα πιο γρήγορα
## 📂 Κάθε μάθημα περιλαμβάνει:
- προαιρετικό σκίτσο
- προαιρετικό συμπληρωματικό βίντεο
- κουίζ προθέρμανσης πριν το μάθημα
- γραπτό μάθημα
- για μαθήματα που βασίζονται σε έργα, οδηγίες βήμα-βήμα για την κατασκευή του έργου
- ελέγχους γνώσεων
- μια πρόκληση
- συμπληρωματική ανάγνωση
- εργασία
- [κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/)
> **Σημείωση για τα κουίζ**: Όλα τα κουίζ περιέχονται στον φάκελο Quiz-app, συνολικά 48 κουίζ με τρεις ερωτήσεις το καθένα. Είναι διαθέσιμα [εδώ](https://ff-quizzes.netlify.app/web/) και η εφαρμογή κουίζ μπορεί να εκτελεστεί τοπικά ή να αναπτυχθεί στο Azure. Ακολουθήστε τις οδηγίες στον φάκελο `quiz-app`.
## 🗃️ Μαθήματα
| | Όνομα Έργου | Διδασκόμενες Έννοιες | Μαθησιακοί Στόχοι | Συνδεδεμένο Μάθημα | Συγγραφέας |
| :-: | :------------------------------------------------------: | :--------------------------------------------------------------------: | ----------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------: | :---------------------: |
| 01 | Ξεκινώντας | Εισαγωγή στον Προγραμματισμό και τα Εργαλεία του Επαγγέλματος | Μάθετε τις βασικές αρχές πίσω από τις περισσότερες γλώσσες προγραμματισμού και για το λογισμικό που βοηθά τους επαγγελματίες προγραμματιστές στη δουλειά τους | [Εισαγωγή στις Γλώσσες Προγραμματισμού και τα Εργαλεία του Επαγγέλματος](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Ξεκινώντας | Βασικά του GitHub, περιλαμβάνει εργασία με ομάδα | Πώς να χρησιμοποιήσετε το GitHub στο έργο σας, πώς να συνεργαστείτε με άλλους σε μια βάση κώδικα | [Εισαγωγή στο GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Ξεκινώντας | Προσβασιμότητα | Μάθετε τα βασικά της προσβασιμότητας στον ιστό | [Βασικές Αρχές Προσβασιμότητας](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | Βασικά JS | Τύποι Δεδομένων JavaScript | Τα βασικά των τύπων δεδομένων στη JavaScript | [Τύποι Δεδομένων](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | Βασικά JS | Συναρτήσεις και Μέθοδοι | Μάθετε για τις συναρτήσεις και τις μεθόδους για τη διαχείριση της ροής λογικής μιας εφαρμογής | [Συναρτήσεις και Μέθοδοι](./2-js-basics/2-functions-methods/README.md) | Jasmine and Christopher |
| 06 | Βασικά JS | Λήψη Αποφάσεων με JS | Μάθετε πώς να δημιουργείτε συνθήκες στον κώδικά σας χρησιμοποιώντας μεθόδους λήψης αποφάσεων | [Λήψη Αποφάσεων](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | Βασικά JS | Πίνακες και Βρόχοι | Εργαστείτε με δεδομένα χρησιμοποιώντας πίνακες και βρόχους στη JavaScript | [Πίνακες και Βρόχοι](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Τεραριούμ](./3-terrarium/solution/README.md) | HTML στην Πράξη | Δημιουργήστε το HTML για να φτιάξετε ένα online τεραριούμ, εστιάζοντας στη δημιουργία μιας διάταξης | [Εισαγωγή στο HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Τεραριούμ](./3-terrarium/solution/README.md) | CSS στην Πράξη | Δημιουργήστε το CSS για να διαμορφώσετε το online τεραριούμ, εστιάζοντας στα βασικά του CSS, συμπεριλαμβανομένης της προσαρμογής της
| 10 | [Terrarium](./3-terrarium/solution/README.md) | Κλεισίματα JavaScript, Χειρισμός DOM | Δημιουργήστε τον κώδικα JavaScript για να λειτουργεί το terrarium ως διεπαφή drag/drop, εστιάζοντας στα κλεισίματα και τον χειρισμό DOM | [Κλεισίματα JavaScript, Χειρισμός DOM](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typing Game](./4-typing-game/solution/README.md) | Δημιουργία Παιχνιδιού Πληκτρολόγησης | Μάθετε πώς να χρησιμοποιείτε γεγονότα πληκτρολογίου για να καθοδηγήσετε τη λογική της εφαρμογής σας σε JavaScript | [Προγραμματισμός με Γεγονότα](./4-typing-game/typing-game/README.md) | Christopher |
2. Ανοίξτε τον φάκελο στο Visual Studio Code. Μπορείτε να το κάνετε πατώντας **File**.
> **Άνοιγμα Φακέλου** και επιλογή του φακέλου που μόλις κλωνοποιήσατε.
> Προτεινόμενες επεκτάσεις για το Visual Studio Code:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - για προεπισκόπηση σελίδων HTML μέσα από το Visual Studio Code
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - για να γράφετε κώδικα πιο γρήγορα
## 📂 Κάθε μάθημα περιλαμβάνει:
- προαιρετική σκίτσο-σημείωση
- προαιρετικό συμπληρωματικό βίντεο
- κουίζ προθέρμανσης πριν το μάθημα
- γραπτό μάθημα
- για μαθήματα που βασίζονται σε έργα, βήμα-βήμα οδηγίες για την κατασκευή του έργου
- έλεγχος γνώσεων
- μία πρόκληση
- συμπληρωματική ανάγνωση
- εργασία
- [κουίζ μετά το μάθημα](https://ff-quizzes.netlify.app/web/)
> **Σημείωση για τα κουίζ**: Όλα τα κουίζ βρίσκονται στον φάκελο Quiz-app, συνολικά 48 κουίζ με τρεις ερωτήσεις το καθένα. Είναι διαθέσιμα [εδώ](https://ff-quizzes.netlify.app/web/) και η εφαρμογή κουίζ μπορεί να εκτελεστεί τοπικά ή να αναπτυχθεί στο Azure. Ακολουθήστε τις οδηγίες στον φάκελο `quiz-app`.
## 🗃️ Μαθήματα
| | Όνομα Έργου | Διδασκόμενες Έννοιες | Μαθησιακοί Στόχοι | Συνδεδεμένο Μάθημα | Συγγραφέας |
| :-: | :------------------------------------------------------: | :--------------------------------------------------------------------: | ----------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------: | :---------------------: |
| 01 | Ξεκινώντας | Εισαγωγή στον Προγραμματισμό και τα Εργαλεία του Επαγγέλματος | Μάθετε τις βασικές αρχές πίσω από τις περισσότερες γλώσσες προγραμματισμού και για το λογισμικό που βοηθά τους επαγγελματίες προγραμματιστές | [Εισαγωγή στις Γλώσσες Προγραμματισμού και τα Εργαλεία του Επαγγέλματος](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Ξεκινώντας | Βασικά του GitHub, περιλαμβάνει εργασία με ομάδα | Πώς να χρησιμοποιείτε το GitHub στο έργο σας, πώς να συνεργάζεστε με άλλους σε μια βάση κώδικα | [Εισαγωγή στο GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Ξεκινώντας | Προσβασιμότητα | Μάθετε τα βασικά της προσβασιμότητας στον ιστό | [Βασικές Αρχές Προσβασιμότητας](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | Βασικά JS | Τύποι Δεδομένων JavaScript | Τα βασικά των τύπων δεδομένων της JavaScript | [Τύποι Δεδομένων](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | Βασικά JS | Συναρτήσεις και Μέθοδοι | Μάθετε για τις συναρτήσεις και τις μεθόδους για τη διαχείριση της ροής λογικής μιας εφαρμογής | [Συναρτήσεις και Μέθοδοι](./2-js-basics/2-functions-methods/README.md) | Jasmine and Christopher |
| 06 | Βασικά JS | Λήψη Αποφάσεων με JS | Μάθετε πώς να δημιουργείτε συνθήκες στον κώδικά σας χρησιμοποιώντας μεθόδους λήψης αποφάσεων | [Λήψη Αποφάσεων](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | Βασικά JS | Πίνακες και Βρόχοι | Εργαστείτε με δεδομένα χρησιμοποιώντας πίνακες και βρόχους στη JavaScript | [Πίνακες και Βρόχοι](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML στην Πράξη | Δημιουργήστε το HTML για να φτιάξετε ένα online terrarium, εστιάζοντας στη δημιουργία διάταξης | [Εισαγωγή στο HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS στην Πράξη | Δημιουργήστε το CSS για να στυλιζάρετε το online terrarium, εστιάζοντας στα βασικά του CSS, συμπεριλαμβανομένης της προσαρμογής της σελίδας | [Εισαγωγή στο CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | Κλεισίματα JavaScript, Διαχείριση DOM | Δημιουργήστε το JavaScript για να λειτουργήσει το terrarium ως διεπαφή drag/drop, εστιάζοντας στα κλεισίματα και τη διαχείριση DOM | [Κλεισίματα JavaScript, Διαχείριση DOM](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typing Game](./4-typing-game/solution/README.md) | Δημιουργία Παιχνιδιού Πληκτρολόγησης | Μάθετε πώς να χρησιμοποιείτε γεγονότα πληκτρολογίου για να καθοδηγήσετε τη λογική της εφαρμογής σας | [Προγραμματισμός με Γεγονότα](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Εργασία με Περιηγητές | Μάθετε πώς λειτουργούν οι περιηγητές, την ιστορία τους, και πώς να δημιουργήσετε τα πρώτα στοιχεία μιας επέκτασης περιηγητή | [Σχετικά με τους Περιηγητές](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Δημιουργία φόρμας, κλήση API και αποθήκευση μεταβλητών στην τοπική αποθήκευση | Δημιουργήστε τα στοιχεία JavaScript της επέκτασης περιηγητή σας για να καλέσετε ένα API χρησιμοποιώντας μεταβλητές που αποθηκεύονται στην τοπική αποθήκευση | [APIs, Φόρμες, και Τοπική Αποθήκευση](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Διεργασίες παρασκηνίου στον περιηγητή, απόδοση ιστού | Χρησιμοποιήστε τις διεργασίες παρασκηνίου του περιηγητή για να διαχειριστείτε το εικονίδιο της επέκτασης· μάθετε για την απόδοση ιστού και κάποιες βελτιστοποιήσεις για να το πετύχετε | [Διεργασίες Παρασκηνίου και Απόδοση](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | Πιο Προχωρημένη Ανάπτυξη Παιχνιδιών με JavaScript | Μάθετε για την Κληρονομικότητα χρησιμοποιώντας τόσο Κλάσεις όσο και Σύνθεση και το μοτίβο Pub/Sub, ως προετοιμασία για τη δημιουργία ενός παιχνιδιού | [Εισαγωγή στην Προχωρημένη Ανάπτυξη Παιχνιδιών](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Σχεδίαση σε καμβά | Μάθετε για το API του Καμβά, που χρησιμοποιείται για να σχεδιάσετε στοιχεία στην οθόνη | [Σχεδίαση σε Καμβά](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Μετακίνηση στοιχείων στην οθόνη | Ανακαλύψτε πώς τα στοιχεία μπορούν να αποκτήσουν κίνηση χρησιμοποιώντας τις καρτεσιανές συντεταγμένες και το API του Καμβά | [Μετακίνηση Στοιχείων](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Ανίχνευση σύγκρουσης | Κάντε τα στοιχεία να συγκρούονται και να αντιδρούν μεταξύ τους χρησιμοποιώντας πατήματα πλήκτρων και παρέχετε μια λειτουργία καθυστέρησης για να εξασφαλίσετε την απόδοση του παιχνιδιού | [Ανίχνευση Σύγκρουσης](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Καταγραφή σκορ | Εκτελέστε μαθηματικούς υπολογισμούς βασισμένους στην κατάσταση και την απόδοση του παιχνιδιού | [Καταγραφή Σκορ](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Τερματισμός και επανεκκίνηση του παιχνιδιού | Μάθετε για τον τερματισμό και την επανεκκίνηση του παιχνιδιού, συμπεριλαμβανομένης της εκκαθάρισης πόρων και της επαναφοράς τιμών μεταβλητών | [Η Συνθήκη Τερματισμού](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Banking App](./7-bank-project/solution/README.md) | Πρότυπα HTML και Διαδρομές σε μια Εφαρμογή Ιστού | Μάθετε πώς να δημιουργήσετε τη δομή της αρχιτεκτονικής μιας ιστοσελίδας πολλαπλών σελίδων χρησιμοποιώντας διαδρομές και πρότυπα HTML | [Πρότυπα HTML και Διαδρομές](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Banking App](./7-bank-project/solution/README.md) | Δημιουργία Φόρμας Εισόδου και Εγγραφής | Μάθετε για τη δημιουργία φορμών και τη διαχείριση διαδικασιών επικύρωσης | [Φόρμες](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Banking App](./7-bank-project/solution/README.md) | Μέθοδοι Ανάκτησης και Χρήσης Δεδομένων | Πώς τα δεδομένα ρέουν μέσα και έξω από την εφαρμογή σας, πώς να τα ανακτήσετε, να τα αποθηκεύσετε και να τα διαχειριστείτε | [Δεδομένα](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Banking App](./7-bank-project/solution/README.md) | Έννοιες Διαχείρισης Κατάστασης | Μάθετε πώς η εφαρμογή σας διατηρεί την κατάσταση και πώς να τη διαχειριστείτε προγραμματιστικά | [Διαχείριση Κατάστασης](./7-bank-project/4-state-management/README.md) | Yohan |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Δημιουργία φόρμας, κλήση API και αποθήκευση μεταβλητών σε τοπική αποθήκευση | Δημιουργήστε τα στοιχεία JavaScript της επέκτασης περιηγητή σας για να καλέσετε ένα API χρησιμοποιώντας μεταβλητές αποθηκευμένες σε τοπική αποθήκευση | [APIs, Φόρμες και Τοπική Αποθήκευση](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Διεργασίες στο παρασκήνιο του περιηγητή, απόδοση ιστού | Χρησιμοποιήστε τις διεργασίες παρασκηνίου του περιηγητή για να διαχειριστείτε το εικονίδιο της επέκτασης. Μάθετε για την απόδοση ιστού και κάποιες βελτιστοποιήσεις | [Διεργασίες Παρασκηνίου και Απόδοση](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | Πιο Προχωρημένη Ανάπτυξη Παιχνιδιών με JavaScript | Μάθετε για την Κληρονομικότητα χρησιμοποιώντας τόσο Κλάσεις όσο και Σύνθεση και το μοτίβο Pub/Sub, ως προετοιμασία για τη δημιουργία παιχνιδιού | [Εισαγωγή στην Προχωρημένη Ανάπτυξη Παιχνιδιών](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Σχεδίαση σε καμβά | Μάθετε για το Canvas API, που χρησιμοποιείται για τη σχεδίαση στοιχείων στην οθόνη | [Σχεδίαση σε Καμβά](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Μετακίνηση στοιχείων στην οθόνη | Ανακαλύψτε πώς τα στοιχεία μπορούν να αποκτήσουν κίνηση χρησιμοποιώντας τις καρτεσιανές συντεταγμένες και το Canvas API | [Μετακίνηση Στοιχείων](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Ανίχνευση συγκρούσεων | Κάντε τα στοιχεία να συγκρούονται και να αντιδρούν μεταξύ τους χρησιμοποιώντας πατήματα πλήκτρων και παρέχετε μια λειτουργία ψύξης για την απόδοση του παιχνιδιού | [Ανίχνευση Συγκρούσεων](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Καταγραφή σκορ | Εκτελέστε μαθηματικούς υπολογισμούς με βάση την κατάσταση και την απόδοση του παιχνιδιού | [Καταγραφή Σκορ](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Τερματισμός και επανεκκίνηση παιχνιδιού | Μάθετε για τον τερματισμό και την επανεκκίνηση του παιχνιδιού, συμπεριλαμβανομένου του καθαρισμού πόρων και της επαναφοράς τιμών μεταβλητών | [Συνθήκη Τερματισμού](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Banking App](./7-bank-project/solution/README.md) | Πρότυπα HTML και Διαδρομές σε μια Εφαρμογή Ιστού | Μάθετε πώς να δημιουργείτε τη δομή της αρχιτεκτονικής μιας ιστοσελίδας πολλαπλών σελίδων χρησιμοποιώντας διαδρομές και πρότυπα HTML | [Πρότυπα HTML και Διαδρομές](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Banking App](./7-bank-project/solution/README.md) | Δημιουργία Φόρμας Εισόδου και Εγγραφής | Μάθετε για τη δημιουργία φορμών και τη διαχείριση ρουτινών επικύρωσης | [Φόρμες](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Banking App](./7-bank-project/solution/README.md) | Μέθοδοι Ανάκτησης και Χρήσης Δεδομένων | Πώς τα δεδομένα ρέουν μέσα και έξω από την εφαρμογή σας, πώς να τα ανακτάτε, να τα αποθηκεύετε και να τα διαχειρίζεστε | [Δεδομένα](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Banking App](./7-bank-project/solution/README.md) | Έννοιες Διαχείρισης Κατάστασης | Μάθετε πώς η εφαρμογή σας διατηρεί την κατάσταση και πώς να τη διαχειρίζεστε προγραμματιστικά | [Διαχείριση Κατάστασης](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Browser/VScode Code](../../8-code-editor) | Εργασία με το VScode | Μάθετε πώς να χρησιμοποιείτε έναν επεξεργαστή κώδικα | [Χρήση του VScode Code Editor](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Assistants](./9-chat-project/README.md) | Εργασία με AI | Μάθετε πώς να δημιουργήσετε τον δικό σας βοηθό AI | [Έργο Βοηθού AI](./9-chat-project/README.md) | Chris |
## 🏫 Παιδαγωγική
Το πρόγραμμα σπουδών μας έχει σχεδιαστεί με δύο βασικές παιδαγωγικές αρχές:
* μάθηση βασισμένη σε έργα
* μάθηση μέσω έργων
* συχνά κουίζ
Το πρόγραμμα διδάσκει τα βασικά του JavaScript, HTML και CSS, καθώς και τα πιο πρόσφατα εργαλεία και τεχνικές που χρησιμοποιούν οι σημερινοί προγραμματιστές ιστού. Οι μαθητές θα έχουν την ευκαιρία να αποκτήσουν πρακτική εμπειρία δημιουργώντας ένα παιχνίδι πληκτρολόγησης, ένα εικονικό terrarium, μια φιλική προς το περιβάλλον επέκταση περιηγητή, ένα παιχνίδι τύπου space-invader και μια τραπεζική εφαρμογή για επιχειρήσεις. Μέχρι το τέλος της σειράς, οι μαθητές θα έχουν αποκτήσει μια σταθερή κατανόηση της ανάπτυξης ιστού.
Το πρόγραμμα διδάσκει τα βασικά της JavaScript, HTML και CSS, καθώς και τα πιο σύγχρονα εργαλεία και τεχνικές που χρησιμοποιούν οι σημερινοί προγραμματιστές ιστού. Οι μαθητές θα έχουν την ευκαιρία να αποκτήσουν πρακτική εμπειρία δημιουργώντας ένα παιχνίδι πληκτρολόγησης, ένα εικονικό terrarium, μια φιλική προς το περιβάλλον επέκταση περιηγητή, ένα παιχνίδι τύπου space-invader και μια τραπεζική εφαρμογή για επιχειρήσεις. Μέχρι το τέλος της σειράς, οι μαθητές θα έχουν αποκτήσει μια σταθερή κατανόηση της ανάπτυξης ιστού.
> 🎓 Μπορείτε να παρακολουθήσετε τα πρώτα μαθήματα αυτού του προγράμματος σπουδών ως [Learn Path](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) στο Microsoft Learn!
> 🎓 Μπορείτε να παρακολουθήσετε τα πρώτα μαθήματα αυτού του προγράμματος σπουδών ως [Μονοπάτι Μάθησης](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) στο Microsoft Learn!
Με την εξασφάλιση ότι το περιεχόμενο ευθυγραμμίζεται με έργα, η διαδικασία γίνεται πιο ενδιαφέρουσα για τους μαθητές και η διατήρηση των εννοιών ενισχύεται. Γράψαμε επίσης αρκετά εισαγωγικά μαθήματα στα βασικά του JavaScript για να εισαγάγουμε έννοιες, συνοδευόμενα από ένα βίντεο από τη συλλογή "[Beginners Series to: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)" με εκπαιδευτικά βίντεο, μερικοί από τους συγγραφείς των οποίων συνέβαλαν σε αυτό το πρόγραμμα σπουδών.
Με την εξασφάλιση ότι το περιεχόμενο ευθυγραμμίζεται με τα έργα, η διαδικασία γίνεται πιο ενδιαφέρουσα για τους μαθητές και η διατήρηση των εννοιών ενισχύεται. Γράψαμε επίσης αρκετά εισαγωγικά μαθήματα στις βασικές αρχές της JavaScript για να εισαγάγουμε έννοιες, συνοδευόμενα από ένα βίντεο από τη συλλογή "[Σειρά για Αρχάριους: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)", μερικοί από τους συγγραφείς της οποίας συνέβαλαν σε αυτό το πρόγραμμα σπουδών.
Επιπλέον, ένα κουίζ χαμηλού κινδύνου πριν από την τάξη θέτει την πρόθεση του μαθητή προς την εκμάθηση ενός θέματος, ενώ ένα δεύτερο κουίζ μετά την τάξη εξασφαλίζει περαιτέρω διατήρηση. Αυτό το πρόγραμμα σπουδών σχεδιάστηκε για να είναι ευέλικτο και διασκεδαστικό και μπορεί να παρακολουθηθεί ολόκληρο ή τμηματικά. Τα έργα ξεκινούν μικρά και γίνονται όλο και πιο περίπλοκα μέχρι το τέλος του 12-εβδομαδιαίου κύκλου.
Επιπλέον, ένα κουίζ χαμηλού ρίσκου πριν από το μάθημα θέτει την πρόθεση του μαθητή προς την εκμάθηση ενός θέματος, ενώ ένα δεύτερο κουίζ μετά το μάθημα εξασφαλίζει περαιτέρω διατήρηση. Αυτό το πρόγραμμα σπουδών σχεδιάστηκε για να είναι ευέλικτο και διασκεδαστικό και μπορεί να παρακολουθηθεί ολόκληρο ή εν μέρει. Τα έργα ξεκινούν μικρά και γίνονται όλο και πιο περίπλοκα μέχρι το τέλος του 12-εβδομάδων κύκλου.
Παρόλο που αποφύγαμε σκόπιμα την εισαγωγή πλαισίων JavaScript για να επικεντρωθούμε στις βασικές δεξιότητες που χρειάζονται ως προγραμματιστής ιστού πριν από την υιοθέτηση ενός πλαισίου, ένα καλό επόμενο βήμα μετά την ολοκλήρωση αυτού του προγράμματος σπουδών θα ήταν η εκμάθηση του Node.js μέσω μιας άλλης συλλογής βίντεο: "[Beginner Series to: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
> Επισκεφθείτε τις [Οδηγίες Συμπεριφοράς](CODE_OF_CONDUCT.md) και τις [Οδηγίες Συνεισφοράς](CONTRIBUTING.md). Καλωσορίζουμε τα εποικοδομητικά σας σχόλια!
Ενώ αποφύγαμε σκόπιμα την εισαγωγή πλαισίων JavaScript για να επικεντρωθούμε στις βασικές δεξιότητες που χρειάζονται ως προγραμματιστής ιστού πριν από την υιοθέτηση ενός πλαισίου, ένα καλό επόμενο βήμα μετά την ολοκλήρωση αυτού του προγράμματος σπουδών θα ήταν η εκμάθηση του Node.js μέσω μιας άλλης συλλογής βίντεο: "[Σειρά για Αρχάριους: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
> Επισκεφθείτε τις [Οδηγίες Συμπεριφοράς](CODE_OF_CONDUCT.md) και τις [Οδηγίες Συνεισφοράς](CONTRIBUTING.md) μας. Περιμένουμε με χαρά τα εποικοδομητικά σας σχόλια!
## 🧭 Πρόσβαση εκτός σύνδεσης
Μπορείτε να εκτελέσετε αυτήν την τεκμηρίωση εκτός σύνδεσης χρησιμοποιώντας το [Docsify](https://docsify.js.org/#/). Κλωνοποιήστε αυτό το αποθετήριο, [εγκαταστήστε το Docsify](https://docsify.js.org/#/quickstart) στον τοπικό σας υπολογιστή και στη συνέχεια, στον ριζικό φάκελο αυτού του αποθετηρίου, πληκτρολογήστε `docsify serve`. Ο ιστότοπος θα εξυπηρετηθεί στην θύρα 3000 του localhost σας: `localhost:3000`.
## 📘 PDF
Ένα PDF με όλα τα μαθήματα μπορείτε να βρείτε [εδώ](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
## 🎒 Άλλα Μαθήματα
Η ομάδα μας παράγει και άλλα μαθήματα! Δείτε:
- [Generative AI for Beginners](https://aka.ms/genai-beginners)
- [Generative AI for Beginners .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet)
- [Generative AI with JavaScript](https://github.com/microsoft/generative-ai-with-javascript)
- [Generative AI with Java](https://github.com/microsoft/Generative-AI-for-beginners-java)
- [AI for Beginners](https://aka.ms/ai-beginners)
- [Data Science for Beginners](https://aka.ms/datascience-beginners)
- [ML for Beginners](https://aka.ms/ml-beginners)
- [Cybersecurity for Beginners](https://github.com/microsoft/Security-101)
- [Web Dev for Beginners](https://aka.ms/webdev-beginners)
- [IoT for Beginners](https://aka.ms/iot-beginners)
- [XR Development for Beginners](https://github.com/microsoft/xr-development-for-beginners)
- [Mastering GitHub Copilot for Agentic use](https://github.com/microsoft/Mastering-GitHub-Copilot-for-Paired-Programming)
- [Mastering GitHub Copilot for C#/.NET Developers](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
- [Choose Your Own Copilot Adventure](https://github.com/microsoft/CopilotAdventures)
Μπορείτε να εκτελέσετε αυτήν την τεκμηρίωση εκτός σύνδεσης χρησιμοποιώντας το [Docsify](https://docsify.js.org/#/). Κλωνοποιήστε αυτό το αποθετήριο, [εγκαταστήστε το Docsify](https://docsify.js.org/#/quickstart) στον τοπικό σας υπολογιστή και στη συνέχεια, στον ριζικό φάκελο αυτού του αποθετηρίου, πληκτρολογήστε `docsify serve`. Ο ιστότοπος θα εξυπηρετηθεί στη θύρα 3000 στον τοπικό σας διακομιστή: `localhost
- [Επιστήμη Δεδομένων για Αρχάριους](https://aka.ms/datascience-beginners)
- [Μηχανική Μάθηση για Αρχάριους](https://aka.ms/ml-beginners)
- [Κυβερνοασφάλεια για Αρχάριους](https://github.com/microsoft/Security-101)
- [Ανάπτυξη Ιστού για Αρχάριους](https://aka.ms/webdev-beginners)
- [IoT για Αρχάριους](https://aka.ms/iot-beginners)
- [Ανάπτυξη XR για Αρχάριους](https://github.com/microsoft/xr-development-for-beginners)
- [Κατανόηση του GitHub Copilot για Χρήση με Πρακτορικό Στυλ](https://github.com/microsoft/Mastering-GitHub-Copilot-for-Paired-Programming)
- [Κατανόηση του GitHub Copilot για Προγραμματιστές C#/.NET](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
- [Επιλέξτε τη Δική σας Περιπέτεια με το Copilot](https://github.com/microsoft/CopilotAdventures)
## Άδεια Χρήσης
## Άδεια Χρήσης
Αυτό το αποθετήριο έχει άδεια χρήσης MIT. Δείτε το αρχείο [LICENSE](../../LICENSE) για περισσότερες πληροφορίες.
Αυτό το αποθετήριο διαθέτει άδεια χρήσης MIT. Δείτε το αρχείο [LICENSE](../../LICENSE) για περισσότερες πληροφορίες.
---
**Αποποίηση ευθύνης**:
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.
Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.

@ -1,15 +1,15 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "c63675cfaf1d223b37bb9fecbfe7c252",
"translation_date": "2025-08-27T23:13:46+00:00",
"original_hash": "2dcbb9259dee4f20a4f08d9a1aa2bd4c",
"translation_date": "2025-08-29T09:17:50+00:00",
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md",
"language_code": "id"
}
-->
# Pengantar Bahasa Pemrograman dan Alat yang Digunakan
Pelajaran ini membahas dasar-dasar bahasa pemrograman. Topik yang dibahas di sini berlaku untuk sebagian besar bahasa pemrograman modern saat ini. Pada bagian 'Alat yang Digunakan', Anda akan mempelajari perangkat lunak yang berguna bagi pengembang.
Pelajaran ini membahas dasar-dasar bahasa pemrograman. Topik yang dibahas di sini berlaku untuk sebagian besar bahasa pemrograman modern saat ini. Pada bagian 'Alat yang Digunakan', Anda akan mempelajari perangkat lunak yang berguna untuk membantu Anda sebagai pengembang.
![Intro Programming](../../../../translated_images/webdev101-programming.d6e3f98e61ac4bff0b27dcbf1c3f16c8ed46984866f2d29988929678b0058fde.id.png)
> Sketchnote oleh [Tomomi Imura](https://twitter.com/girlie_mac)
@ -24,7 +24,7 @@ Dalam pelajaran ini, kita akan membahas:
- Apa itu pemrograman?
- Jenis-jenis bahasa pemrograman
- Elemen dasar dari sebuah program
- Perangkat lunak dan alat yang berguna bagi pengembang profesional
- Perangkat lunak dan alat yang berguna untuk pengembang profesional
> Anda dapat mengikuti pelajaran ini di [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/introduction-programming/?WT.mc_id=academic-77807-sagibbon)!
@ -32,7 +32,7 @@ Dalam pelajaran ini, kita akan membahas:
Pemrograman (juga dikenal sebagai coding) adalah proses menulis instruksi untuk perangkat seperti komputer atau perangkat seluler. Kita menulis instruksi ini menggunakan bahasa pemrograman, yang kemudian diinterpretasikan oleh perangkat. Kumpulan instruksi ini dapat disebut dengan berbagai nama, seperti *program*, *program komputer*, *aplikasi (app)*, dan *eksekusi*.
Sebuah *program* bisa berupa apa saja yang ditulis dengan kode; situs web, permainan, dan aplikasi ponsel adalah program. Meskipun memungkinkan untuk membuat program tanpa menulis kode, logika dasarnya diinterpretasikan oleh perangkat, dan logika tersebut kemungkinan besar ditulis dengan kode. Program yang *berjalan* atau *mengeksekusi* kode sedang menjalankan instruksi. Perangkat yang Anda gunakan untuk membaca pelajaran ini sedang menjalankan program untuk menampilkan pelajaran ini di layar Anda.
Sebuah *program* bisa berupa apa saja yang ditulis dengan kode; situs web, permainan, dan aplikasi ponsel adalah program. Meskipun memungkinkan untuk membuat program tanpa menulis kode, logika dasarnya diinterpretasikan oleh perangkat, dan logika tersebut kemungkinan besar ditulis dengan kode. Program yang sedang *berjalan* atau *mengeksekusi* kode sedang menjalankan instruksi. Perangkat yang Anda gunakan untuk membaca pelajaran ini sedang menjalankan program untuk menampilkan pelajaran ini di layar Anda.
✅ Lakukan sedikit penelitian: siapa yang dianggap sebagai programmer komputer pertama di dunia?
@ -40,7 +40,7 @@ Sebuah *program* bisa berupa apa saja yang ditulis dengan kode; situs web, perma
Bahasa pemrograman memungkinkan pengembang menulis instruksi untuk perangkat. Perangkat hanya dapat memahami biner (1s dan 0s), dan bagi *kebanyakan* pengembang, itu bukan cara yang efisien untuk berkomunikasi. Bahasa pemrograman adalah sarana komunikasi antara manusia dan komputer.
Bahasa pemrograman hadir dalam berbagai format dan dapat melayani tujuan yang berbeda. Misalnya, JavaScript terutama digunakan untuk aplikasi web, sedangkan Bash terutama digunakan untuk sistem operasi.
Bahasa pemrograman hadir dalam berbagai format dan dapat melayani tujuan yang berbeda. Misalnya, JavaScript terutama digunakan untuk aplikasi web, sementara Bash terutama digunakan untuk sistem operasi.
*Bahasa tingkat rendah* biasanya membutuhkan lebih sedikit langkah dibandingkan *bahasa tingkat tinggi* bagi perangkat untuk menginterpretasikan instruksi. Namun, yang membuat bahasa tingkat tinggi populer adalah keterbacaan dan dukungannya. JavaScript dianggap sebagai bahasa tingkat tinggi.
@ -89,7 +89,7 @@ Percaya atau tidak, *keduanya melakukan hal yang sama*: mencetak urutan Fibonacc
## Elemen Program
Satu instruksi dalam program disebut *pernyataan* dan biasanya memiliki karakter atau spasi baris yang menandai di mana instruksi berakhir, atau *berhenti*. Cara program berhenti bervariasi tergantung pada setiap bahasa.
Satu instruksi dalam program disebut *pernyataan* dan biasanya memiliki karakter atau spasi baris yang menandai di mana instruksi berakhir, atau *berhenti*. Cara program berhenti bervariasi untuk setiap bahasa.
Pernyataan dalam program mungkin bergantung pada data yang diberikan oleh pengguna atau sumber lain untuk menjalankan instruksi. Data dapat mengubah cara program berperilaku, sehingga bahasa pemrograman dilengkapi dengan cara untuk menyimpan data sementara agar dapat digunakan nanti. Ini disebut *variabel*. Variabel adalah pernyataan yang menginstruksikan perangkat untuk menyimpan data dalam memorinya. Variabel dalam program mirip dengan variabel dalam aljabar, di mana mereka memiliki nama unik dan nilainya dapat berubah seiring waktu.
@ -151,7 +151,7 @@ Beberapa pengembang lebih memilih tampilan yang kurang grafis untuk tugas sehari
### Opsi Baris Perintah Populer
Opsi untuk baris perintah akan berbeda tergantung pada sistem operasi yang Anda gunakan.
Opsi untuk baris perintah akan berbeda berdasarkan sistem operasi yang Anda gunakan.
*💻 = sudah terinstal di sistem operasi.*
@ -176,7 +176,7 @@ Opsi untuk baris perintah akan berbeda tergantung pada sistem operasi yang Anda
#### Alat Baris Perintah Populer
- [Git](https://git-scm.com/) (💻 pada sebagian besar sistem operasi)
- [Git](https://git-scm.com/) (💻 di sebagian besar sistem operasi)
- [NPM](https://www.npmjs.com/)
- [Yarn](https://classic.yarnpkg.com/en/docs/cli/)
@ -198,10 +198,10 @@ Ketika seorang pengembang ingin mempelajari sesuatu yang baru, mereka kemungkina
## 🚀 Tantangan
Bandingkan beberapa bahasa pemrograman. Apa saja ciri khas JavaScript vs. Java? Bagaimana dengan COBOL vs. Go?
Bandingkan beberapa bahasa pemrograman. Apa saja ciri khas JavaScript dibandingkan Java? Bagaimana dengan COBOL dibandingkan Go?
## Kuis Pasca-Pelajaran
[Kuis pasca-pelajaran](https://ff-quizzes.netlify.app/web/quiz/2)
[Kuis pasca-pelajaran](https://ff-quizzes.netlify.app/web/)
## Tinjauan & Studi Mandiri
@ -214,4 +214,4 @@ Pelajari sedikit tentang berbagai bahasa yang tersedia untuk programmer. Cobalah
---
**Penafian**:
Dokumen ini telah diterjemahkan menggunakan layanan penerjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Meskipun kami berupaya untuk memberikan hasil yang akurat, harap diingat bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang otoritatif. Untuk informasi yang bersifat kritis, disarankan menggunakan jasa penerjemahan profesional oleh manusia. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari penggunaan terjemahan ini.
Dokumen ini telah diterjemahkan menggunakan layanan penerjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Meskipun kami berupaya untuk memberikan hasil yang akurat, harap diperhatikan bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang berwenang. Untuk informasi yang bersifat kritis, disarankan menggunakan jasa penerjemahan manusia profesional. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari penggunaan terjemahan ini.

@ -1,8 +1,8 @@
<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "05666cecb8983a72cf0ce1d18932b5b7",
"translation_date": "2025-08-27T23:20:45+00:00",
"original_hash": "361249da70432ddfd4741c917d1a6f50",
"translation_date": "2025-08-29T09:19:16+00:00",
"source_file": "1-getting-started-lessons/2-github-basics/README.md",
"language_code": "id"
}
@ -14,8 +14,8 @@ Pelajaran ini mencakup dasar-dasar GitHub, sebuah platform untuk menyimpan dan m
![Intro to GitHub](../../../../translated_images/webdev101-github.8846d7971abef6f947909b4f9d343e2a23778aa716ca6b9d71df7174ee5009ac.id.png)
> Sketchnote oleh [Tomomi Imura](https://twitter.com/girlie_mac)
## Kuis Sebelum Pelajaran
[Kuis sebelum pelajaran](https://ff-quizzes.netlify.app/web/quiz/3)
## Kuis Pra-Pelajaran
[Kuis pra-pelajaran](https://ff-quizzes.netlify.app)
## Pengantar
@ -39,19 +39,19 @@ Untuk memeriksa apakah Git sudah dikonfigurasi, Anda dapat mengetik:
Anda juga memerlukan akun GitHub, editor kode (seperti Visual Studio Code), dan Anda perlu membuka terminal Anda (atau: command prompt).
Kunjungi [github.com](https://github.com/) dan buat akun jika Anda belum memilikinya, atau masuk dan lengkapi profil Anda.
Kunjungi [github.com](https://github.com/) dan buat akun jika Anda belum memilikinya, atau masuk dan lengkapi profil Anda.
✅ GitHub bukan satu-satunya repositori kode di dunia; ada yang lain, tetapi GitHub adalah yang paling dikenal.
### Persiapan
Anda memerlukan folder dengan proyek kode di komputer lokal Anda (laptop atau PC), dan repositori publik di GitHub, yang akan digunakan sebagai contoh cara berkontribusi pada proyek orang lain.
Anda memerlukan folder dengan proyek kode di komputer lokal Anda (laptop atau PC), dan repositori publik di GitHub, yang akan digunakan sebagai contoh cara berkontribusi pada proyek orang lain.
---
## Manajemen Kode
Misalkan Anda memiliki folder lokal dengan proyek kode dan ingin mulai melacak kemajuan Anda menggunakan git - sistem kontrol versi. Beberapa orang membandingkan penggunaan git dengan menulis surat cinta untuk diri Anda di masa depan. Membaca pesan commit Anda beberapa hari, minggu, atau bulan kemudian, Anda akan dapat mengingat mengapa Anda membuat keputusan tertentu, atau "mengembalikan" perubahan - yaitu, jika Anda menulis "pesan commit" yang baik.
Misalkan Anda memiliki folder lokal dengan proyek kode dan Anda ingin mulai melacak kemajuan Anda menggunakan git - sistem kontrol versi. Beberapa orang membandingkan penggunaan git dengan menulis surat cinta untuk diri Anda di masa depan. Membaca pesan commit Anda beberapa hari, minggu, atau bulan kemudian, Anda akan dapat mengingat mengapa Anda membuat keputusan tertentu, atau "mengembalikan" perubahan - yaitu, jika Anda menulis "pesan commit" yang baik.
### Tugas: Membuat repositori dan commit kode
@ -59,9 +59,9 @@ Misalkan Anda memiliki folder lokal dengan proyek kode dan ingin mulai melacak k
>
> [![Video dasar-dasar Git dan GitHub](https://img.youtube.com/vi/9R31OUPpxU4/0.jpg)](https://www.youtube.com/watch?v=9R31OUPpxU4)
1. **Buat repositori di GitHub**. Di GitHub.com, pada tab repositori, atau dari bilah navigasi kanan atas, temukan tombol **new repo**.
1. **Buat repositori di GitHub**. Di GitHub.com, di tab repositori, atau dari bilah navigasi kanan atas, temukan tombol **new repo**.
1. Beri nama repositori (folder) Anda.
1. Beri nama repositori (folder) Anda
1. Pilih **create repository**.
1. **Navigasikan ke folder kerja Anda**. Di terminal Anda, pindah ke folder (juga dikenal sebagai direktori) yang ingin Anda mulai lacak. Ketik:
@ -95,14 +95,14 @@ Misalkan Anda memiliki folder lokal dengan proyek kode dan ingin mulai melacak k
Biasanya perintah `git status` memberi tahu Anda hal-hal seperti file apa yang siap untuk _disimpan_ ke repo atau memiliki perubahan yang mungkin ingin Anda simpan.
1. **Tambahkan semua file untuk dilacak**
1. **Tambahkan semua file untuk dilacak**
Ini juga disebut sebagai menambahkan file ke area staging.
```bash
git add .
```
Perintah `git add` dengan argumen `.` menunjukkan bahwa semua file & perubahan Anda akan dilacak.
Argumen `git add` ditambah `.` menunjukkan bahwa semua file & perubahan Anda akan dilacak.
1. **Tambahkan file tertentu untuk dilacak**
@ -110,7 +110,7 @@ Misalkan Anda memiliki folder lokal dengan proyek kode dan ingin mulai melacak k
git add [file or folder name]
```
Ini membantu kita menambahkan hanya file tertentu ke area staging ketika kita tidak ingin melakukan commit semua file sekaligus.
Ini membantu kita menambahkan hanya file tertentu ke area staging ketika kita tidak ingin commit semua file sekaligus.
1. **Batalkan staging semua file**
@ -134,9 +134,9 @@ Misalkan Anda memiliki folder lokal dengan proyek kode dan ingin mulai melacak k
git commit -m "first commit"
```
Ini melakukan commit semua file Anda, dengan pesan "first commit". Untuk pesan commit di masa depan, Anda ingin lebih deskriptif untuk menyampaikan jenis perubahan yang telah Anda buat.
Ini melakukan commit semua file Anda, dengan menambahkan pesan "first commit". Untuk pesan commit di masa depan, Anda akan ingin lebih deskriptif untuk menyampaikan jenis perubahan yang telah Anda buat.
1. **Hubungkan repo Git lokal Anda dengan GitHub**. Sebuah repo Git bagus di komputer Anda, tetapi pada suatu saat Anda ingin memiliki cadangan file Anda di suatu tempat dan juga mengundang orang lain untuk bekerja dengan Anda di repo Anda. Salah satu tempat yang bagus untuk melakukannya adalah GitHub. Ingat kita sudah membuat repo di GitHub, jadi satu-satunya yang perlu kita lakukan adalah menghubungkan repo Git lokal kita dengan GitHub. Perintah `git remote add` akan melakukannya. Ketik perintah berikut:
1. **Hubungkan repo Git lokal Anda dengan GitHub**. Sebuah repo Git bagus di komputer Anda, tetapi pada suatu saat Anda ingin memiliki cadangan file Anda di suatu tempat dan juga mengundang orang lain untuk bekerja dengan Anda di repo Anda. Salah satu tempat yang bagus untuk melakukannya adalah GitHub. Ingat kita sudah membuat repo di GitHub, jadi satu-satunya hal yang perlu kita lakukan adalah menghubungkan repo Git lokal kita dengan GitHub. Perintah `git remote add` akan melakukannya. Ketik perintah berikut:
> Catatan, sebelum Anda mengetik perintah, buka halaman repo GitHub Anda untuk menemukan URL repositori. Anda akan menggunakannya dalam perintah di bawah ini. Ganti ```https://github.com/username/repository_name.git``` dengan URL GitHub Anda.
@ -168,7 +168,7 @@ Misalkan Anda memiliki folder lokal dengan proyek kode dan ingin mulai melacak k
#### Pesan Commit
Baris subjek pesan commit Git yang bagus melengkapi kalimat berikut:
Baris subjek commit Git yang bagus melengkapi kalimat berikut:
Jika diterapkan, commit ini akan <baris subjek Anda di sini>
Untuk subjek, gunakan bentuk imperatif, waktu sekarang: "ubah" bukan "diubah" atau "mengubah".
@ -178,7 +178,7 @@ Seperti pada subjek, di badan (opsional) juga gunakan bentuk imperatif, waktu se
### Tugas: Berkolaborasi
Alasan utama untuk menyimpan sesuatu di GitHub adalah untuk memungkinkan kolaborasi dengan pengembang lain.
Alasan utama untuk menempatkan sesuatu di GitHub adalah untuk memungkinkan kolaborasi dengan pengembang lain.
## Bekerja pada proyek bersama orang lain
@ -195,24 +195,24 @@ Di repositori Anda, navigasikan ke `Insights > Community` untuk melihat bagaiman
- **Kode Etik**. Apakah Anda memiliki [Kode Etik](https://docs.github.com/articles/adding-a-code-of-conduct-to-your-project/)?
- **Lisensi**. Mungkin yang paling penting, apakah Anda memiliki [lisensi](https://docs.github.com/articles/adding-a-license-to-a-repository/)?
Semua sumber daya ini akan membantu onboarding anggota tim baru. Dan ini biasanya adalah hal-hal yang dilihat oleh kontributor baru sebelum bahkan melihat kode Anda, untuk mengetahui apakah proyek Anda adalah tempat yang tepat bagi mereka untuk menghabiskan waktu mereka.
Semua sumber daya ini akan bermanfaat untuk membantu anggota tim baru bergabung. Dan ini biasanya adalah hal-hal yang dilihat oleh kontributor baru sebelum bahkan melihat kode Anda, untuk mengetahui apakah proyek Anda adalah tempat yang tepat bagi mereka untuk menghabiskan waktu mereka.
✅ File README, meskipun memerlukan waktu untuk disiapkan, sering diabaikan oleh pemelihara yang sibuk. Bisakah Anda menemukan contoh README yang sangat deskriptif? Catatan: ada beberapa [alat untuk membantu membuat README yang baik](https://www.makeareadme.com/) yang mungkin ingin Anda coba.
### Tugas: Gabungkan beberapa kode
Dokumen kontribusi membantu orang berkontribusi pada proyek. Ini menjelaskan jenis kontribusi apa yang Anda cari dan bagaimana prosesnya bekerja. Kontributor perlu melalui serangkaian langkah untuk dapat berkontribusi pada repo Anda di GitHub:
Dokumen kontribusi membantu orang berkontribusi pada proyek. Dokumen ini menjelaskan jenis kontribusi apa yang Anda cari dan bagaimana prosesnya bekerja. Kontributor perlu melalui serangkaian langkah untuk dapat berkontribusi pada repo Anda di GitHub:
1. **Fork repo Anda**. Anda mungkin ingin orang-orang _fork_ proyek Anda. Forking berarti membuat replika repositori Anda di profil GitHub mereka.
1. **Clone**. Dari sana mereka akan meng-clone proyek ke komputer lokal mereka.
1. **Buat branch**. Anda ingin meminta mereka membuat _branch_ untuk pekerjaan mereka.
1. **Fokuskan perubahan mereka pada satu area**. Minta kontributor untuk memusatkan kontribusi mereka pada satu hal pada satu waktu - dengan cara itu kemungkinan Anda dapat _merge_ pekerjaan mereka lebih tinggi. Bayangkan mereka menulis perbaikan bug, menambahkan fitur baru, dan memperbarui beberapa tes - bagaimana jika Anda ingin, atau hanya dapat mengimplementasikan 2 dari 3, atau 1 dari 3 perubahan?
1. **Clone**. Dari sana, mereka akan meng-clone proyek ke komputer lokal mereka.
1. **Buat branch**. Anda akan ingin meminta mereka membuat _branch_ untuk pekerjaan mereka.
1. **Fokuskan perubahan mereka pada satu area**. Minta kontributor untuk memusatkan kontribusi mereka pada satu hal dalam satu waktu - dengan cara itu peluang Anda untuk _merge_ pekerjaan mereka lebih tinggi. Bayangkan mereka menulis perbaikan bug, menambahkan fitur baru, dan memperbarui beberapa tes - bagaimana jika Anda ingin, atau hanya dapat mengimplementasikan 2 dari 3, atau 1 dari 3 perubahan?
✅ Bayangkan situasi di mana branch sangat penting untuk menulis dan mengirimkan kode yang baik. Kasus penggunaan apa yang dapat Anda pikirkan?
> Catatan, jadilah perubahan yang ingin Anda lihat di dunia, dan buat branch untuk pekerjaan Anda sendiri juga. Setiap commit yang Anda buat akan dibuat di branch tempat Anda saat ini "checked out". Gunakan `git status` untuk melihat branch mana itu.
Mari kita melalui alur kerja kontributor. Anggaplah kontributor telah _fork_ dan _clone_ repo sehingga mereka memiliki repo Git yang siap untuk dikerjakan di komputer lokal mereka:
Mari kita melalui alur kerja kontributor. Anggaplah kontributor telah _forked_ dan _cloned_ repo sehingga mereka memiliki repo Git yang siap untuk dikerjakan di komputer lokal mereka:
1. **Buat branch**. Gunakan perintah `git branch` untuk membuat branch yang akan berisi perubahan yang ingin mereka kontribusikan:
@ -242,7 +242,7 @@ Mari kita melalui alur kerja kontributor. Anggaplah kontributor telah _fork_ dan
git pull
```
Pada titik ini Anda ingin memastikan bahwa setiap _conflict_, situasi di mana Git tidak dapat dengan mudah _combine_ perubahan, terjadi di branch kerja Anda. Oleh karena itu jalankan perintah berikut:
Pada titik ini Anda ingin memastikan bahwa setiap _conflict_, situasi di mana Git tidak dapat dengan mudah _combine_ perubahan, terjadi di branch kerja Anda. Oleh karena itu, jalankan perintah berikut:
```bash
git switch [branch_name]
@ -259,30 +259,30 @@ Mari kita melalui alur kerja kontributor. Anggaplah kontributor telah _fork_ dan
Perintah di atas membuat branch di repo forked Anda.
1. **Buka PR**. Selanjutnya, Anda ingin membuka PR. Anda melakukannya dengan menavigasi ke repo forked di GitHub. Anda akan melihat indikasi di GitHub di mana ia bertanya apakah Anda ingin membuat PR baru, Anda klik itu dan Anda akan dibawa ke antarmuka di mana Anda dapat mengubah judul pesan commit, memberikan deskripsi yang lebih sesuai. Sekarang pemelihara repo yang Anda forked akan melihat PR ini dan _semoga_ mereka menghargai dan _merge_ PR Anda. Anda sekarang adalah kontributor, yay :)
1. **Buka PR**. Selanjutnya, Anda ingin membuka PR. Anda melakukannya dengan menavigasi ke repo forked di GitHub. Anda akan melihat indikasi di GitHub di mana ia bertanya apakah Anda ingin membuat PR baru, Anda klik itu dan Anda dibawa ke antarmuka di mana Anda dapat mengubah judul pesan commit, memberikan deskripsi yang lebih sesuai. Sekarang pemelihara repo yang Anda forked akan melihat PR ini dan _semoga_ mereka akan menghargai dan _merge_ PR Anda. Anda sekarang adalah kontributor, yay :)
1. **Bersihkan**. Dianggap sebagai praktik yang baik untuk _membersihkan_ setelah Anda berhasil menggabungkan PR. Anda ingin membersihkan branch lokal Anda dan branch yang Anda dorong ke GitHub. Pertama, hapus secara lokal dengan perintah berikut:
1. **Bersihkan**. Dianggap sebagai praktik yang baik untuk _membersihkan_ setelah Anda berhasil menggabungkan PR. Anda ingin membersihkan branch lokal Anda dan branch yang Anda dorong ke GitHub. Pertama, hapus branch tersebut secara lokal dengan perintah berikut:
```bash
git branch -d [branch-name]
```
Pastikan Anda pergi ke halaman GitHub untuk repo yang telah di-*fork* dan hapus cabang jarak jauh yang baru saja Anda dorong ke sana.
`Pull request` mungkin terdengar seperti istilah yang aneh karena sebenarnya Anda ingin mendorong perubahan Anda ke proyek. Namun, pemelihara (pemilik proyek) atau tim inti perlu mempertimbangkan perubahan Anda sebelum menggabungkannya dengan cabang "utama" proyek, jadi sebenarnya Anda meminta keputusan perubahan dari pemelihara.
Pastikan Anda pergi ke halaman GitHub untuk repo forked dan hapus branch remote yang baru saja Anda dorong ke sana.
`Pull request` mungkin terdengar seperti istilah yang aneh karena sebenarnya Anda ingin mendorong perubahan Anda ke proyek. Namun, pemilik proyek (maintainer) atau tim inti perlu mempertimbangkan perubahan Anda sebelum menggabungkannya ke dalam cabang "main" proyek, jadi sebenarnya Anda meminta keputusan perubahan dari seorang maintainer.
Sebuah pull request adalah tempat untuk membandingkan dan mendiskusikan perbedaan yang diperkenalkan pada sebuah cabang dengan ulasan, komentar, pengujian terintegrasi, dan lainnya. Pull request yang baik mengikuti aturan yang kurang lebih sama dengan pesan commit. Anda dapat menambahkan referensi ke sebuah isu di pelacak isu, misalnya ketika pekerjaan Anda memperbaiki sebuah isu. Ini dilakukan dengan menggunakan `#` diikuti oleh nomor isu Anda. Contohnya `#97`.
Pull request adalah tempat untuk membandingkan dan mendiskusikan perbedaan yang diperkenalkan pada sebuah cabang dengan ulasan, komentar, pengujian terintegrasi, dan lainnya. Pull request yang baik mengikuti aturan yang kurang lebih sama seperti pesan commit. Anda dapat menambahkan referensi ke sebuah issue di pelacak issue, misalnya ketika pekerjaan Anda memperbaiki sebuah issue. Ini dilakukan dengan menggunakan `#` diikuti oleh nomor issue Anda. Contohnya `#97`.
🤞Semoga semua pemeriksaan lulus dan pemilik proyek menggabungkan perubahan Anda ke dalam proyek🤞
Perbarui cabang kerja lokal Anda saat ini dengan semua commit baru dari cabang jarak jauh yang sesuai di GitHub:
Perbarui cabang kerja lokal Anda saat ini dengan semua commit baru dari cabang remote yang sesuai di GitHub:
`git pull`
## Cara berkontribusi ke open source
Pertama, mari temukan sebuah repositori (atau **repo**) di GitHub yang menarik bagi Anda dan ingin Anda kontribusikan sebuah perubahan. Anda akan ingin menyalin isinya ke mesin Anda.
Pertama, mari temukan sebuah repositori (atau **repo**) di GitHub yang menarik bagi Anda dan ingin Anda kontribusikan perubahan. Anda perlu menyalin isinya ke komputer Anda.
✅ Cara yang baik untuk menemukan repo yang 'ramah pemula' adalah dengan [mencari berdasarkan tag 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
✅ Cara yang baik untuk menemukan repo yang 'ramah pemula' adalah dengan [mencari menggunakan tag 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
![Salin repo secara lokal](../../../../translated_images/clone_repo.5085c48d666ead57664f050d806e325d7f883be6838c821e08bc823ab7c66665.id.png)
@ -291,20 +291,20 @@ Ada beberapa cara untuk menyalin kode. Salah satu caranya adalah dengan "mengklo
Buka terminal Anda dan kloning repositori seperti ini:
`git clone https://github.com/ProjectURL`
Untuk bekerja pada proyek, pindah ke folder yang benar:
Untuk bekerja pada proyek, pindah ke folder yang sesuai:
`cd ProjectURL`
Anda juga dapat membuka seluruh proyek menggunakan [Codespaces](https://github.com/features/codespaces), editor kode terintegrasi / lingkungan pengembangan berbasis cloud dari GitHub, atau [GitHub Desktop](https://desktop.github.com/).
Anda juga dapat membuka seluruh proyek menggunakan [Codespaces](https://github.com/features/codespaces), editor kode terintegrasi / lingkungan pengembangan cloud dari GitHub, atau [GitHub Desktop](https://desktop.github.com/).
Terakhir, Anda dapat mengunduh kode dalam folder yang dikompresi (zip).
### Beberapa hal menarik lainnya tentang GitHub
Anda dapat memberi bintang, menonton, dan/atau "fork" repositori publik mana pun di GitHub. Anda dapat menemukan repositori yang Anda beri bintang di menu drop-down kanan atas. Ini seperti menandai halaman, tetapi untuk kode.
Anda dapat memberi bintang, mengikuti, dan/atau "fork" repositori publik apa pun di GitHub. Anda dapat menemukan repositori yang Anda beri bintang di menu drop-down kanan atas. Ini seperti menandai halaman, tetapi untuk kode.
Proyek memiliki pelacak isu, biasanya di GitHub pada tab "Issues" kecuali dinyatakan lain, tempat orang-orang mendiskusikan masalah yang terkait dengan proyek. Dan tab Pull Requests adalah tempat orang-orang mendiskusikan dan meninjau perubahan yang sedang berlangsung.
Proyek memiliki pelacak issue, biasanya di GitHub pada tab "Issues" kecuali dinyatakan lain, tempat orang-orang mendiskusikan masalah terkait proyek. Tab Pull Requests adalah tempat orang-orang mendiskusikan dan meninjau perubahan yang sedang berlangsung.
Proyek mungkin juga memiliki diskusi di forum, daftar email, atau saluran obrolan seperti Slack, Discord, atau IRC.
Proyek juga mungkin memiliki diskusi di forum, milis, atau saluran obrolan seperti Slack, Discord, atau IRC.
✅ Jelajahi repo GitHub baru Anda dan coba beberapa hal, seperti mengedit pengaturan, menambahkan informasi ke repo Anda, dan membuat proyek (seperti papan Kanban). Ada banyak hal yang bisa Anda lakukan!
@ -312,10 +312,10 @@ Proyek mungkin juga memiliki diskusi di forum, daftar email, atau saluran obrola
## 🚀 Tantangan
Berkolaborasi dengan seorang teman untuk bekerja pada kode satu sama lain. Buat proyek secara kolaboratif, fork kode, buat cabang, dan gabungkan perubahan.
Bekerja sama dengan seorang teman untuk mengerjakan kode satu sama lain. Buat proyek secara kolaboratif, fork kode, buat cabang, dan gabungkan perubahan.
## Kuis Pasca-Kuliah
[Kuis pasca-kuliah](https://ff-quizzes.netlify.app/web/quiz/4)
## Kuis Setelah Kuliah
[Kuis setelah kuliah](https://ff-quizzes.netlify.app/web/en/)
## Tinjauan & Belajar Mandiri
@ -323,7 +323,7 @@ Baca lebih lanjut tentang [berkontribusi pada perangkat lunak open source](https
[Git cheatsheet](https://training.github.com/downloads/github-git-cheat-sheet/).
Berlatih, berlatih, berlatih. GitHub memiliki jalur pembelajaran yang hebat yang tersedia melalui [skills.github.com](https://skills.github.com):
Latihan, latihan, latihan. GitHub memiliki jalur pembelajaran yang hebat yang tersedia melalui [skills.github.com](https://skills.github.com):
- [Minggu Pertama di GitHub](https://skills.github.com/#first-week-on-github)
@ -336,4 +336,4 @@ Selesaikan [kursus Minggu Pertama di GitHub](https://skills.github.com/#first-we
---
**Penafian**:
Dokumen ini telah diterjemahkan menggunakan layanan penerjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Meskipun kami berusaha untuk memberikan hasil yang akurat, harap diingat bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang otoritatif. Untuk informasi yang bersifat kritis, disarankan menggunakan jasa penerjemahan manusia profesional. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari penggunaan terjemahan ini.
Dokumen ini telah diterjemahkan menggunakan layanan penerjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Meskipun kami berusaha untuk memberikan hasil yang akurat, harap diingat bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang otoritatif. Untuk informasi yang bersifat kritis, disarankan menggunakan jasa penerjemahan profesional oleh manusia. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari penggunaan terjemahan ini.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save