Kode 2 Informasjonsteknologi 2 (LK20) kap. 1-4

Page 1

Kode

Eirik Vågeskar

Hossein Rostamzadeh

Markus Johansen Sørem Brede Yabo Sherling Kristensen

Informasjonsteknologi 2

Studiespesialiserende programfag vg2/vg3

BOKMÅL

2

© CAPPELEN DAMM AS, Oslo 2022

ISBN: 978-82-02-73999-7

2.utgave

1.opplag 2022

Tekniske tegninger: Terje Sundby/Keops

Omslagsdesign: Anders Bergesen / Superultraplus Designstudio Grafisk formgiving: Kristine Steen / 07 Media

Forlagsredaktør: Henning Vinjusveen Myhrehagen Sats: Jannicke Pedersen / Type-it AS, Trondheim Trykk og innbinding: Livonia Print SiA, Latvia 2022

Kode 2 følger læreplanen (LK20) i informasjonsteknologi 2 programfag i studieforberedende utdanningsprogram. Materialet i denne publikasjonen er omfattet av åndsverklovens bestemmelser. Uten særskilt avtale med Cappelen Damm AS er enhver eksemplarfremstilling og tilgjengeliggjøring bare tillatt i den utstrekning det er hjemlet i lov eller tillatt gjennom avtale med Kopinor, interesseorgan for rettighetshavere til åndsverk. Utnyttelse i strid med lov eller avtale kan medføre erstatningsansvar og inndragning, og kan straffes med bøter eller fengsel.

www.cdu.no www.kode.cdu.no

INNHOLD

1 Programmering med Svelte

1.1 Kode med Svelte 7

1.2 Nettsider med tekstelementer 15

1.3 Variabler med tall 22

1.4 Variabler med strenger 27

1.5 Arrayer 30

1.6 Funksjoner 37

1.7 Valgsetninger 40

1.8 Objekter 45 Sammendrag 48 Oppgaver 51

2 Gjenbruk og testing

2.1 Gjenbruke variabler og funksjoner 71

2.2 Lage og gjenbruke komponenter 77

2.3 Lage interaktive komponenter 82

2.4 Teste et helt dataprogram 90

2.5 Feilsøking 95

2.6 Enhetstester 103

2.7 Vanlige problemer når du tester med tall 112 Sammendrag 119 Oppgaver 121

4 Objektorientert programmering

4.1 Klasser og objekter 160 4.2 Metoder 164

4.3 Bruksområder for klasser og metoder 174 4.4 Arv 182

4.5 Objektorientert modellering 199 Sammendrag 206 Oppgaver 208

5 Lagre og visualisere data

5.1 Lagring 218 5.2 JSON 223

5.3 Datavisualisering 227 5.4 Sikring av data 241 Sammendrag 246 Oppgaver 247

6 Jobbe med IT-prosjekter

3 Brukervennlighet

3.1 Hva er brukervennlighet? 136

3.2 Hvem lager gode brukeropplevelser? 139

3.3 Hvordan lage en god brukeropplevelse? 141

3.4 Mål for brukskvalitet 147

3.5 Ekspertevaluering 150 Sammendrag 156 Oppgaver 157

6.1 Produkter og prosjekter 253 6.2 Utviklingsmetoder 256 6.3 Scrum 259 6.4 Oppgavetavler 264 6.5 En sprinthistorie 267 6.6 Versjoner og versjonskontroll 274 Sammendrag 279 Oppgaver 280

FORORD

Kode 2 er et læreverk som dekker den nye læreplanen i programfaget informasjonsteknologi 2 i studieforberedende utdanningsprogram (LK20). Læreverket består av denne læreboka og elevog lærernettstedet kode.cappelendamm.no. Læreboka består av seks kapitler. Nettstedet følger bokas kapittelinndeling og inneholder supplerende ressurser for elever og lærere.

KAPITTELOVERSIKT

I denne boka bruker vi HTML, CSS og JavaScript med rammeverket Svelte. Kapittel 1 handler om å lage interaktive nettsider og programmer. Kapittelet er ment som en repetisjon for elever og privatister som har tatt programfaget informasjonsteknologi 1, og som en innføring i programmering med Svelte for de som ikke har tatt informasjonsteknologi 1. I kapittel 2 viser vi deg hvordan du skriver gjenbrukbar kode i flere filer. Vi viser også hvordan du eksporterer og importerer kode mellom filer, hvordan du lager komponenter, og hvilke strategier du kan bruke når du tester koden du har skrevet. I kapittel 3 gir vi deg noen verktøy du kan bruke når du skal vurdere brukervennligheten til IT-produkter. Kapittel 4 handler om objektorientert programmering og objektorientert modellering med klassediagrammer. I kapittel 5 lærer du om standarder for lagring, utveksling og sikring av data og hvordan du kan visualisere datasett. I kapittel 6 får du et innblikk i hvordan det er å jobbe med IT-prosjekter. Vi ser på ulike utviklingsmetoder og går i dybden på den smidige utviklingsmetoden scrum.

SLIK ER HVERT KAPITTEL BYGGET OPP

Hvert kapittel begynner med en oversikt over de mest sentrale kompetansemålene for kapittelet. Ny teori forklares på en strukturert måte og ofte gjennom konkrete eksempler. Viktige ord er satt i halvfet første gangen de brukes, slik at det blir enkelt å finne dem igjen. Når kodetekst inngår i hovedteksten, bruker vi en egen skrifttype og farge, slik: kodetekst. Koden for en nettside eller et program vises i egne kodebokser der teksten er fargemarkert og tekstlinjene er nummererte.

I hvert kapittel finner du også margtekster, faktarammer, eksempler, ekstrastoff og diskusjonsspørsmål. Nedenfor ser du hvordan disse elementene ser ut. Sammendraget kommer etter teoridelen og oppsummerer de viktigste poengene i kapittelet.

Margtekster inneholder ordforklaringer eller utdyper hovedteksten.

Faktaramme

I slike faktarammer oppsummerer vi viktig stoff som du bør lære deg godt.

EKSEMPEL

I løpet av teksten finner du eksempler som belyser teorien, og nye kodeteknikker. Vi anbefaler at du tar deg god tid til å lese og forstå dem. Mange eksempler inneholder koden til en nettside eller et program.

I slike tilfeller kan det være lurt å skrive av koden selv. Vi legger eksempelkodene ut på elevnettstedet også, slik at du ikke alltid må skrive av kodene for å prøve dem ut og gjøre de endringene du måtte ønske.

DISKUTER

Her stiller vi spørsmål som du kan svare på sammen med medelever, eller som du kan reflektere over på egen hånd. Spørsmålene kan handle om noe du nettopp har lært, eller noe du er i ferd med å lese mer om. Det er lurt å tenke gjennom dem før du leser videre.

EKSTRASTOFF

Innimellom dukker det opp en slik ramme med ekstrastoff. Dette er interessant stoff som utdyper hovedteksten, og som du gjerne kan finne ut mer om, for eksempel på nettet. Det er ikke alltid slik at du skal jobbe videre med akkurat dette stoffet, men det vil gi deg litt mer innsikt og kanskje være til hjelp når du skal gjøre andre oppgaver.

OPPGAVER

Bakerst i hvert kapittel finner du en oppgavesamling. Når du løser disse oppgavene, får du god trening i programmering.

Vi markerer nivået på oppgavene med én til tre prikker. Oppgaver som er markert med én prikk, er de letteste oppgavene. De gir deg trening i grunnleggende programmeringsferdigheter og sentrale begreper og faktakunnskap. Oppgaver som er markert med to prikker, er middels vanskelige oppgaver. Her må du ofte bruke kunnskapen og ferdighetene du har tilegnet deg, til å løse oppgaver som handler om temaer du kanskje ikke kjenner fra før. De vanskeligste og mest tidkrevende oppgavene er markert med tre prikker. For å løse disse oppgavene må du ofte reflektere, finne ny kunnskap og tenke kritisk. Det er viktig å presisere at oppgaver markert med to eller tre prikker kan ha deloppgaver på lavere nivå.

Før du sier deg ferdig med en oppgave, er det lurt å lese oppgaveteksten én gang til og vurdere om du har gjort det oppgaven ber deg om. Det er også lurt å reflektere over alternative måter du kunne ha løst oppgaven på. Det er sjelden bare én måte å løse en oppgave på. Derfor kan det være fint å se hvordan andre har løst oppgavene. På bokas nettsted finner du løsningsforslag til et utvalg av oppgavene i boka. Vi håper oppgavene vekker kreativiteten din, og at du får lyst til å videreutvikle det du har laget.

TAKK!

Vi vil gjerne rette en stor takk til alle som har bidratt til boka. Spesielt vil vi takke redaktøren vår som har ledet oss trygt gjennom hele prosjektet. Takk også til lærere, elever og privatister som har gitt oss konstruktive tilbakemeldinger.

Vi håper at Kode 2 vil bidra til god læring og være et inspirerende hjelpemiddel i undervisningen. Lykke til med informasjonsteknologi 2!

Hilsen forfatterne

Programmering med Svelte 1

I dette kapittelet skal du jobbe for å nå disse målene:

> presentere og formatere ulike tekster på en nettside med HTML og CSS

> lagre data i variabler med enkeltverdier, arrayer og objekter

> bruke funksjoner, løkker og valgsetninger i programmering

> lage interaktive programmer med input-felt, glidere, knapper og avkryssingsbokser

I hverdagen er vi omgitt av datamaskiner. En datamaskin er, i bred forstand, en maskin som lagrer, behandler og deler data. Når vi i dagligspråket bruker ordet datamaskin, tenker vi ofte på en personlig datamaskin med tastatur og skjerm. Mobiltelefoner, smartklokker og spillkonsoller er også datamaskiner. Og biler, vaskemaskiner, droner og kaffetraktere inneholder datamaskiner.

Felles for alle datamaskiner er at de består av maskinvare (hardware på engelsk) og programvare (software på engelsk). Maskinvare er fysiske komponenter som blant annet prosessor og harddisk. Dersom datamaskinen skal vise informasjon på en skjerm, trenger den også et grafikkort. Programvare er et sett med instruksjoner som forteller datamaskinen hva den skal gjøre. Programvaren er lagret på datamaskinen, og den gjør at vi kan bruke datamaskinen til noe som er nyttig for oss.

Å programmere betyr å skrive en serie instruksjoner med et kodespråk som datamaskinen forstår. Et sett med slike stegvise instruksjoner som løser en oppgave, kalles for en algoritme. Med programmering kan vi for eksempel lage dynamiske nettsider og apper (applikasjoner, eller dataprogram). På dynamiske nettsider kan brukeren utføre handlinger (klikke, tappe, sveipe, taste inn tekst, osv.) som påvirker utseendet eller innholdet på nettsiden. Dette skiller dem fra statiske nettsider, som bare viser frem informasjon.

LÆRINGSMÅL

1.1 Kode med Svelte

På moderne nettsider ser vi forskjellige typer innhold. De fleste har statisk innhold som overskrifter, tekstavsnitt og lenker til andre nettsider, mens andre også har interaktive elementer som innskrivingsfelt og knapper vi kan klikke på. Hvis vi skal lage statiske nettsider, bruker vi som oftest markeringsspråket HTML (Hypertext Markup Language) og stilformateringsspråket CSS (Cascading Style Sheet). Hvis vi skal lage interaktive og dynamiske nettsider, må vi i tillegg bruke et programmeringsspråk. Det mest brukte programmeringsspråket for å lage interaktive nettsider heter JavaScript

Med HTML og CSS kan vi lage statiske nettsider som bare viser frem innhold. HTML definerer hvordan innholdet på nettsiden (overskrifter, avsnitt, lister) skal være strukturert, mens CSS styrer utseendet og plasseringen til innholdet. Programmeringsspråket JavaScript gjør det mulig å lage interaktive og dynamiske nettsider der brukeren kan utføre handlinger som påvirker utseendet eller innholdet på nettsiden.

7Programmering med Svelte

SVELTE

I de siste årene har det blitt vanligere for bedrifter å ta i bruk kodeverktøy som ofte kalles for web-rammeverk. I web-rammeverkene skriver utviklerne forenklet kode som oversettes til tradisjonell HTML-, CSS- og JavaScript-kode. Google og Facebook har for eksempel utviklet hver sine web-rammeverk, henholdsvis Angular og React, som de bruker til å lage nettsidene sine. I tillegg finnes det flere andre web-rammeverk som er åpen kildekode-prosjekter. Det betyr at kildekoden er allment tilgjengelig, ofte på et nettsted som heter Github.

I denne boka bruker vi web-rammeverket Svelte, som er et åpent kildekode-prosjekt. Med Svelte skriver vi programmer med forenklet HTML-, CSS- og JavaScript-kode. På Sveltes nettsted finnes det en editor der vi kan skrive koden vår og se resultatet av den umiddelbart. Du finner editoren på nettadressen https://svelte.dev/repl/

Du har sik kert allerede programmert en del tidligere i matematikk og naturfag. Programmeringsspråket som mange bruker i disse fagene, er Python. Selv om vi bruker et annet programmeringsspråk i denne boka, får du bruk for programmeringsferdighetene du har fra tidligere. For eksempel får du bruk for det du kan om å bruke for-løkker og if-else-setninger, men skrivemåten, eller syntaksen, er forskjellig. I IT-bransjen brukes mange forskjellige programmeringsspråk, så programvareutviklere, ofte bare kalt utviklere, må være i stand til å sette seg inn i og bruke ulike språk.

HTML

HTML står for Hypertext Markup Language. Vi kaller HTML for et markeringsspråk fordi vi strukturerer forskjellige deler av en tekst ved å markere dem med kodeord som vi kaller tagger. En tagg består av et kodeord omgitt av vinkelparenteser: < >. Vi markerer at en tekst skal være en overskrift slik:

<h1>Overskrift</h1>

Koden ovenfor utgjør det vi kaller et HTML-element av typen h1, som betyr overskrift (heading på engelsk) på nivå 1. De aller fleste HTML-elementene består av en starttagg, et tekstinnhold og en sluttagg. Skråstreken i sluttaggen markerer slutten av HTML-elementet. Resultatet av koden vil være teksten «Overskrift», som vises med en stor skriftstørrelse.

Et HTML-element består som regel av en starttagg, et tekstinnhold og en sluttagg.

Vi skal nå lage en enkel nettside med en overskrift og et tekstavsnitt. Vi skriver koden øverst på neste side rett inn i Svelte-editoren.

For å markere tekst som et avsnitt bruker vi p-elementet. Bokstaven p står for paragraph, som betyr «avsnitt». Bildet viser resultatet av koden slik det vises i feltet til høyre i editoren.

8 Kapittel 1

Vi har skrevet tre prikker … der det skal være et tekstinnhold.

1 <h1>Hei, elev!</h1>

2 <p>Lykke til med informasjonsteknologi 2.</p>

Når du skriver tekster i skriveprogrammer som Word eller Pages, kan du formatere teksten. Du kan for eksempel utheve deler av teksten med fet skrift eller ved å kursivere den Med HTML har vi mange av de samme mulighetene til å formatere teksten. I tabellen nedenfor finner du noen tagger vi kan bruke på tekster.

formatere tekst

<b><i>en

Tagger Forklaring

Står for <h1> </h1> <h2>…</h2> overskrift på nivå 1 overskrift på nivå 2 ... heading 1 heading 2 ... <p>…</p> avsnitt paragraph <b>…</b> fet skrift bold <i>…</i> kursiv skrift italic <u>…</u> understreking underline <mark>…</mark> markert tekst marked text <sub>…</sub> senket tekst subscript <sup>…</sup> hevet tekst superscript <br /> bryter linjen, har ingen sluttagg break <span>…</span> grupperer innhold uten linjeskift span <!-- … --> kommentar, innholdet blir ikke vist på nettsiden

mine favoritter: Rotterdam,

Legg merke til at teksten «en hel måned» er fet og kursivert. Der har vi et i-element inni et b-element. Vi kunne valgt motsatt rekkefølge (b-element inni et i-element) og oppnådd det samme resultatet. Vi hadde derimot fått en feilmelding dersom vi bare hadde endret rekkefølgen på sluttaggene:

<b><i>en hel måned</b></i>

9Programmering med Svelte
Å
I koden nedenfor viser vi hvordan vi kan formatere tekst. 1 <!-- Tittel med understreking --> 2 <h1><u>Sommerferien min</u></h1> 3 <p>I sommer reiste jeg og <b>vennene mine</b> rundt i Europa med tog. Vi kjøpte <mark><i>Interrail </i>-billetter</mark> så vi kunne reise hvor vi ville i
hel måned</i></b> </p> 4 <p>Av byene vi besøkte,<br /> var disse
Milano og Budapest.</p>
EKSEMPEL

CSS

Når vi sammenligner forskjellige nettsider, ser vi at overskriftene og tekstavsnittene har forskjellig utseende. For å angi hvordan innholdet på en nettside skal se ut, bruker vi stilformateringsspråket CSS, som står for Cascading Style Sheet. Med CSS-kode kan vi blant annet kontrollere størrelsen og fargen til teksten, hvilken skrifttype teksten skal ha, og hvor på siden innholdet skal vises.

Når vi ønsker å endre utseendet til innholdet i et HTML-element, kan vi skrive CSSkoden for dette i starttaggen. Informasjon vi legger inni tagger, kaller vi attributt. Vi endrer utseendet til innholdet med style-attributtet (style betyr «stil» på norsk). I koden nedenfor endrer vi fargen på overskriften og tekstavsnittet.

1 <h1 style="color: green;">Hei, elev!</h1>

2 <p style="color: blue;">Lykke til med informasjonsteknologi 2.</p>

Etter attributtnavnet style skriver vi altså = etterfulgt av anførselstegn "". Mellom anførselstegnene skriver vi navnet på den egenskapen vi ønsker å endre (color), etterfulgt av kolon (:) og verdien. Her valgte vi verdien green for overskriften og blue for tekstavsnittet. Etter verdien skriver vi semikolon (;).

10 Kapittel 1

Dersom vi ønsker å endre flere egenskaper, for eksempel skriftstørrelsen til p-elementet, legger vi til egenskapen og verdien slik: <p style="color: blue; font-size: 13px;>. Fordi standard skriftstørrelse til p-elementet er 16 piksler, ville denne koden ha resultert i en mindre skriftstørrelse.

Vi kan endre utseendet til innholdet ved å legge til attributtet style i HTMLelementets starttagg, slik:

<element style="egenskap1: verdi; egenskap2: verdi;">

Det finnes i praksis ingen begrensninger på for hvor mange egenskaper vi kan endre i style-attributtet, men dersom vi ønsker å endre mange egenskaper, er det mer oversiktlig å angi stilen i et eget style-element, slik vi har gjort i koden nedenfor.

1 <h1>Hei, elev!</h1>

2 <p>Lykke til med informasjonsteknologi 2.</p>

3 4 <style>

5 h1 {

6 color: green;

7 }

8 p { 9 color: blue;

10 font-size: 13px;

11 }

12 </style>

I style-elementet definerte vi først hvilke egenskaper h1-elementet skal ha. Når vi bruker navnet til et HTML-element i style-elementet slik, kaller vi det en selektor. Etter selektoren angir vi verdien til egenskapene vi ønsker å endre, mellom krøllparenteser. For å gjøre koden oversiktlig angir vi hver egenskap på en egen linje.

Ofte har vi flere avsnitt på en nettside og dermed flere p-elementer i koden. Når vi skriver CSS-koden i et style-element slik vi gjorde ovenfor, får alle avsnittene det samme utseendet.

Når vi skriver CSS-koden i et style-element, velger vi hvilket HTML-element vi skal endre utseendet på, med en selektor.

1 <style>

2 selektor {

3 egenskap1: verdi;

4 egenskap2: verdi;

5 }

6 /* Vi kommenterer CSS-kode slik */

7 </style>

11Programmering med Svelte

Farger

Til nå har vi brukt engelske fargenavn når vi har angitt verdien til fargeegenskapene i CSSkoden. Det finnes 140 farger med engelske navn som alle moderne nettlesere støtter. Blant de navngitte fargene finner vi fargene vi oftest omtaler i dagligtalen: black, grey, white, red, blue, green og yellow. I tillegg finnes det mange fargenavn du kanskje ikke har hørt om før, som aqua, DarkOrchid og FireBrick. Du finner enkelt frem til en fullstendig oversikt over fargenavnene ved å søke etter «CSS colors» på Internett.

Det finnes mange flere farger enn de 140 som har fått egne navn. To vanlige måter å angi farger på, er med RGB-verdier eller heksadesimale verdier.

RGB står for red, green og blue. Vi angir RGB-verdier med tre heltall mellom 0 og 255 som indikerer intensiteten til hver av primærfargene rødt, grønt og blått. For eksempel angir vi hvit farge med rgb(0, 0, 0) og svart med rgb(255, 255, 255). Verdien rgb(255, 0, 0) gir den samme fargen som når vi bruker navnet red.

Heksadesimale verdier tar utgangspunkt i det heksadesimale tallsystemet, som består av 16 ulike tegn. Titallssystemet som vi er vant til, har ti ulike tegn. Tegnene som brukes i det heksadesimale tallsystemet, er tallene 0–9 og bokstavene A–F. I titallssystemet svarer A til tallet 10 og F til tallet 16.

Når vi bruker heksadesimale verdier for farger, skriver vi koden på formen #RRGGBB. For eksempel gir #FF0000 og red samme farge. Denne måten å angi farge på har samme utgangspunkt som RGB ved at de to første sifrene for verdien for rødfargen, de to midterste for grønnfargen og de to siste angir blåfargen. Vi kan lage like mange forskjellige farger med heksadesimale verdier som med RGB-verdier. Fordelen er at skrivemåten er kortere.

JAVASCRIPT

Med JavaScript kan vi blant annet

• endre innholdet i HTML-elementer

• legge til nye HTML-elementer

• endre CSS-koden for HTML-elementer

• skape interaktivitet

• hente data fra en ekstern datakilde

• tegne og animere vektorgrafikk med SVG

• gjøre utregninger

12 Kapittel 1
EKSTRASTOFF

Vi skriver JavaScript-kode i et script-element. Når vi skriver koden vår i Svelte, kan vi velge om vi plasserer script-elementet før eller etter HTML- og CSS-koden. Etter hvert som vi går gjennom denne boka, kommer vi ofte til å definere variabler og funksjoner som vi skal bruke i HTML-koden, og da er det enklest å plassere script-elementet øverst i koden. Programmene våre blir lettere å lese når de følger en fast struktur.

Når vi lager interaktive nettsider eller programmer med Svelte, skriver vi JavaScript-koden først. Deretter følger HTML-koden. Dersom vi skriver CSSkoden i et style-element, plasserer vi dette til slutt. Strukturen til programmene våre ser da slik ut:

1 <script>

2 //JavaScript-kode

3 </script>

4 5 <h1>HTML-kode</h1>

6 7 <style>

8 /* CSS-kode */ 9 </style>

Vi tar utgangspunkt i koden på side 11. Nå vil vi lage en ny versjon der «elev» byttes ut med navnet til en elev. I stedet for å skrive et navn i HTML-koden kan vi definere en variabel som lagrer navnet. En variabel består av et navn og en verdi. Vi definerer en variabel i script-elementet ved å skrive let navn = "Ingvild". Vi kan lese dette som «La variabelen med navnet navn få verdien "Ingvild"». Datamaskinen lagrer da teksten som står mellom anførselstegnene. For at dette navnet skal dukke opp i overskriften på nettsiden, erstatter vi ordet «elev» med koden {navn}. Når vi setter et variabelnavn mellom to krøllparenteser i HTML-koden på denne måten, vises verdien som er lagret i variabelen.

1 <script>

2 let navn = "Ingvild"

3 </script>

4

5 <h1>Hei, {navn}!</h1>

6 <p>Lykke til med informasjonsteknologi 2.</p>

Nå vil vi gjøre det mulig for brukeren å skrive inn sitt eget navn, slik at nettsiden blir interaktiv. Vi lager et innskrivingsfelt, som ofte kalles et input-felt, med et input-element. I likhet med br-elementet har ikke input-elementet noen sluttagg. For at brukeren skal forstå hva hun eller han skal skrive inn, plasserer vi input-elementet inni

13Programmering med Svelte

En interaktiv nettside.

label-elementet (label betyr «merkelapp»). Da kan vi skrive en forklarende tekst foran eller bak input-feltet. Vi velger å skrive teksten «Navn:» foran input-feltet. Så skriver vi bind:value={navn} inni input-taggen, slik at det brukeren skriver inn i input-feltet lagres i variabelen navn. Dette attributtet binder inputverdien til variabelen som står mellom krøllparentesene.

1 <script>

2 let navn = "" //I utgangspunktet en tom variabel.

3 </script>

4

5 <label>Navn: <input bind:value={navn} /></label>

6

7 <h1>Hei, {navn}!</h1>

8 <p>Lykke til med informasjonsteknologi 2.</p>

EKSTRASTOFF

Variabler og variabelnavn

Du har kanskje hørt om ordet variabel i matematikk og andre realfag. I disse fagene utgjør en variabel et symbol, ofte en bokstav, som representerer en tallverdi. Tallverdien kan representere en målbar størrelse. Når vi skriver x = 2, betyr det at x er identisk med tallet 2. I programmering har variabler en litt annen betydning. Her er variabler en måte å lagre data på. Når vi definerer en variabel med kodeordet let etterfulgt av et variabelnavn, åpnes en ledig plass i datamaskinens minne. Navnet på variabelen blir en slags kobling som peker til den ledige plassen. Når vi skriver likhetstegnet og verdien vi vil lagre, sier vi at vi tilordner variabelen den verdien.

Programmeringsspråket oversetter verdien vi lagrer, til maskinkode, som er tall i totallssystemet: 0 og 1. Tallet 1 betyr at det går strøm gjennom en transistor i minnet, mens tallet 0 betyr at det ikke går strøm gjennom den. Hvert tall og tegn kan representeres som binære tall, altså serier av 0-er og 1-ere. Dataene vi lagrer, blir altså lagret fysisk, og det betyr at vi når som helst kan hente dem frem igjen.

Variabelnavnene vi bruker i JavaScript-programmering, må følge tre regler:

1.Navnet må begynne på en bokstav eller et understrekingstegn ( ).

2.Navnet kan ikke inneholde mellomrom.

3.Navnet kan bare bestå av bokstaver, tall og understrekingstegn.

Det er en stor fordel for deg selv og andre som leser koden din, at du gir variabelen et beskrivende navn. Navnet kan være ett enkelt ord, for eksempel poeng og fornavn, men av og til er det være lurt med navn som består av flere ord. Da kan vi skille mellom ordene med skrivestilen camelCase. Med camelCase lar vi den første bokstaven i hvert ord være stor, med unntak av det første ordet. Eksempler kan være tilfeldigTall eller nySpiller. Alternativt kan vi skille ordene fra hverandre med understrekingstegn, slik: tilfeldig_tall og ny_spiller

14 Kapittel 1

ABokstaven A med og uten seriffer.

Websikre skrifttyper

Arial Courier New Georgia Times New Roman Trebuchet MS Verdana

1.2 Nettsider med tekstelementer

I forrige delkapittel fikk du en kort innføring i hvordan vi kan vise tekst som overskrifter og avsnitt på en nettside og hvordan vi kan endre fargen og størrelsen på teksten. Når vi lager nettsider og programmer, er det viktig å tenke nøye gjennom hvordan teksten ser ut, og hvordan informasjonen fremstilles. Dersom skriftstørrelsen er for liten eller har en farge som ikke står i god nok kontrast til bakgrunnen, kan teksten bli unødvendig vanskelig å lese. Utseendet til en tekst kan altså avgjøre om teksten er lett eller vanskelig å lese. Det kan også påvirke hvordan andre oppfatter informasjonen vi fremstiller. I dette delkapittelet tar vi for oss flere vanlige måter å formatere og fremstille tekst på med CSS og HTML.

CSSEGENSKAPER FOR TEKST

CSS gir oss mange muligheter til å endre utseendet til tekst. Tabellen nedenfor oppsummerer de mest brukte CSS-egenskapene for tekst.

Egenskap Forklaring

Eksempel

color: darkorange; background-color bakgrunnsfarge background-color: blue;

color farge

marg over, til høyre, under eller til venstre for teksten

margin-bottom: 30px;

font-size størrelse font-size: 14px; font-family skrifttype font-family: verdana; line-height avstand mellom tekstlinjer line-height: 1.5; margin marg rundt teksten margin: 20px; margin-top margin-right margin-bottom margin-left

text-align horisontal plassering av tekst text-align: center; text-align: left; text-align: right;

ASKRIFTTYPER

Når du skriver tekster i skriveprogrammer som Word eller Pages, har du tilgang til mange forskjellige skrifttyper. Disse skrifttypene er lagret på datamaskinen din. Noen skrifttyper har seriffer, som er streker som står på tvers av de rette linjene i en bokstav, mens andre ikke har seriffer.

Med CSS angir vi skrifttypen som en verdi til egenskapen font-family. Når vi skal velge skrifttypen på en nettside, er det tryggest å bruke de skrifttypene som er installert på de mest kjente operativsystemene. Disse kalles websikre skrifttyper. Vi kan også velge en av de fem generiske skrifttypene: serif, sans-serif, monospace, cursive eller fantasy. Da velger nettleseren en skrifttype med egenskapen vi har angitt.

15Programmering med Svelte

Når vi angir skrifttype, er det vanlig å legge til en alternativ skrifttype i tilfelle datamaskinen til den som ser nettsiden, ikke har installert den samme skrifttypen som vi valgte. Noen velger å legge til en generisk type også, som et tredjevalg. Vi kan for eksempel angi skrifttypen slik:

font-family: "Courier New", "Times New Roman", serif;

I koden nedenfor har vi en tekst om fossekallen – Norges nasjonalfugl. Teksten er strukturert med en overskrift og to avsnitt. Med CSS-kode har vi valgt ulike verdier for skrifttype, skriftfarge, skriftstørrelse og linjeavstand.

1 <h1>Fossekall</h1>

2 <p>Fossekallen ble i 1963 kåret til Norges nasjonalfugl etter en lytteravstemning i NRK. </p>

3 <p>Fossekallen er en art i den monotypiske fossekallfamilien. Den blir 17–20 cm lang, har brunsvarte og hvite fjær og trives over det meste i landet vårt –også om vinteren.</p>

<style>

h1

6 color: rgb(207, 56, 30);

7 font-size: 20px;

8 font-family: "Georgia", "Times New roman", serif;

font-size: 12px;

font-family: "Arial", "Trebuchet MS", sans-serif;

line-height: 1.2;

</style>

16 Kapittel 1
4
5
{
9 } 10 p { 11
12
13
14 } 15
EKSEMPEL

Ta utgangspunkt i koden i forrige eksempel. Utforsk ulike verdier for skrifttypen, skriftfargen, skriftstørrelsen og linjeavstanden. Ta vare på to versjoner: én som du mener er lett å lese, og én som du mener er vanskelig å lese. Vis frem versjonene til andre i klassen. Er de enige i din oppfatning av hvilken versjon som er lettest å lese?

SELEKTOR MED ID

På større nettsider er det vanlig å ha mange HTML-elementer av samme type, for eksempel mange avsnitt, og dermed mange p-elementer. Dersom vi ønsker at ett enkelt p-element skal ha en annen stil, kan vi gi elementet en id ved å skrive id="idNavn" i starttaggen, der «idNavn» er et navn vi velger selv. I style-elementet refererer vi til det enkelte HTML-elementet med en hashtag-selektor, slik: #idNavn {…}. Mellom krøllparentesene angir vi verdier for de egenskapene vi ønsker å endre.

Vi legger inn en id i det ene HTML-elementet som stilen skal gjelde for:

1 <h1 id="idNavn"> </h1>

I style-elementet refererer vi til HTML-elementet med en hashtag-selektor, slik:

1 <style>

2 #idNavn {

3 egenskap: verdi;

4 } 5 </style>

SELEKTOR MED CLASS

Når vi ønsker at flere HTML-elementer skal ha de samme egenskapene, kan vi definere et klassenavn med attributtet class. Da skriver vi class="classNavn" i starttaggen til de HTML-elementene som skal ha de samme egenskapene. Navnet «classNavn» velger vi selv. I style-elementet refererer vi til HTML-elementene med det samme navnet med en punkt-selektor, slik: .classNavn {…}. Mellom krøllparentesene angir vi verdier for de egenskapene vi ønsker å endre.

Vi legger inn class i starttaggene til HTML-elementene som stilen skal gjelde for:

1 <h1 class="classNavn"> </h1>

2 <p class="classNavn"> </p>

I style-elementet refererer vi til HTML-elementene med en punkt-selektor, slik:

1 <style>

2 .classNavn {

3 egenskap: verdi; 4 } 5 </style>

DISKUTER
17Programmering med Svelte

EKSEMPEL

I koden nedenfor lager vi en mal for å vise frem en sangtekst. Vi ønsker at refrengene skal se litt annerledes ut enn versene. Det første p-elementet inneholder informasjon om låtskriveren og artisten. Dette elementet skal også skille seg litt ut.

1 <h1>Sangtittel</h1>

2 <p id="info">Låtskriver: Navn. Artist: Navn.</p>

3 <p class="vers">Verset går over<br /> </p>

4 <p class="refreng">Refrenget går også over<br /> linjer.</p>

5 <p class="vers">Verset går over<br /> </p>

6 <p class="refreng">Refrenget går også over <br /> linjer.</p>

7 <style>

h1 { color: rgb(0, 140, 80); text-align: center; }

#info { text-align: center; font-size: small; line-height: 0.1; }

.vers { color: maroon; }

.refreng { color: darkblue; margin-left: 15px; }

</style>

LENKER

De to første bokstavene i HTML står for Hypertext. Hypertekst er et annet ord for hyperlenke, som vi ofte bare kaller lenke. En lenke har en kobling til en annen del av en nettside eller til et annet nettsted. Når vi klikker på en lenke, vises innholdet eller nettsiden som lenken er koblet til, i nettleseren. Det var faktisk ønsket om å koble sammen tekster på forskjellige nettsider, som var bakgrunnen for at Internett ble oppfunnet.

Vi setter inn en lenke i HTML-koden med a-elementet. Vi skriver teksten vi ønsker at lenken skal vises med, mellom start- og sluttaggen. Deretter skriver vi inn URL-adressen til nettsiden vi ønsker å koble, som verdien til et attributt som heter href

<a href="URL-adresse">Klikkbar tekst</a>

18 Kapittel 1

Når du har klikket på en lenke, har du kanskje lagt merke til at nettsiden noen ganger lastes inn i den samme fanen, mens den andre ganger lastes inn i en ny fane. Standarden er at en lenke skal lastes inn i den samme fanen. Dersom vi ønsker at nettsiden skal lastes inn i en ny fane når noen klikker på lenken, kan vi legge til attributtet target med verdien _blank.

EKSEMPEL

I koden nedenfor har vi satt inn en lenke til nettsiden med URLadressen https://www.interrail.eu/en. Lenken vises med blå tekst som standard, og når vi holder musepekeren over lenken, vises understrekingen. Når vi klikker på lenken, åpnes nettsiden i en ny fane fordi vi har satt verdien til target-egenskapen til _blank

1 <p>I sommer reiste jeg og vennene mine rundt i Europa med tog. Vi kjøpte <a href="https://www.interrail.eu/en" target="_blank">Interrail</a>-billetter så vi kunne reise hvor vi ville i en hel måned.</p>

<ul> = unordered list = unummerert liste

<ol> = ordered list = nummerert liste <li> = list item = listepunkt

LISTER

Vi har to valg når vi vil skrive HTML-kode for lister. Listen kan være en unummerert liste med kulepunkt eller en nummerert liste med tall. Vi bruker ul-elementet når vi vil ha en unummerert liste, og ol-elementet når vi vil ha en nummerert liste. For hvert punkt på listen bruker vi taggene <li>…</li>.

En unummerert liste

1 <ul>

2 <li>Tekst</li>

3 <li>Tekst</li>

4 <li>Tekst</li>

4 </ul>

EKSEMPEL

I koden nedenfor har vi valgt å presentere tre byer i en unummerert liste.

1 <p>Av byene vi besøkte, var disse mine favoritter:</p>

2 <ul>

3 <li>Rotterdam</li>

4 <li>Milano</li>

5 <li>Budapest</li>

6 </ul>

Dersom vi ønsker andre punkttyper eller nummereringsmåter, kan vi endre dette med CSS-egenskapen list-style-type. Vi kan bytte ut kulepunktene med sirkler eller kvadrater ved å sette verdien til circle eller square. I stedet for en nummerert liste med tall kan vi ha en liste med store eller små romertall eller store eller små bokstaver. Da setter vi verdien til lower-roman, upper-roman, lower-alpha eller upper-alpha

En nummerert liste

1 <ol>

2 <li>Tekst</li>

3 <li>Tekst</li>

4 <li>Tekst</li>

5 </ol>

Dersom vi endrer ul-elementet til ol-elementet, får vi en nummerert liste.

Her har vi satt inn koden style="list-style-type: lower-roman;" i starttaggen til ol-elementet.

20 Kapittel 1

TABELLER

Når vi skal presentere data på en systematisk og oversiktlig måte, er det lurt å bruke en tabell. Tabeller består av rader og kolonner, og ofte har de en egen tittelrad som forklarer innholdet i hver kolonne.

Akkurat som med lister trenger vi flere tagger for å lage en tabell i HTML. Tabellen nedenfor forklarer taggene vi trenger.

TaggBruk Forklaring Står for <table><table>…</table> tabell table <tr><tr>…</tr> rad table row <td><td>…</td> innhold i en celletable data <th><th>…</th> overskrift table head

I koden nedenfor finner du HTML-koden som trengs for å lage en tabell med tre rader og to kolonner. Vi trenger <table>-taggen for å opprette selve tabellen. Med <tr>-taggen lager vi en ny rad i tabellen. For å lage flere kolonner skriver vi like mange <td>-tagger som antallet kolonner vi vil ha. I den første raden bruker vi <th>-taggen slik at teksten i tittelraden blir midtstilt og fet.

1 <table>

2 <tr>

3 <th>Tittel kolonne A</th>

4 <th>Tittel kolonne B</th>

5 </tr>

6 <tr>

7 <td>Innhold 1A</td>

8 <td>Innhold 1B</td>

9 </tr>

10 <tr>

11 <td>Innhold 2A</td>

12 <td>Innhold 2B</td>

13 </tr>

14 </table>

Resultatet av koden viser et enkelt tabelloppsett uten kantlinjer. Tabeller blir mer leservennlige med kantlinjer og bakgrunnsfarger. Koden nedenfor viser hvordan vi kan bruke CSS til å få til nettopp dette ved å velge verdier for egenskapene

background-color og border. For border velger vi at kantlinjene til th og td skal være 1 piksel tykke, heltrukne (solid) og svarte. Vi gjør ingen endringer i HTML-koden nå.

1 <style>

2 th {

3 border: 1px solid black;

4 background-color: yellow;

5 }

6 td {

7 border: 1px solid black;

8 background-color: lightcyan;

9 }

10 </style>

21Programmering med Svelte

Vi legger først merke til at det ble et mellomrom mellom kantlinjene. Det kan vi fjerne med table-egenskapen border-collapse, som vi gir verdien collapse, slik: table { border-collapse: collapse; }

Vi legger også merke til at tekstinnholdet står nærme kantlinjene. Vi velger å legge til mer luft rundt teksten med padding-egenskapen med koden padding:5px 10px; både for th og td. Da får vi 5 piksler med luft over og under teksten og 10 piksler luft til venstre og høyre for teksten. Bildet nedenfor viser sluttresultatet for tabellen vår.

1.3 Variabler med tall

Når vi programmerer, er vi avhengige av å hente inn og lagre data for å kunne hente dem frem igjen senere, slik vi gjorde avslutningsvis i delkapittel 1.1. Da lagret programmet vårt en tekst som en bruker selv skrev inn. Teksten ble lagret i en variabel i script-elementet før den ble vist frem på nettsiden. Vi kan gjøre det samme for tallverdier. Da vi definerte variabelen med tekst, skrev vi anførselstegn rundt teksten vi ville lagre. Når vi definerer en tallvariabel, bruker vi ikke anførselstegn.

Vi definerer en tallvariabel slik: let heltall = 5

Dersom tallet er et desimaltall, må vi bruke punktum som desimalskilletegn: let desimaltall = 5.8

Datatypen til tall er number.

I koden nedenfor har vi lagret to tall i hver sine variabler i script-elementet. Vi viser frem de lagrede tallverdiene ved å skrive variabelnavnene mellom to krøllparenteser i HTML-koden.

1 <script>

2 let a = 66.7

3 let b = 33.3

4 </script>

5 <p>De lagrede tallene er {a} og {b}.</p>

22 Kapittel 1

Vi kan også bruke datamaskinen til å gjøre beregninger med tallene. Dersom vi bare er ute etter å vise summen av tallene, kan vi skrive regnestykket med krøllparenteser rundt i HTML-delen.

1 <script>

2 let a = 66.7

3 let b = 33.3

4 </script>

5 <p>{a} + {b} = {a+b}</p>

6 <p>{a} / {b} = {a/b}</p>

Dersom vi ønsker å bruke svarene på et regnestykke videre, må vi definere en ny variabel. Vi kan bruke de eksisterende variablene til å definere den nye variabelen, slik: let c = a + b. Datamaskinen regner ut svaret på regnestykket for så lagre verdien til variabelen.

ENDRE VERDIEN TIL EN VARIABEL

La variabelen tall ha verdien 2. Dersom vi for eksempel ønsker å øke verdien til tall med 8, kan vi skrive tall = tall + 8. En mer kortfattet skrivemåte er tall += 8. Det finnes tilsvarende skrivemåter for de andre regneartene:

OperatorEksempelForklaring

+= tall += 2 øker verdien med 2

-= tall –= 2 minker verdien med 2

*= tall *= 2 ganger verdien med 2

/= tall /= 2 deler verdien på 2

++ tall++ øker verdien med 1 tall-- minker verdien med 1

REAKTIVE VARIABLER

Les koden nedenfor. Hvilke tall tror du vil vises på nettsiden?

1 <script>

let a

let

let

Når datamaskinen leser koden i script-elementet, starter den øverst og leser linje for linje nedover. Først lagres tallet 6 i variabel a, deretter lagres tallet 3 i variabel b. Ineste linje regner datamaskinen ut at summen av a + b er 9, og lagrer denne verdien i variabel c. Til slutt lagrer datamaskinen tallet 7 i variabel a. Da glemmer datamaskinen den gamle verdien til a. Når datamaskinen leser HTML-delen av koden, har den allerede lest gjennom script-elementet. Det som vises på nettsiden, er dermed: 7 + 3 = 9. Variabelen c har med andre ord ikke blitt oppdatert etter at a fikk en ny verdi.

23Programmering med Svelte
2
= 6 3
b = 3 4
c = a + b 5 a = 7 6 </script> 7 <p>{a} + {b} = {c}</p>

I Svelte kan vi bruke reaktive variabler som automatisk oppdaterer seg når én eller flere av variablene som de er utledet fra, endrer seg. Vi definerer at en variabel skal være reaktiv ved å skrive $: foran variabelnavnet i stedet for kodeordet let.

1 <script>

2 let a = 6 3 let b = 3

4 $:c = a + b

a = 7

</script>

<p>{a} + {b} = {c}</p>

Når vi nå har definert c som en reaktiv variabel, vil teksten 7 + 3 = 10 vises på nettsiden.

INPUTFELT FOR TALL

I delkapittel 1.1 laget vi et input-felt for tekst ved å bruke taggen <input />. Vi la til koden bind:value={variabelnavn} for å binde den inntastede verdien til en variabel.

Måten vi oppretter et input-felt for tall på, er nesten helt lik. Standard datatype for input-elementet er string, som er datatypen til tekst. Når input-feltet skal ta imot data av en annen type, må datatypen spesifiseres med attributtet type

Vi oppretter et input-felt for tall med koden <input type="number" />.

EKSEMPEL

Vi skal lage et interaktivt program der en bruker kan taste inn lengden og bredden til et rektangulært rom. Programmet skal regne ut og vise hvor stort gulvarealet til rommet er. Lengden og bredden skal oppgis i centimeter, mens arealet skal oppgis i kvadratmeter.

Vi har valgt å presentere gulvarealet inni et div-element med brun bakgrunnsfarge. I div-elementets starttagg velger vi at egenskapen width skal bestemmes ut fra lengden til rommet, og at egenskapen height skal bestemmes ut fra bredden til rommet.

Størrelsen på rektangelet endres etter hvilke verdier brukeren legger inn i input-feltene for lengde og bredde.

24 Kapittel 1
5
6
7
1 <script> 2 let lengde = 100 3 let bredde = 80 4 $: areal = lengde*bredde/10000 5 </script> 6 7 <label>Lengde: <input type="number" bind:value={lengde}> cm </label> 8 <label>Bredde: <input type="number" bind:value={bredde}> cm </label> 9 <div style="width: {lengde}px; height: {bredde}px;"> 10 Gulvarealet er {areal} m<sup>2</sup> 11 </div> 12 13 <style> 14 input { width: 60px; } 15 div { 16 background-color: brown; 17 color: white; 18 text-align: center; 19 } 20 </style>

Sette skriftstørrelsen med en glider

Med en glider kan brukeren velge et tall i et intervall ved å klikke og dra i en bryter. Vi lager en glider ved å velge verdien "range" for type-attributtet i et input-element. Vi angir intervallet for tallverdiene som brukeren kan velge, med attributtene min og max Med bind:value binder vi den valgte tallverdien til en variabel.

På nettsiden nedenfor har vi laget en glider som styrer skriftstørrelsen til et p-element.

1 <script>

2 let skriftStr = 16

3 </script>

4

5 <label>

6 <input type="range" min="8" max="30" bind:value={skriftStr} />

7 Du har valgt skriftstørrelsen {skriftStr}.

8 </label>

9 <p style="font-size: {skriftStr}px; color: crimson;">

10 Dra i glideren for å endre skriftstørrelsen!

11 </p>

Skriftstørrelsen endres etter hvor i intervallet brukeren slipper glideren.

MATH

I JavaScript er det bygd inn mange matematiske konstanter og funksjoner. Vi får for eksempel tallverdien til når vi skriver koden Math.PI og tallverdien til eulertallet e når vi skriver Math.E. Funksjonen Math.sqrt(4) regner ut kvadratroten av 4. Itabellen nedenfor finner du noen av de vanligste matematiske funksjonene. Vi har tatt med tall i funksjonene for å demonstrere hvordan de virker.

Kode

Forklaring

Resultat

Math.log(10) den naturlige logaritmen til 10 (In10) ca. 2,302

Math.sqrt(9) kvadratroten av 9 ( 9 ) 3

Math.cbrt(27) kubikkroten av 27 ( 327 ) 3

Math.pow(2, 3) potensen 23 8

Math.abs(-20) absoluttverdien til –20 (absoluttverdifunksjonen gjengir tallet uten fortegn) 20

Math.round(19.6)

runder av 19,6 til nærmeste heltall 20 runder 19,9 ned, uavhengig av desimalene 19

Math.ceil(19.1) runder 19,1 opp, uavhengig av desimalene 20

Math.trunc(2.345) kutter desimalene til 2,345 2

Math.min(-2, 45, -10, 8) det minste tallet i en liste –10

Math.max(-2, 45, -10, 8) det største tallet i en liste 45

Math.random() gir et tilfeldig desimaltall mellom 0 og 1

25Programmering med Svelte
EKSEMPEL

Tilfeldige tall

Math-funksjonen Math.random() gir oss et tilfeldig desimaltall mellom 0 og 1. Vi kan sette sammen regnestykker og bruke andre Math-funksjoner for å lage tilfeldige desimaltall og heltall innenfor andre tallintervaller.

1 <p><b>Tilfeldig desimaltall mellom 0 og 1:</b>

{Math.random()} </p>

2 <p><b>Tilfeldig tall mellom 0 og 100:</b>

{Math.random()*100} </p>

3 <p><b>Tilfeldig tall mellom 1 og 6:</b>

{(Math.random()*5 + 1).toFixed(2)} </p>

4 <p><b>Tilfeldig heltall mellom 1 og 10:</b>

{Math.round(Math.random()*9 + 1)} </p>

Legg merke til at funksjonen toFixed(2) gir oss tallet med bare to desimaler.

TEGNSETT

Et tegnsett er et system for hvordan ulike tegn kan representeres digitalt som tall. Tegnsettet i en datamaskin avgjør hvordan ulike bokstaver, tall og andre tegn skal vises på skjermen. I dag bruker datamaskiner tegnsettet Unicode som standard. I Unicode har hvert tegn et eget nummer og blant annet en HTML-kode. Det gjør at vi enkelt kan søke opp koden for et tegn vi ikke finner på tastaturet, for eksempel matematiske symboler eller emojier, og bruke dem på en nettside.

Det er noen tegn vi ikke kan bruke i HTML-elementer, for eksempel tegnene < og >, fordi datamaskinen alltid tolker disse tegnene som en del av programkoden vår. Hvis

vi vil vise disse tegnene på en nettside, må vi skrive HTML-kodene &lt; og &gt; i stedet for å bruke tegnene direkte fra tastaturet.

I koden nedenfor bruker vi HTML-koden for forskjellige

26 Kapittel 1
EKSEMPEL
tegn for å vise tegnene på en nettside. Kommaene skiller de ulike tegnene. 1 <p><b>Greske bokstaver</b></p> 2 <p> &alpha; , &beta; , &pi; , &Pi; , &psi; , &lambda; , &theta; , &Sigma;</p> 3 4 <p><b>Emojier</b></p> 5 <p>Vi kan sette inn emojier direkte, slik:</p> 6 <p> </p> 7 <p>Eller skrive koden for dem, slik: </p> 8 <p> &#128512; , &#129392; , &#129395; , &#128568; , &#9989; , 9 &#128077; </p> 10 11 <p><b>Matematiske tegn</b></p> 12 <p> 25&deg; , &ne; , &lt; , &gt; , 2 &sdot; 2 , &#8734; , &hArr; , 13 &and; , &or; , &int; </p> EKSEMPEL

1.4 Variabler med strenger

Som vi har sett tidligere, kan vi lagre tekst i variabler. Datatypen til slike variabler heter string. Vi må skrive teksten vi vil lagre, mellom to anførselstegn "". Teksten mellom to anførselstegn omtales ofte som en tekststreng, eller bare streng.

Når vi definerer tekstvariabler, skriver vi teksten vi vil lagre, mellom to anførselstegn.

let tekstStreng = "alt vi skriver, blir lagret"

Alle tegnene mellom anførselstegnene blir lagret, inkludert eventuelle mellomrom.

Vi kan lagre alle mulige tegn i en tekstvariabel. Det gjelder også tall, for eksempel "25", men da lagrer vi bare tegnene 2 og 5. Da kan vi ikke uten videre bruke tallet i utregninger.

EKSEMPEL

Fargevelger

I koden nedenfor lager vi et input-felt der en bruker kan skrive inn et fargenavn for å endre fargen på teksten.

1 <script>

2 let farge = "black"

3 </script>

4 5 <label>

6 Skriv inn et fargenavn på engelsk: <br />

7 <input bind:value={farge} />

8 </label>

9 <p style="color: {farge};">

10 Prøv ut forskjellige farger!

11 </p>

SKJØTE SAMMEN TEKSTSTRENGER

I koden nedenfor har vi lagret forskjellige ord som vi også viser på en nettside.

<script>

let subjekt = "Lisa" let verbal = "gikk" let toOrd = "til skolen" let tekstTall = "7"

</script>

<p>Her vises de lagrede strengene:</p> <p>{subjekt} {verbal} {toOrd}. Hun er {tekstTall} år.</p>

27Programmering med Svelte

Når resultatet blir

at strengen

konvertert

Dersom vi ønsker å skjøte sammen tekstvariabler til en lengre tekststreng, gjør vi det med plusstegnet, slik:

subjekt + verbal + toOrd

Da får vi tekststrengen "Lisagikktil skolen". Dersom vi ønsker å legge til mellomrom mellom ordene Lisa, gikk og til, gjør vi det slik:

subjekt + " " + verbal + " " + toOrd

Vi kan lagre den skjøtede strengen i en variabel i script-elementet eller skrive hele uttrykket mellom to krøllparenteser i HTML-koden for å vise resultatet. Å skjøte sammen strenger med plusstegnet på denne måten kaller vi konkatenering

Plusstegnet skjøter sammen strenger.

"En " + "setning " + "blir til." Resultatet blir strengen

"En setning blir til."

KONVERTERE MELLOM STRING OG NUMBER

Dersom vi har lagret et tall som en streng i en variabel og ønsker å bruke tallverdien i beregninger, kan vi konvertere variabelen til datatypen number på flere måter. Vi kan blant annet bruke funksjonene Number() eller parseInt(). Da skriver vi variabelnavnet mellom parentesene. Det finnes også en funksjon som heter String() som konverterer en tallverdi til en streng. Vi viser hvordan disse funksjonene brukes, i koden nedenfor.

1 <script>

2 let tekstTall = "2"

3 let tallverdi = Number(tekstTall)

4 </script>

5 6 <p> tekstTall + tekstTall gir: {tekstTall + tekstTall}. </p>

7 <p> tallverdi + tallverdi gir: {tallverdi + tallverdi}. </p>

8 <p>

9 parseInt(tekstTall) + parseInt(tekstTall) gir:

10 {parseInt(tekstTall) + parseInt(tekstTall)}

11 </p>

12 <p>

String(tallverdi) + String(tallverdi) gir:

{String(tallverdi) + String(tallverdi)}</p>

Funksjonene Number() og parseInt() konverterer en streng med talltegn til en tallverdi.

Funksjonen String() konverterer en tallverdi til en streng.

28 Kapittel 1
13
14
4, vet vi
"2" har blitt
til tallverdien 2.

Dersom vi er usikre på datatypen til en variabel, kan vi bruke funksjonen typeof, som returnerer navnet på datatypen til en variabel. Dersom vi hadde skrevet {typeof tekstTall} i HTML-koden ovenfor, ville resultatet ha blitt string. {typeof tallverdi} ville ha gitt number.

STRINGMETODER

JavaScript har innebygde metoder, eller funksjoner, som vi kan bruke på tekststrenger. Vi kan for eksempel undersøke om en streng inneholder et spesifikt tegn eller kombinasjoner av tegn, gjøre alle bokstavene store eller små og bytte ut deler av strengen med noe annet.

Metoden toUpperCase() gjør alle små bokstaver i en streng store. For å bruke denne metoden skriver vi en tekststreng etterfulgt av punktum foran metodenavnet, slik: . Dersom strengen hadde vært lagret i en variabel med navnet kommentar, ville vi ha skrevet variabelnavnet etterfulgt av punktum og metodenavnet, slik: kommentar.toUpperCase().

Disse metodene endrer ikke den lagrede verdien i en variabel. De tar bare inn strengen som er lagret, og returnerer et resultat som kan vises. Dersom vi ønsker å bruke en metode for å endre en variabel, kan vi gjøre det slik:

1 <script>

2 let kommentar =

3 kommentar = kommentar.toUpperCase() //Gir kommentar ny verdi.

4 </script>

I koden nedenfor demonstrerer vi flere nyttige string-metoder.

1 <script>

2 let kommentar = "KjempeFint"

3 </script>

4 5 <ul>

6 <li>kommentar.toLowerCase() returnerer: {kommentar.toLowerCase()}</li>

7 <li>kommentar.length() returnerer antall tegn: {kommentar.length}</li>

8 <li>kommentar.charAt(0) viser den første bokstaven: {kommentar.charAt(0)}</li>

9 <li>kommentar.replace("Fint", "bra") gir: {kommentar.replace("Fint", "bra")}</li>

10 <li>kommentar.substring(6, 9) gir: {kommentar.substring(6, 9)}</li>

11 <li>kommentar.slice(1, 5) gir: {kommentar.slice(1, 5)}</li>

12 </ul>

DISKUTER

Studer koden ovenfor. Hva gjør hver av metodene? Definer en variabel med verdien " Det var en gang " og prøv ut disse kodene: substr(2, 2), substr(-4) og trim(). Hva gjør de?

29Programmering med Svelte

Metoden length() returnerer antallet verdier i arrayet.

1.5 Arrayer

Til nå har vi lagret enkeltverdier i variabler. En datamaskin kan håndtere store mengder data og gjøre mange beregninger og operasjoner fort. Med programmering kan vi dermed effektivisere arbeidsoppgaver som før tok lang tid.

Når vi ønsker å lagre mange dataverdier, er det tungvint å måtte opprette én variabel for hver dataverdi. Med et array kan vi lagre mange verdier i én og samme variabel. Vi oppretter et array ved å liste opp verdiene mellom to klammeparenteser. Vi skiller verdiene fra hverandre med kommategnet.

let venner = ["Bodil", "Max", "Trym", "Francesca", "Emma"]

Arrayet venner har fem verdier. Vi kan også si at arrayet består av fem elementer

Elementene i et array blir nummerert med indekser. Det første har indeks 0, det andre har indeks 1, osv., helt til det ikke finnes flere elementer.

Vi bruker variabelnavnet og en indeks for å hente frem en verdi fra arrayet. Dersom vi vil hente frem verdien "Trym", skriver vi venner[2]. Vi kan også endre en spesifikk verdi. Vi bytter ut verdien til det fjerde elementet i arrayet med navnet Monika ved å skrive venner[3]="Monika".

Vi definerer et array slik: let arraynavn = [verdi1, verdi2, verdi3, osv.]

Elementene er indeksert med et nummer. Første element har indeks 0, det andre har indeks 1, osv.

Vi henter frem en verdi fra arrayet med arrayets navn og elementets indeks, slik: arraynavn[indeks].

VISNING AV ARRAYINNHOLD

I koden nedenfor viser vi arrayet venner på en nettside.

1 <script>

2 let venner = ["Bodil", "Max", "Trym", "Francesca", "Emma"]

venner[3] = "Monika"

</script>

<p>Hele arrayet vises slik: {venner}</p>

<p>Den første verdien i arrayet er: {venner[0]}</p>

<p>Du har {venner.length} venner.</p>

30 Kapittel 1
3
4
5 6
7
8

Når vi skriver navnet til et array mellom to krøllparenteser i et HTML-element, vises alle verdiene i arrayet. Verdiene skilles bare med et komma. Denne visningen er ikke så lett å lese. Det finnes mange forskjellige metoder for arrayer, og ett av dem er join(), som gjør at vi kan velge andre skilletegn enn komma. Nedenfor viser vi noen alternative skilletegn.

1 <p>Bare mellomrom som skilletegn: <br /> {venner.join(" ")}</p>

2 <p>Mellomrom og bindestrek som skilletegn: <br /> {venner.join(" – ")}</p>

3 <p>Emoji som skilletegn: <br /> {venner.join(" ")}</p>

I Svelte kan vi vise frem én og én verdi fra et array med noe som kalles en each-blokk.

Vi skriver koden for en each-blokk slik:

1 <p>Her viser vi frem hver verdi med et p-element.</p>

2 {#each venner as venn}

3 <p> {venn} </p>

4 {/each}

Koden for en each-blokk starter med {#each} og avsluttes med {/each}. En eachblokk går gjennom et array og henter ut én og én verdi. Vi kan også si at each-blokken itererer over arrayet. Vi spesifiserer hvilket array each-blokken skal gå gjennom, etter #each. Da angir vi samtidig et midlertidig variabelnavn som each-blokken bruker for å referere til et element. Each-blokken fungerer som en løkke der koden gjentas flere ganger.

I kodesnutten ovenfor får den midlertidige variabelen venn først verdien til det første elementet i venner-arrayet. Så kjøres koden i blokken. Det opprettes et nytt p-element der verdien til venn vises. Deretter får venn verdien til det andre elementet i venner-arrayet, og et nytt p-element opprettes. Slik fortsetter det helt til each-blokken har vært innom alle elementene i arrayet.

31Programmering med Svelte

En each-blokk går gjennom elementene i et array og pakker ut verdiene én etter én i et HTML-element. Vi skriver koden for en each-blokk i HTML-delen slik:

1 {#each arraynavn as navn}

2 <!-- HTML-kode som skal gjentas for hver verdi i arrayet. -->

3 {/each}

Vise array-innholdet i en liste

I koden nedenfor har vi lagret et array med titlene til de sju Harry Potter-bøkene. Vi ønsker å bruke en each-blokk for å vise de fullstendige titlene i en punktliste.

1 <script>

2 let bøkene = [

3 "de vises stein",

4 "mysteriekammeret",

5 "fangen fra Azkaban",

6 "ildbegeret",

7 "føniksordenen",

9 "halvblodsprinsen",

10 "dødstalismanene"

12 ]

13 </script>

14

15 <h1>Harry Potter-bøkene</h1>

16 <ul>

17 {#each bøkene as bok}

18 <li>Harry Potter og {bok}</li>

19 {/each}

20 </ul>

FJERNE ELLER LEGGE TIL VERDIER

Tabellen nedenfor viser de viktigste array-metodene for å legge til eller fjerne verdier i et array. I motsetning til string-metodene endrer array-metodene det lagrede arrayet.

Array-metode

Forklaring

fjerner den siste verdien i arrayet shift() fjerner den første verdien i arrayet push(verdi)

pop()

legger til en ny verdi bakerst i arrayet unshift(verdi) legger til en ny verdi fremst i arrayet splice(indeks, antall)

fjerner et antall verdier fra og med en angitt indeks splice(indeks, antall, nyVerdi) fjerner et antall verdier fra og med en angitt indeks og legger til en ny verdi på plassen til den angitte indeksen

32 Kapittel 1
EKSEMPEL

Dersom vi vil slå sammen to arrayer til et nytt array, kan vi bruke en såkalt spread-operator. Skrivemåten for spread-operatoren er tre punktum ( ) foran variabelnavnet. For å slå sammen arrayene array1 og array2 bruker vi spread-operatoren slik:

let nyttArray = [...array1, ...array2]

Vi kan også bruke spread-operatoren for å legge elementer fra ett array inn i et annet array.

EKSEMPEL

Eksemplene i tabellen nedenfor tar utgangspunkt i følgende array:

tallene = [0, 1, 2, 3, 4, 5, 6]

Kode Arrayet endres til tallene.pop() [0, 1, 2, 3, 4, 5] tallene.shift() [1, 2, 3, 4, 5, 6] tallene.push(7) [0, 1, 2, 3, 4, 5, 6, 7] tallene.push(7, 8, 9) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] tallene.unshift(-1) [-1, 0, 1, 2, 3, 4, 5, 6] tallene.unshift(-3, -2, -1)[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6] tallene.splice(2,4) [0, 1, 6] tallene.splice(2,4, 33) [0, 1, 33, 6] tallene.splice(2,4, 33, 44)[0, 1, 33, 44, 6]

SORTERE ARRAYER

Hvis verdiene i et array er navnelister, resultatlister eller måledata, er det praktisk å kunne sortere verdiene. Arrayer med strenger kan sorteres i alfabetisk orden (A–Å) eller i omvendt alfabetisk orden (Å–A). Arrayer med tallverdier kan sorteres i stigende eller fallende rekkefølge. I tabellen nedenfor viser vi koden for de ulike sorteringsmulighetene.

Kode

Forklaring

sorterer et array med strenger i alfabetisk orden arraynavn.sort( (a, b) => a - b )

arraynavn.sort()

sorterer et array med tall i stigende rekkefølge arraynavn.sort( (a, b) => b - a )

sorterer et array med tall i minkende rekkefølge arraynavn.sort( (a, b) => a. localeCompare(b) )

sorterer et array med strenger i alfabetisk orden arraynavn.sort( (a, b) => b. localeCompare(a) )

sorterer et array med strenger i omvendt alfabetisk orden arraynavn.reverse() snur rekkefølgen på verdiene i et array

33Programmering med Svelte

Metoden sort() tar utgangspunkt tegnsettet Unicode. I Unicode har hvert tegn en tallverdi i det heksadesimale tallsystemet. Nedenfor ser du Unicode-koden med tilhørende tallverdier i titallssystemet for noen tegn vi finner på tastaturet.

Tall i titallssystemet Heksadesimalt tall Tegn på tastatur 48 30 1 49 31 2 65 41

66 42

90 5A

97 61

98

122 7A

Som vi ser i tabellen, har talltegnene lavere verdi enn bokstavene, og de store bokstavene har lavere verdi enn de små. Når vi sorterer arrayet

["alex", "2", "Berit", "Alex", "1"]

med sort, blir resultatet: ["1", "2", "Alex", "Berit", "alex"]

I tilfeller der noen strenger starter med store bokstaver og andre starter med små, kan vi heller bruke sort-metoden med localCompare, for den skiller ikke mellom store og små bokstaver. Når vi bruker metoden sort( (a, b) => a.localeCompare(b) ) på arrayet

["Ankel", "Lår", , "albue"]

får vi dette resultatet:

["albue", "Ankel", , "Lår"]

FORLØKKER

Med en for-løkke gjentas en kodesnutt et gitt antall ganger. Det er praktisk når vi ønsker å gjenta en bestemt beregning flere ganger med forskjellige verdier. Vi definerer en for-løkke i script-elementet slik:

1 <script>

2 for (argument1; argument2; argument3){

3 //Kode som skal gjentas.

4 }

5 </script>

34 Kapittel 1
A
B
Z
a
62 b
z

I argument1 definerer vi en tellevariabel, for eksempel: let i = 0. Denne variabelen defineres før for-løkken går gjennom koden for første gang. I argument3 forteller vi hva vi vil gjøre med tellevariabelen hver gang etter at koden mellom krøllparentesene har blitt kjørt. Ofte vil vi at variabelen i skal øke med 1. Da kan vi skrive i++. I argument2 definerer vi et vilkår for at koden skal fortsette. Hvis vi vil at koden mellom krøllparentesene skal kjøres ti ganger, skriver vi i<10. Hvis vi hadde valgt at tellevariabelen skulle starte med en annen verdi, for eksempel 1, måtte vi ha brukt i<11 som vilkår dersom koden skulle kjøres ti ganger.

Å fylle et array med verdier

Vi ønsker å fylle et array med femti tilfeldige heltall mellom 1 og 6 med en for-løkke. Vi ønsker også å beregne gjennomsnittsverdien av de femti tallene.

Vi starter med å opprette et tomt array som vi skal lagre tallene i, og variabelen sum. Deretter definerer vi for-løkken. Vi lar tellevariabelen i starte med verdien 0, og fordi vi vil ha femti verdier, setter vi vilkåret til å være i<50

Koden Math.round(Math.random()*5 + 1) gir et tilfeldig heltall mellom 1 og 6. Vi lagrer verdien i variabelen tall. For hver gang løkken kjøres, bruker vi push-metoden for å lagre verdien i arrayet. Vi øker verdien av sum med det tilfeldige tallet ved å skrive sum += tall.

tilfeldigeTall

i<50;

Math.round(Math.random()*5

DISKUTER

tallene

Hvordan kan vi finne medianverdien til tallene i arrayet? Og hvordan kunne vi ha funnet antall 1-ere, 2-ere osv.? Foreslå forskjellige måter å løse det på.

35Programmering med Svelte
1 <script> 2 let
= [] 3 let tall = 0 4 let sum = 0 5 6 for (let i = 0;
i++){ 7 tall =
+ 1) 8 tilfeldigeTall.push(tall) 9 sum += tall 10 } 11 </script> 12 13 <p> 14 De {tilfeldigeTall.length} tilfeldige
er: <br /> 15 {tilfeldigeTall.join(", ")} 16 </p> 17 <p>Gjennomsnittsverdien er {sum/tilfeldigeTall.length}.</p> EKSEMPEL

Å ITERERE OVER ET ARRAY MED FORLØKKE

I en navneliste kan navnene være oppgitt på formen Etternavn, Fornavn. Vi ser for oss at vi har et array med strenger der navnene er skrevet på denne måten. Nedenfor har vi laget et program med en for-løkke som itererer over arrayet og henter ut fornavnene. Vi presenterer navnene i en punktliste der navnene er sorterte i alfabetisk orden, med en each-blokk.

String-metoden split() deler en streng i to ved et angitt tegn. Metoden returnerer et array med to elementer. Koden "Etternavn, fornavn".split(" ") gir arrayet ["Etternavn,""Fornavn"]. Tegnene før mellomrommet ligger da i det første elementet, og tegnene etter mellomrommet ligger i det andre elementet. Dermed kan vi bruke split-metoden for å hente ut fornavnene.

1 <script>

2 let forfattere = [

3 "Ibsen, Henrik", "Collett, Camilla",

4 "Hamsun, Knut", "Holt, Anne",

5 "Ambjørnsen, Ingvar", "Hjorth, Vigdis"

6 ]

7 let fornavn = []

8 let navn = ""

10 for(let i=0; i<forfattere.length; i++) {

navn = forfattere[i].split(" ")

fornavn.push(navn[1])

fornavn.sort()

</script>

fornavn as forfatter}

36 Kapittel 1
9
11
12
13 } 14 15
16
17 18 <ul> 19 {#each
20 <li>{forfatter}</li> 21 {/each} 22 </ul>

1.6 Funksjoner

Når vi har lagret data, kan vi bearbeide dem slik at vi kan få ny informasjon som vi kan dra nytte av. Det er dette vi prøver å beherske og bli gode til når vi lærer oss programmering. Når vi lagrer tall, er vi som regel interessert i å bruke tallene i beregninger. Vi har også sett at vi kan behandle tekststrenger og arrayer med metoder. I dette delkapittelet skal vi lage våre egne funksjoner der vi selv bestemmer hvilken oppgave funksjonene skal løse.

En funksjon består av én eller flere linjer med kode. Koden kjøres bare når vi kaller på funksjonen. Det gjør at vi kan bruke funksjonen mange ganger, og vi bestemmer selv når vi vil at funksjonens kode skal kjøre.

En funksjon består av én eller flere linjer med kode. Vi definerer en funksjon i script-elementet på denne måten:

1 const funksjonsnavn = () => {

2 3 }

Nedenfor definerer vi en funksjon som øker verdien til variabelen tall med én:

1 <script>

2 let tall = 0

3 const økMedEn = () => {

4 tall++

5 }

6 </script>

7 <p>Tallet er {tall}.</p>

I koden har vi bare definert funksjonen. Når vi henter verdien til tall på nettsiden, vises verdien 0. Det er fordi koden til funksjonen ikke kjører før vi har kalt på funksjonen. I script-elementet kaller vi på funksjonen ved å skrive funksjonsnavnet etterfulgt av parenteser, slik vi har gjort i linje 6:

1 <script>

2 let tall = 0

3 const funksjonsnavn = () => {

4 tall++

5 }

6 økMedEn()

7 </script>

8 <p>Tallet er {tall}.</p>

KNAPPER

Fordi vi nå har kalt på funksjonen, har verdien til tallet økt med én.

På nettsider finner vi ofte knapper vi kan klikke på for å få noe til å skje. Da er knappen koblet til en funksjon som setter i gang det vi ønsker. Når vi klikker på knappen, kaller vi altså på funksjonen.

37Programmering med Svelte

Vi bruker HTML-elementet button til å lage knapper på en nettside. Teksten vi skriver mellom start- og sluttaggen, vises på knappen. I Svelte kobler vi en knapp til en funksjon med koden on:click={funksjonsnavn} i starttaggen til button-elementet. Ikoden nedenfor har vi lagt til en knapp som er koblet til funksjonen økMedEn.

1 <script>

2 let tall = 0

3 const økMedEn = () => {

4 tall++

5 }

6 </script>

7 <p>Tallet er {tall}.</p>

8 <button on:click={økMedEn}> Øk tallet med én </button>

Resultatet av to klikk på knappen.

Legg merke til at vi ikke skrev parenteser etter funksjonsnavnet i siste kodelinje. Dersom vi hadde skrevet økMedEn(), ville funksjonen ha blitt kalt på når nettsiden ble lastet inn, og ikke når vi klikker på knappen.

Fargemodus på nettside

I programmet nedenfor har vi laget to funksjoner som endrer tekstfargen og bakgrunnsfargen på en nettside. Funksjonene er koblet til hver sin knapp.

1 <script>

2 let tekstfarge = "black"

3 let bakgrunnsfarge = "white"

4

5 const lysModus = () => {

6 tekstfarge = "#FF3300"

7 bakgrunnsfarge = "beige"

}

9 const mørkModus = () => {

10 tekstfarge = "#009966"

bakgrunnsfarge = "#333333"

}

{tekstfarge}; background-color: {bakgrunnsfarge}; height: 100%">

on:click={lysModus} style="color: #FF3300; background-color: beige;">Lys</button>

on:click={mørkModus} style="color: #009966; background-color: #333333;" >Mørk</button>

går

blodet</i>

i

Ingvar Ambjørnsen)

annet.</p>

38 Kapittel 1
8
11
12
13 </script> 14 15 <div ="color:
16 <button
17 <button
18 19 <p>Alt går over. Eller mer presist: <br />Alt
over
noe
20 <p style="font-size: small; text-align: right;"> 21 – Elling (<i>Brødre i
av
22 </p> 23 </div> EKSEMPEL

FUNKSJONER MED PARAMETERE OG RETURVERDIER

Noen av funksjonene du har brukt tidligere, har tatt inn én eller flere verdier og returnert et svar. Når vi skriver Math.sqrt(25), sender vi tallet 25 inn i funksjonen. Da regner funksjonen ut kvadratroten av 25 og returnerer svaret 5. Vi kaller verdiene vi sender inn i en funksjon, for parametere.

Vi definerer en funksjon med parametere og returverdi slik:

1 const funksjonsnavn = (parameter1, parameter2) => {

2 //Parameterne fungerer som variabler inni funksjonen.

3 //Verdien vi skriver etter return, returneres.

4 return verdi

5 }

Parameterne får verdier når vi kaller på funksjonen. Disse verdiene kalles argumenter. Vi kaller på en funksjon med parametere slik: funksjonsnavn("Argument1", "Argument2")

EKSEMPEL

Funksjon med én parameter

Vi lager et program der en bruker kan angi verdien for fart målt i meter per sekund (m/s) i et input-felt. På skjermen vises farten i kilometer i timen (km/h) og miles per hour (mph).

1 <script>

2 let fart = 0

3

4

const tilKMH = (meterPrSek) => {

5 return meterPrSek*3.6

}

8 const tilMPH = (meterPrSek) => {

return meterPrSek/0.44704

}

</script>

<label>

Angi farten i m/s:

<input type="number" bind:value={fart} />

</label>

<p>

</p>

{fart} m/s tilsvarer {tilKMH(fart).toFixed(2)} km/h

og {tilMPH(fart).toFixed(2)} mph.

39Programmering med Svelte
6
7
9
10
11
12 13
14
15
16
17
18
19
20

Funksjon med to parametere

Vi lager et program der en bruker kan angi radiusen og høyden til en sylinder. På skjermen vises volumet til sylinderen.

1 <script>

2 let radius = 0

3 let høyde = 0

4

const volumSylinder = (r, h) => {

return Math.PI*r*r*h

}

8 </script>

9

10 <label>Radius: <input type="number" bind:value={radius} /> cm</label>

11 <label>Høyde: <input type="number" bind:value={høyde} /> cm</label>

12 <p>Volumet til sylinderen er {volumSylinder(radius, høyde).toFixed(2)} cm<sup>3</sup>.</p>

1.7 Valgsetninger

Har du noen gang fått feilmeldinger når du har skrevet inn feil brukernavn eller passord? Eller løst digitale oppgaver som gir deg en tilbakemelding om at du har svart riktig eller feil? Når vi skal skrive kode med slik funksjonalitet, må vi sammenligne data og skrive logiske tester, også kalt valgsetninger. Resultatet av en logisk test er enten verdien true eller false, sant eller usant. Disse verdiene kalles boolske verdier. Når vi lagrer en boolsk verdi i en variabel, for eksempel let sant = true, blir datatypen boolean.

Det er for eksempel sant at 5 er mindre enn 10, og det er usant at 7 er større enn 9. Vi kaller slike sammenlignende uttrykk for boolske uttrykk eller logiske tester.

Tabellen nedenfor gir en oversikt over operatorer vi kan bruke for å sammenligne to verdier.

OperatorForklaring Eksempel

== lik verdi 2 == "2" gir true

=== lik verdi og datatype 2 === "2" gir false

< mindre enn 5 < 10 gir true

<= mindre enn eller lik 5 <= 10 gir true

> større enn 5 > 1 gir true

>= større enn eller lik 5 >= 5 gir true

!= ikke lik 3 != 2 gir true

40 Kapittel 1
5
6
7
EKSEMPEL

EKSEMPEL

True eller false?

Vi skriver inn noen boolske uttrykk med tall og strenger og sjekker om vi får true eller false. Legg merke til at vi kan skrive regnestykker og bruke metoder på verdiene i slike sammenligninger. Datamaskinen finner da verdiene før den sammenligner dem.

1 <p> "Emma" == "emma" gir {"Emma" == "emma"}. </p>

2 <p> "Emma".toLowerCase() == "emma" gir {"Emma".toLowerCase() == "emma"}. </p>

3 <p> 10 === "10" gir {10 === "10"}. </p>

4 <p> 10 != "10" gir {10 != "10"}. </p>

5 <p> 8*5 &gt; 6*7 gir {10 < 3}. </p>

5 <p> 3/4 &lt;= 4/5 gir {3/4 <= 4/5} </p>

IF OG ELSE

Som du har sett, kan vi styre innholdet som vises på en nettside, etter input fra en bruker. Boolske variabler og sammenligninger gir oss flere muligheter. Da kan vi vise forskjellig innhold avhengig av inputverdier fra brukeren. Til det bruker vi if-setninger. Hvis (if) en betingelse blir oppfylt, altså hvis en test gir true, kjøres en bestemt kode. Dersom betingelsen ikke oppfylles, kan vi legge til et else-ledd, slik at en annen kode kjøres dersom testen blir false. I script-elementet skriver vi en if-else-setning slik:

1 if (test) {

2 //Hvis testen gir true, kjør denne koden.

3 } else {

4 //Hvis testen gir false, kjør denne koden.

5 }

Vi kan legge til flere betingelser med else-if-ledd.

1 if (test) {

2 //Hvis testen gir true, kjør denne koden.

3 } else if (ny test){

4 //Hvis den nye testen gir true, kjør denne koden.

5 } else {

6 //Hvis begge testene gir false, kjør denne koden.

7 }

I HTML-delen av koden skriver vi if-else-setninger slik:

1 {#if test }

2 <p> Innhold som vises dersom testen gir true. </p>

3 {:else}

4 <p> Innhold som vises dersom testen gir false. </p>

5 {/if}

41Programmering med Svelte

EKSEMPEL

Myntkast

De to sidene av en mynt heter kron og mynt. I koden nedenfor etterligner vi et myntkast.

Først trekker vi et tilfeldig tall med Math.random()-funksjonen. Deretter bruker vi en if-else-setning til å avgjøre om vi fikk kron eller mynt. Hvis det tilfeldige tallet er mindre enn 0,5, blir det kron. Ellers blir det mynt.

1 <script>

2 let tilfeldigTall = Math.random()

3 let side = ""

4

5 if (tilfeldigTall < 0.5){

6 side = "kron"

7 } else {

8 side = "mynt"

9 }

10 </script>

11

12 <p>Det tilfeldige tallet er: {tilfeldigTall.toFixed(2)} </p>

13 <p>Myntkastet gav: {side} </p>

EKSEMPEL

I programmet nedenfor kan en bruker angi alderen sin. Når brukeren klikker på OK-knappen, kjøres testene i funksjonen beskrivAlder. Funksjonen sjekker først om alderen er lavere enn 13. Hvis testen gir false, går den videre og sjekker om alderen er lavere enn 20. Hvis den andre testen gir false, sjekker funksjonen til slutt om alderen er lavere enn 80. I hvert av tilfellene lages det en beskrivelse av alderen til personen.

<script> let alder let beskrivelse = ""

const beskrivAlder = () => {

if (alder < 13) { beskrivelse = "Du er et barn."

} else if (alder < 20) { beskrivelse = "Du er tenåring."

} else if (alder < 80){ beskrivelse = "Du er voksen."

} else { beskrivelse = "Wow, du har levd mange år!"

} }

</script>

<label>

Din alder:

<input type="number" bind:value={alder} />

<button on:click={beskrivAlder}> OK </button>

</label>

<p>{beskrivelse}</p>

42 Kapittel 1

Logiske operatorer: Og: && Eller: ||

AVKRYSSINGSBOKSER

Vi kan lage avkryssingsbokser ved å velge typen checkbox i et input-element. En avkryssingsboks kan kobles til en boolsk variabel med attributtet bind:checked.

Når boksen er krysset av, får variabelen verdien true, og når boksen ikke er krysset av, får variabelen verdien false.

1 <script>

2 let kryssetAv = false

3 </script>

4

5 <label>

6 <input type="checkbox" bind:checked={kryssetAv} />

6 Verdi: {kryssetAv}

7 </label>

LOGISKE OPERATORER

Av og til ønsker vi å utføre to eller flere tester samtidig. For eksempel må vi ha både en gyldig billett og et gyldig pass når vi går om bord på et langdistansefly.

Vi har to logiske operatorer: && kalles og (and på engelsk), og || kalles eller (or på engelsk). Vi skriver én test på hver side av operatorene, for eksempel: test1 && test2. Med og-operatoren får vi true bare hvis begge testene gir true. Med eller-operatoren får vi true hvis minst én av testene gir true.

EKSEMPEL

Inn- og utlogging

I koden nedenfor har vi laget et enkelt inn- og utloggingssystem. For å logge seg inn må brukeren taste inn riktig brukernavn og PIN-kode og klikke på en innloggingsknapp.

HTML-delen styrer hvilket innhold som skal vises, basert på verdien til variabelen innlogget. Denne variabelen har i utgangspunktet verdien false. Da vises en enkel innloggingsside med input-felter for brukernavnet og PIN-koden og en innloggingsknapp. I script-elementet har vi definert funksjonen loggInn, som sjekker om de inntastede verdiene for brukernavn og PIN-kode er riktige, ved hjelp av en if-else-setning. Hvis inntastet brukernavn og PIN-kode er riktig, settes innlogget til true. Da vises innholdet som står mellom {#if innhold} og {:else}. Hvis brukernavnet eller PIN-koden er feil, vises en feilmelding.

Når brukeren er innlogget, vises blant annet en utloggingsknapp. Når brukeren klikker på denne, kjøres funksjonen loggUt, som setter innlogget til false. Da vises innloggingssiden igjen.

1 <script>

2 let brukernavn = "mjau"

3 let pinkode = "1234"

4 let inntastetNavn = ""

5 let inntastetPin = ""

6 let innlogget = false

7 let tilbakemelding = ""

const sjekkPin = () => {

10 if (brukernavn == inntastetNavn && pinkode == inntastetPin){

11 innlogget = true

43Programmering med Svelte
8 9

12 } else {

13

tilbakemelding = "Feil brukernavn eller PIN-kode. Prøv igjen!"

14 inntastetNavn = "" //Nullstiller inntastet verdi.

15 inntastetPin = "" //Nullstiller inntastet verdi.

16 }

17 }

18 const loggUt = () => {

19 innlogget = false

20 inntastetNavn = ""

21 inntastetPin = ""

22 }

23 </script>

24

25 {#if innlogget}

26 <h1>Velkommen!</h1>

27 <p>Du er innlogget.</p>

28 <button on:click={loggUt}>Logg ut </button>

29 {:else}

30 <label>

31 Brukernavn: <input bind:value={inntastetNavn} /><br />

32 PIN-kode: <input bind:value={inntastetPin} />

33 </label>

34 <button on:click={loggInn}> Logg inn</button>

35 <p>{tilbakemelding}</p>

36 {/if}

FLERE SANNE OG USANNE VERDIER

I JavaScript kan vi bruke andre verdier enn true og false i tester. Noen ganger må vi forhåndsdefinere variabler som skal få andre verdier basert på inntastinger fra brukeren eller ved innlasting av data fra en fil. Da bruker vi for eksempel tallet null eller en tom streng som startverdier. I if-tester anser JavaScript tallet 0 og en tom streng for å være usanne. Alle strenger som ikke er tomme, og alle tall utenom 0, anses som sanne verdier. Dermed kan vi bruke if-tester for å sjekke om de forhåndsdefinerte variablene har fått andre verdier.

44 Kapittel 1

EKSTRASTOFF

Heltallsdivisjon og modulo-operatoren

Et delestykke med to heltall kalles heltallsdivisjon. En heltallsdivisjon gir to heltall som svar: kvotient og rest. For eksempel gir 5/2 kvotienten 2 og 1 i rest. Modulo er en operator som finner resten i heltallsdivisjonen. Vi skriver modulo-operatoren med prosenttegnet mellom to tall. Når vi skriver 10 % 2 (les «ti modulo 2»), finner datamaskinen ut at delestykket 10/2 gir null i rest fordi 2 går opp i 10 et heltallig antall ganger. 9 % 2 gir resultatet 1. Det er fordi 2·4 = 8, og da mangler vi 1 for å få 9.

Modulo-operatoren kan for eksempel brukes i tester for å sjekke om et tall er et partall. Da skriver vi tall % 2 == 0. Testen gir true dersom verdien til tall er et partall.

1.8 Objekter

Når vi har sammensatte data om noe, kan vi lagre verdiene i et objekt. Vi kan for eksempel lagre et objekt som beskriver en person med fornavn, etternavn, alder og øyenfarge. Vi bruker heller objekter enn arrayer når vi skal lagre forskjellige typer data om det samme. Vi definerer et objekt slik:

1 let person = {

2 fornavn : "Meera",

3 etternavn : "Singh",

4 alder : 24,

5 øyenfarge : "brun"

6 }

Objekter består av nøkkel–verdi-par mellom krøllparenteser. En nøkkel er navnet til en verdi. Vi skriver kolon mellom nøkkelen og verdien, og vi skiller nøkkel–verdiparene fra hverandre med komma. Vi henter ut enkeltverdier fra et objekt ved å skrive variabelnavnet og nøkkelnavnet med punktum mellom: person.fornavn. Med samme notasjon kan vi endre en verdi ved å skrive person.alder = 25

Et objekt består av nøkkel–verdi-par. Vi definerer et objekt med to nøkkel–verdi-par slik:

1 let objektnavn = {

2 nøkkel1 : verdi1,

3 nøkkel2 : verdi2

4 }

Vi henter ut en verdi ved å skrive variabelnavnet til objektet etterfulgt av punktum og navnet på nøkkelen: objektnavn.nøkkel1. Vi endrer verdien til nøkkelen når vi i tillegg skriver = nyVerdi.

Datatypen til objekter er object.

45Programmering med Svelte

I koden nedenfor har vi definert tre objekter som representerer varer i frukt- og grøntavdelingen i en matbutikk. I hvert objekt lagrer vi navnet, opprinnelseslandet, prisen og enheten til prisen. Vi viser frem innholdet til objektene i en liste.

1 <script>

2 let appelsin = {

3 navn : "appelsiner",

4 pris : 34.90,

5 prisEnhet : "kr per kg",

6 land : "Spania"

7 }

8 let agurk = {

9 navn : "agurk",

10 pris : 19.90,

11 prisEnhet : "kr per stk.",

12 land : "Norge"

13 }

14 let lime = {

15 navn : "lime",

16 pris : 37.00,

17 prisEnhet : "kr per kg",

18 land : "Mexico"

19 }

20

21 </script>

22

23 <p><b>Tilbud på frukt og grønt!</b></p>

24 <ul>

25

<li>{appelsin.navn}: {appelsin.pris} {appelsin.prisEnhet}</li>

26 <li>{agurk.navn}: {agurk.pris} {agurk.prisEnhet}</li>

27 <li>{lime.navn}: {lime.pris} {lime.prisEnhet}</li>

28 </ul>

46 Kapittel 1
EKSEMPEL

Objekter i array

På samme måte som vi fyller tall og strenger i et array, kan vi fylle et array med objekter. Da slipper vi å definere én variabel for hvert objekt.

I tabellen nedenfor finner du antall innbyggere i alderen 0–17 år i en kommune fra 2015 til 2020.

Årstall 201520162017201820192020

Antall 398323997640320406834065340780

I koden nedenfor har vi lagret den samme informasjonen som objekter i et array. I HTML-delen presenterer vi dataene i en tabell med en each-blokk.

1 <script>

2 let innbyggertall = [

3 {år : "2015", antall : 39832},

4 {år : "2016", antall : 39976},

5 {år : "2017", antall : 40320},

6 {år : "2018", antall : 40683},

7 {år : "2019", antall : 40653},

8 {år : "2020", antall : 40780}

9 ]

10 </script>

11

12 <table>

13 <tr>

14 <th>Årstall</th>

15 <th>Innbyggertall (0–17 år)</th>

16 </tr>

17 {#each innbyggertall as tall} 18 <tr>

19 <td>{tall.år}</td>

20 <td>{tall.antall}</td>

21 </tr>

22 {/each}

23 </table>

24

25 <style>

26 table {

27 border-collapse: collapse;

}

td {

30

border:1px solid black;

31 padding: 5px 10px;

32 text-align: center;

}

th {

35

border: 1px solid black;

36 background-color: #CCFFCC;

padding: 5px 10px;

}

</style>

47Programmering med Svelte
28
29
33
34
37
38
39
EKSEMPEL

SAMMENDRAG

> HTML (Hypertext Markup Language) er et markeringsspråk. Et HTML-element består som regel av en starttagg, et innhold og en sluttagg. Noen av de vanligste HTML-elementene er h1 (overskrift på nivå 1), h2 (overskrift på nivå 2), p (avsnitt), b (fet), i (kursiv), u (understreking), mark (markert tekst), sub (senket tekst), sup (hevet tekst), br (bryter linjen), og span (grupperer innhold uten linjeskift).

> Taggene <ul>…</ul> gir en unummerert liste. Taggene <ol>…</ol> gir en nummerert liste. Vi bruker taggene <li>…</li> på de enkelte punktene.

> CSS (Cascading Style Sheet) styrer utseendet til HTML-elementene. Vi kan angi stiler i starttagger med style-attributtet slik: style="egenskap1: verdi; egenskap2: verdi;". Eksempler på egenskaper er color, backgroundcolor, font-size, font-family, line-height, margin og text-align. Vi kan også skrive CSS-kode i style-elementet, mellom taggene <style> … </style>. Da bruker vi selektorer, selektorer med id eller selektorer med class.

> JavaScript er det mest brukte programmeringsspråket for interaktive og dynamiske nettsider. Vi skriver JavaScript-kode i script-elementet.

> En variabel lagrer én eller flere verdier med et navn vi velger selv. Vi definerer en variabel med kodeordet let slik: let variabelnavn = verdi

> Tallvariabler har datatypen number. JavaScript har innebygde matematiske funksjoner. Du finner en oversikt over disse på side 25.

> En tekststreng er tegn skrevet mellom to anførselstegn (""). En variabel som lagrer en tekststreng, har datatypen string.

> JavaScript har innebygde metoder (funksjoner) som kan brukes på strenger. Du finner en oversikt over disse nedenfor.

Metode

.toLowerCase()

Forklaring

gjør alle bokstavene små

.toUpperCase() gjør alle bokstavene små

.length()

.charAt(0)

returnerer antall tegn i strengen

viser det første tegnet i strengen. .charAt(1) gir det andre tegnet, osv.

.replace("gammel verdi, "ny verdi") bytter ut tegnene "gammel verdi" med "ny verdi"

.substring(0, 2)

.trim()

gir tegnene fra og med tegnet på plass 0 til tegnet på plass 2. Tegnet på plass 2 returneres ikke.

fjerner mellomrom på starten og slutten av en streng

48 Kapittel 1

> Vi lager input-felt med input-elementet. Inputverdien kan kobles til en variabel. <input bind:value={variabelnavn} /> gir et innskrivingsfelt for tekststrenger. <input type="number" bind:value={variabelnavn} /> gir et innskrivingsfelt for tall. <input type="range" bind:value={variabelnavn} /> gir en glider. <input type="checkbox" bind:checked={variabelnavn} /> gir en avkryssingsboks.

> Vi kan lagre mange verdier i et array. I arrayer lister vi opp verdiene mellom to klammeparenteser [], og vi skiller verdiene fra hverandre med komma. Vi definerer et array slik: let arraynavn = [verdi 1, verdi 2, verdi 3]. Verdiene blir nummerert med indekser, der den første verdien har indeks 0, den andre indeks 1, osv. Vi henter ut en verdi ved å bruke arraynavnet og en indeks slik: arraynavn[indeks].

> Tabellen nedenfor viser noen array-metoder.

Array-metode

Forklaring pop() fjerner den siste verdien i arrayet shift() fjerner den første verdien i arrayet push(verdi) legger til en ny verdi bakerst i arrayet unshift(verdi) legger til en ny verdi fremst i arrayet splice(indeks, antall) fjerner et antall verdier fra og med en angitt indeks splice(indeks, antall, nyVerdi) fjerner et antall verdier fra og med en angitt indeks og legger til en ny verdi på plassen til den angitte indeksen

> En each-blokk går gjennom elementene i et array og pakker ut verdiene én etter én i et HTML-element. Vi skriver koden for en each-blokk i HTML-delen slik:

1 {#each arraynavn as navn}

2 <!-- HTML-kode som skal gjentas for hver verdi i arrayet. -->

3 {/each}

> Med en for-løkke gjentas en kodesnutt et gitt antall ganger. Det er praktisk når vi ønsker å gjenta en bestemt beregning flere ganger med forskjellige verdier eller behandle verdiene i et array. Vi definerer en for-løkke som gjentas ti ganger i script-elementet, slik:

1 <script>

2 for (let i=0; i<10; i++){

3 //Kode som skal gjentas.

4 }

5 </script>

49Programmering med Svelte

> Vi definerer en funksjon med parametere og returverdi slik:

1 const funksjonsnavn = (parameter1, parameter2) => {

2 //Parameterne fungerer som variabler inni funksjonen.

3 //Verdien vi skriver etter return, returneres.

4 return verdi

5 }

> Parameterne får verdier når vi kaller på funksjonen. Disse verdiene kalles argumenter. Vi kaller på en funksjon med parametere slik: funksjonsnavn("Argument1", "Argument2")

> Vi oppretter en knapp som kaller på en funksjon, med koden <button on:click={funsksjonsnavn}> Knappetekst </button>.

> Boolske variabler har enten verdien true eller verdien false. Et boolsk uttrykk, eller en logisk test, er en sammenligning av to verdier. Slike sammenligninger kan være å sjekke om en verdi er større enn, mindre enn, lik eller ikke lik en annen verdi.

> Vi skriver en if-else-setning i script-elementet slik:

1 if (test) {

2 //Hvis testen gir true, kjør denne koden.

3 } else if (ny test){

4 //Hvis den nye testen gir true, kjør denne koden.

5 } else {

6 //Hvis begge testene gir false, kjør denne koden.

7 }

> Vi skriver en if-else-setning i HTML-koden slik:

1 {#if test }

2 <p> Innhold som vises dersom testen gir true. </p>

3 {:else}

4 <p> Innhold som vises dersom testen gir false. </p>

5 {/if}

> Et objekt består av nøkkel–verdi-par. Vi definerer et objekt med to nøkkelverdi-par slik:

1 let objektnavn = {

2 nøkkel1 : verdi1,

3 nøkkel2 : verdi2

4 }

> Vi henter ut en verdi ved å skrive variabelnavnet til objektet etterfulgt av punktum og navnet på nøkkelen: objektnavn.nøkkel1.

50 Kapittel 1

Oppgaver

1.1 Kode med Svelte

1.01

a) Hva er forskjellen mellom en statisk nettside og en dynamisk nettside?

b) Gå til to nettsider du besøker ofte. Finn eksempler på statisk og dynamisk innhold.

c) Hva heter kodespråkene vi bruker for å lage nettsider?

1.02

a) Hva består et HTML-element av?

b) Gi noen eksempler på HTML-elementer. Forklar hva elementene gjør.

c) Skriv en kort tekst om sommerferien din og vis den på en nettside. Teksten skal ha en overskrift og to avsnitt. Bruk fet skrift på stedsnavn.

1.03

a) Hva er et attributt?

b) Hvilket attributt kan vi bruke for å endre skriftfarge?

1.04

a) Finn en nyhetsartikkel og legg den inn på en nettside. Bruk HTML-elementene h1, h2 og p.

b) Prøv også ut de andre HTML-elementene i tabellen på side 9.

1.05

a) Gjør rede for to måter vi kan skrive CSS-kode på.

b) Bruk CSS til å endre utseendet til teksten i nyhetsartikkelen i oppgave 1.04.

1.06

Med h1-elementet lager vi en overskrift på nivå 1, og med h2-elementet lager vi en overskrift på nivå 2. Vi kan også lage overskrifter på flere nivåer ved å skrive et annet tall bak bokstaven h.

a) Lag sju overskrifter på forskjellige nivåer.

b) Søk på Internett og finn en oversikt over de navngitte fargene vi kan bruke på nettsider.

c) Gi overskriftene i oppgave a forskjellige farger.

1.07

a) Hvordan kan vi angi farger med RGB-verdier?

b) Finn RGB-verdiene for fargene du brukte på overskriftene i oppgave 1.06 c. Erstatt de navngitte fargene med RGB-verdiene.

c) Finn RGB-verdier for noen gråfarger.

d) Hvor mange forskjellige farger kan vi lage med RGB-verdier?

e) Lag en overskrift med h1-elementet. Prøv ut forskjellige RGB-verdier.

51Programmering med Svelte

1.08

a) Hvilke tegn bruker vi i det heksadesimale tallsystemet?

b) Skriv tallene fra 0 til 30 i det heksadesimale tallsystemet.

c) Hvor mange forskjellige farger kan vi lage når vi bruker heksadesimale verdier på formen #RRGGBB?

d) Erstatt RGB-verdiene i oppgave 1.07 b med de tilsvarende heksadesimale verdiene.

1.09

a) Skriv følgende kode i Svelte-editoren:

1 <h1>JavaScript</h1>

2 <p>Når vi lager <u>interaktive nettsider</u>, bruker vi programmeringsspråket <b>JavaScript</b>. JavaScript-kode skrives i hovedsak mellom taggene <code> &lt;script&gt;</code> og <code> &lt;/script&gt;</code>. Vi oppretter en tekstvariabel i script-elementet, slik: </p>

3 <p><code>let variabelNavn = "tekst"</code> </p>

b) Hva gjør code-elementet?

c) Skriv CSS-kode der du endrer fargen til HTML-elementene vi brukte i koden i oppgave a. Gi også code-elementet en mindre skriftstørrelse.

1.10

a) Lagre fornavnet og etternavnet ditt i to variabler i et script-element. Vis hele navnet på en nettside.

b) Lag to input-felter: ett for fornavn og ett for etternavn. Når brukeren skriver inn fornavnet og etternavnet sitt, skal teksten vises som en overskrift under inputfeltene.

c) Legg til CSS-koden nedenfor. Endre verdiene og forklar hvordan egenskapene endrer utseendet til input-feltene.

1 <style>

2 input {

3 width: 150px;

4 height: 40px;

5 margin: 5px;

6 padding: 20px;

7 font-size: 20px;

8 border: 2px dashed pink;

9 border-radius: 10px; 10 }

11 12 </style>

d) Søk etter verdier vi kan bruke for egenskapen border (se linje 8), på Internett og prøv dem ut.

52 Kapittel 1

1.2 Nettsider med tekstelementer

1.11

a) Hvordan kan vi endre skrifttypen til HTML-elementer?

b) Hva betyr det at en skrifttype er websikker?

c) Gi noen eksempler på websikre skrifttyper med og uten seriffer.

d) Hvilke fem generiske skrifttyper har vi?

e) Skriv fem setninger i fem p-elementer. Bruk de fem generiske skrifttypene.

f) Hvorfor bør vi angi to–tre skrifttyper når vi angir verdien for CSS-egenskapen font-family?

1.12

a) Hvordan kan vi formatere tekst med id og class?

b) Når bør vi bruke id, og når bør vi bruke class?

c) Gå tilbake til nyhetsartikkelen du brukte i oppgave 1.04. Gi det første avsnittet, altså ingressen til artikkelen, en egen stil.

1.13

Finn teksten til en låt du liker. Kopier teksten, og vis den på en nettside. Nettsiden skal ha en overskrift som er identisk med tittelen på låten. Artistnavnet og navnet til låtskriverne skal stå under overskriften. Versene og refrengene skal ha forskjellig formatering. Bruk id og class.

1.14

a) Lag en punktliste med lenker til fem nettsider du besøker ofte. Når brukeren klikker på en av lenkene, skal nettsiden åpnes i en ny fane.

b) Gi lenkene forskjellige skriftfarger.

c) Endre punktene i listen fra kulepunkter til kvadratiske punkter.

1.15

a) Lag en nummerert liste med favorittmatrettene dine.

b) Endre listenummereringen til store romertall.

1.16

Lag en tabell med fornavnet og etternavnet til alle i IT-klassen din. Hver rad med navn i tabellen skal nummereres.

1.17

Lag en tabell som viser timeplanen din.

53Oppgaver

1.3 Variabler med tall

1.18

Les koden og avgjør hvilke verdier som vises på nettsiden. Skriv deretter koden i Svelte-editoren og sjekk svarene dine.

a) 1 <script>

2 let a = 5

3 let b = 2 4 a += 4 5 b++ 6 </script>

7 8 <p>{a} og {b}</p>

c) 1 <script>

2 let a = 7 3 let b = 4

4 let c = a - b 5 a = c*b - a 6 b /= 2

7 </script>

8 9 <p>{a} og {b+c}</p>

1.19

b) 1 <script>

2 let a = 4

3 let b = a*a 4 b += a 5 </script>

6 7 <p>{a} og {b}</p>

d) 1 <script>

2 let a = 7

3 let b = 4

4 $: c = a - b

5 a = c*b - a 6 b /= 2

7 </script>

8 9 <p>{a}, {b} og {c}</p>

a) Lag en nettside med et input-felt for tall. Tallet brukeren skriver inn, skal lagres i en variabel med navnet radius. Nettsiden skal vise verdien for arealet av en sirkel med den inntastede verdien som radius. Svaret skal ha to desimaler.

b) Utvid HTML-koden slik at nettsiden også viser verdien for volumet av en kule med den inntastede verdien som radius. Svaret skal ha to desimaler.

c) Erstatt input-feltet med en glider.

1.20

a) Lag en nettside med tre input-felter for tall. Tallene skal lagres i hver sin variabel.

b) Utvid HTML-koden slik at nettsiden viser gjennomsnittet av de tre inntastede tallene.

c) Utvid HTML-koden slik at nettsiden forteller brukeren hvilket av de tre inntastede tallene som er minst, og hvilket som er størst.

1.21

Lag en nettside som presenterer og regner ut regnestykkene nedenfor. Svarene skal ha to desimaler.

a) 2 x der x 7

b) ab22 der a 3 og b 4

c) e t028 , der e er eulertallet og t 40,9

d) 10112 9 ln(), x der x 3

54 Kapittel 1

1.22

a) Bruk Math-funksjonen Math.random() til å generere et tilfeldig tall mellom 10 og 20. Tallet skal lagres i en variabel.

b) Opprett en ny variabel som gir en tilfeldig heltallsverdi mellom 0 og 1000.

c) Opprett en ny variabel som gir en tilfeldig heltalls- eller halvtallsverdi mellom 0 og 10. Med halvtallsverdi mener vi tallene 0,5, 1,5, 2,5 osv.

d) Opprett en ny variabel som gir en tilfeldig partallsverdi. Partallet skal ikke ha høyere verdi enn 100.

1.23

a) Søk på Internett og finn HTML-koden for en likesidet trekant. Vis koden for trekanten på en nettside med et h1-element. Juster skriftstørrelsen så trekanten blir passe stor, og gi den en fin farge.

b) Opprett én variabel for sidelengden, én for omkretsen og én for arealet av en likesidet trekant. Nettsiden skal vise sidelengden, omkretsen og arealet med p-elementer. Bildet nedenfor viser én mulig løsning.

c) Lag en interaktiv versjon av nettsiden der brukeren kan angi sidelengden. Verdiene for sidelengden, omkretsen og arealet til trekanten og størrelsen på trekanttegnet fra oppgave a skal oppdateres automatisk.

1.24

a) Søk på Internett og finn HTML-koden for et kvadrat. Vis koden for kvadratet på en nettside med et h1-element. Juster skriftstørrelsen så kvadratet blir passe stort, og gi det en fin farge.

b) Gjenskap tabellen nedenfor på en nettside.

Sidelengde (m)

Omkretsen til kvadratet (m)

Arealet til kvadratet (m2)

55Oppgaver

c) Vi skal fylle tabellen med verdier for sidelengden, omkretsen og arealet til to kvadrater. Sidelengden skal være en tilfeldig verdi mellom 0 og 10. Bildet nedenfor viser én mulig løsning.

1.25

Med svg-elementet kan vi tegne figurer på en nettside. SVG står for Scalable Vector Graphics. Koden nedenfor gir en gul sirkel med oransje omriss.

1 <svg height="200" width="200">

2 <circle cx="60" cy="60" r="30" stroke="orange" stroke-width="2" ="yellow" />

3 </svg>

a) Skriv koden i Svelte-editoren og utforsk hva som skjer når du endrer attributtverdiene.

b) Kopier koden inn i programmet ditt fra oppgave 1.19. Gjør endringer i koden slik at størrelsen på sirkelen justeres etter verdien for radiusen som brukeren velger.

c) Bruk Internett og finn ut hvordan du kan tegne andre figurer.

1.26

a) Lag to like store sirkler som står ved siden av hverandre, med svg-elementet.

b) Lag to like store sirkler som står overfor hverandre, med svg-elementet.

c) Lag en stor sirkel med en liten sirkel inni med svg-elementet.

1.27

Lag tre glidere der brukeren kan velge verdier mellom 0 og 255. De tre gliderne skal til sammen fungere som en fargevelger. Når brukeren justerer én eller flere av gliderne, skal tekstfargen til en overskrift med teksten «Fjong farge» oppdateres automatisk.

56 Kapittel 1

1.4 Variabler med strenger

1.28

a) Lag variabler for en persons navn og alder og for en hunds navn og alder.

b) Skriv en hilsen, slik som på bildet nedenfor. Du kan bruke at ett kalenderår tilsvarer fem hundeår.

c) Lag en interaktiv versjon av denne nettsiden der en bruker kan angi sitt eget navn og sin egen alder og navnet og alderen til en hund.

1.29

a) Hvordan kan vi skjøte sammen to tekststrenger?

b) Hvordan kan vi konvertere en streng med talltegn til en tallverdi?

c) Hvordan kan vi konvertere en tallverdi med datatypen number til datatypen string?

d) Hvordan kan vi sjekke datatypen til en variabel?

1.30

a) Les koden nedenfor. Forklar hva programmet gjør, før du skriver koden i Svelteeditoren.

1 <script>

2 let farge

3 </script>

4

5 <input type="color" bind:value={farge} />

6 <h1 style="color: {farge}">Hva gjør denne koden?</h1>

b) Hvilken datatype har variabelen farge?

1.31

I koden nedenfor har vi lagret en streng og brukt noen metoder på den. Avgjør resultatet av hver kodelinje før du skriver den samme koden i Svelte-editoren.

1 <script>

2 let ordtak = "Den som intet våger, intet vinner."

3 </script>

4

5 <p>{ordtak.toUpperCase()}</p>

6 <p>{ordtak.charAt(15)}</p>

7 <p>{ordtak.charAt(ordtak.length-2)}</p>

8 <p>{ordtak.replace("våger", "taper")}</p>

9 <p>{ordtak.replace("intet", "ingenting")}</p>

10 <p>{ordtak.charAt(0)+ "u " + ordtak.substr(-7)}</p>

57Oppgaver

1.32

a) Lag en interaktiv nettside med input-felter for fornavn og etternavn. Verdiene som brukeren skriver inn, skal lagres i variabler og vises på nettsiden. Nettsiden skal også informere om hvor mange bokstaver en person har i navnet sitt.

b) Utvid nettsiden med input-felter for e-postadresse og telefonnummer. Nå skal verdiene som brukeren skriver inn, vises i en tabell. Bruk string-metoder, slik at verdiene vises på samme måte som i tabellen nedenfor.

Navn ETTERNAVN, Fornavn

E-postadresse f.etternavn ( at ) epost.com Telefonnummer 99 88 77 66

1.33

Tallene i titallssystemet består av sifrene 0–9. Vi kan skrive tallet 3256 matematisk, slik: 31000210051061310210510610 3210

I dette tallet står altså 3-tallet på tusenplassen, 2-tallet på hundrerplassen, 5-tallet på tierplassen og 6-tallet på enerplassen.

Tall i totallssystemet, som er det systemet datamaskinen bruker til å lagre data, følger det samme mønsteret. Sifrene i totallssystemet er 0 og 1, og grunntallet til hver potens er 2. Tallet 1010 kan dermed skrives slik: 12021202 3210

I titallssystemet er dette tallet lik 802010 . Vi kan bruke metoden toString() til å konvertere et tall fra titallssystemet til et tall i totallssystemet. Vi bruker denne metoden i koden nedenfor.

a.toString(2);

i titallssystemet:

type="number" bind:value={a}

{a} tilsvarer {b} i totallssystemet.</p>

skriver vi det slik:

({a})<sub>10</sub> = ({b})<sub>2</sub></p>

a) Skriv den samme koden i Svelte-editoren og utforsk tallene i totallssystemet.

Hvor mange sifre trenger vi i totallssystemet for å representere tallene 2, 4, 13, 16, 32, 128, 175 og 256?

58 Kapittel 1
1 <script> 2 let a = 0 3 $: b =
4 </script> 5 6 <h1>Tallsystem-konverterer </h1> 7 <label> 8 Tall
9 <input
/> 10 </label> 11 <p>Tallet
12 <p>Matematisk
<br />
b)

c) Hvilken datatype har variabel b?

d) Skriv inn et desimaltall i input-feltet. Hva skjer? Hva betyr hver av desimalene i resultatet?

Vi kan bruke programmet for å undersøke andre tallsystemer også, for eksempel det heksadesimale tallsystemet. Da skriver vi toString(16).

e) Utvid programmet slik at tallet som skrives inn i input-feltet, også blir konvertert til et tall i det heksadesimale tallsystemet.

f) Hva blir tallene i oppgave b i det heksadesimale tallsystemet?

1.5 Arrayer

1.34

a) Hvordan definerer vi et array?

b) Hvordan kan vi hente ut enkeltverdier fra et array?

c) Gi noen eksempler på ulike måter å vise innholdet i et array på.

1.35

Finn tilbake klasselisten fra oppgave 1.16. Lagre fornavnene i ett array og etternavnene

i et annet. Bruk en each-blokk til å presentere klasselisten som en nummerert liste.

1.36

a) Definer et array med tittelen til fem filmer du har sett nylig. Vis filmtitlene med p-elementer.

b) Sorter titlene slik at de står i alfabetisk orden.

c) Sorter nå titlene i omvendt alfabetisk orden.

1.37

a) Bruk en for-løkke til å fylle et array med alle heltallene fra 0 til 30.

b) Bruk en for-løkke til å fylle et array med alle partallene fra 0 til 30.

c) Bruk en for-løkke til å fylle et array med alle oddetallene fra 0 til 30.

d) Hvordan kan du sortere arrayene slik at tallene blir lagret i synkende rekkefølge?

1.38

Gitt at vi har et array med tallene

["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

En sykkellås har en tresifret kode.

a) Hvor mange slike koder kan vi lage?

b) Hvordan kan vi bruke arrayet ovenfor til å lage en tilfeldig tresifret kode? Kommer du på flere måter å vi kan gjøre det på?

c) Bruk for-løkker til å generere alle de mulige kodene. Vis alle kodene på en nettside.

d) Hvor mange firesifrede koder kan vi lage? Finn alle disse kodene og vis dem på en nettside.

59Oppgaver

1.39

HTML-koden for en grønn sirkel er &#128994;, mens koden for en lilla sirkel er &#128995;. Vi kan lagre HTML-kodene som strenger, slik som vi gjør for én grønn sirkel i koden nedenfor.

1 <script>

2 let grønnSirkel = "&#128994;"

3 </script>

4

5 <h1>En grønn sirkel!</h1>

6 <span style="font-size: 100px">

7 {@html grønnSirkel}

8 // @html sørger for at innholdet i variabelen

// blir tolket som HTML-kode.

9 </span>

a) Lagre koden for en grønn og en lilla sirkel som strenger i variabler. Velg et ønsket antall av hver farge og vis noen grønne og lilla sirkler ved siden av hverandre på en nettside.

b) Definer egne variabler for antallet av hver sirkel. Antallet kan være tilfeldig. Skriv ut andelen av hver farge som brøk. Bildet nedenfor viser én mulig løsning.

c) Bruk arrayer, for-løkker og each-løkker for å vise et tilfeldig antall grønne og lilla sirkler ved siden av hverandre på en nettside. Andelene av hver farge skal fortsatt vises.

d) Legg til sirkler med en ny farge, for eksempel oransje, som har HTML-koden &#128992;.

1.40

a) Velg fire land og finn ut hva valutaen i hvert land heter. Bruk en valutakalkulator på Internett og finn ut hvor mye 1 amerikansk dollar (USD) er verdt i hver valuta.

b) Lag ett array for navnet på hvert land, et annet for navnet på hvert lands valuta og et siste for valutakodene. Valutakoden for norske kroner er for eksempel NOK, mens valutakoden for amerikanske dollar er USD.

c) Bruk en each-blokk for å vise navnet til hvert land, navnet på landets valuta og valutakoden i en punktliste.

60 Kapittel 1

Vi kan skrive en mer kompakt kode ved å bruke et todimensjonalt array. Det er et array med arrayer inni. Vi kan for eksempel slå sammen informasjonen fra arrayet med valutanavn og valutakode slik:

let valuta = [ ["krone", "NOK"], ["euro", "EUR"], ["rupi", "INR"], ["yen", "JPY"] ]

Her har vi et array i hvert av hovedarrayets elementer. For å hente ut arrayet i det første elementet skriver vi valuta[0]. For å hente ut verdien i underarrayet legger vi til en klammeparentes med indeksnummeret. Vi henter ut verdien "krone" med koden valuta[0][0] og verdien "NOK" med koden valuta[0][1].

d) Erstatt arrayene med valutanavnene og valutakodene med et todimensjonalt array. Nettsiden skal vise den samme informasjonen som i oppgave c.

Vi kan også slå sammen all informasjonen om landene og deres valuta til et firedimensjonalt array:

1 let valuta = [

2 ["Norge", "krone", "NOK", 9.3],

3 ["Frankrike", "euro", "EUR", 0.92],

4 ["India", "rupi", "INR", 76.1],

5 ["Japan", "yen", "JPY", 125.6]

6 ]

e) Erstatt arrayene du har brukt tidligere, med et slikt firedimensjonalt array. Nettsiden skal vise den samme informasjonen som før. Bildet nedenfor viser én mulig løsning.

1.6 Funksjoner

1.41

a) Forklar hvordan vi definerer en funksjon.

b) Lag en funksjon som øker verdien til en variabel med én.

c) Lag en funksjon som minker verdien til en variabel med to.

d) Lag en knapp med teksten «Ett skritt frem». Et klikk på denne knappen skal kalle på funksjonen fra oppgave b.

e) Lag en ny knapp med teksten «To skritt tilbake». Et klikk på denne knappen skal kalle på funksjonen fra oppgave c.

61Oppgaver

1.42

En matematisk funksjon er gitt ved fxx()42 2

a) Definer en funksjon som tar inn en x-verdi og returnerer funksjonsverdien.

b) Omdefiner funksjonen slik at den fyller et array med funksjonsverdiene fra og med –3 til og med 3.

c) Presenter x-verdiene og funksjonsverdiene i en tabell.

1.43

Lag et program der en bruker kan angi en lengde i centimeter i et input-felt. Brukeren skal kunne klikke på en knapp og få oppgitt lengden i tommer. 1 tomme tilsvarer 2,54 cm.

1.44

a) Lag en funksjon som tar inn to tall som argumenter. Funksjonen skal returnere summen av tallene.

b) Lag en ny funksjon som tar inn to tall som argumenter. Funksjonen skal returnere differansen mellom tallene.

c) Lag en tredje funksjon som tar inn to tall som argumenter. Funksjonen skal returnere gjennomsnittet av tallene.

d) Lag en interaktiv versjon av programmet med to input-felter for tall. Bruk funksjonene du har laget, til å presentere summen, differansen og gjennomsnittet av tallene som brukeren angir.

1.45

a) Definer et array med ti vilkårlige tall.

b) Lag en funksjon som finner summen av tallene i arrayet.

c) Lag en ny funksjon som finner gjennomsnittet av tallene i arrayet.

d) Lag en interaktiv versjon av programmet. Brukeren skal angi ett og ett tall i et input-felt og klikke på en knapp for å legge til tallet i arrayet. Summen og gjennomsnittet av tallene skal vises på nettsiden og oppdateres når brukeren legger til et nytt tall.

1.46

Energien vi får fra maten vi spiser, kommer fra fett, proteiner og karbohydrater. Når kroppen forbrenner ett gram fett, frigjøres en energimengde på ca. 9 kilokalorier (kcal). Når kroppen forbrenner ett gram proteiner eller ett gram karbohydrater, frigjøres en energimengde på ca. 4 kilokalorier.

a) Lag en funksjon som tar inn en mengde fett målt i gram og returnerer energimengden som blir frigjort.

b) Lag tilsvarende funksjoner for proteiner og karbohydrater.

c) Slå sammen de tre funksjonene fra oppgave a og b til én funksjon som tar inn mengden fett, proteiner og karbohydrater i gram og returnerer den totale frigjorte energien i kilokalorier.

62 Kapittel 1

Én kalori (cal) energi tilsvarer 4,18 joule (J).

d) Lag en ny funksjon som regner om en energimengde fra kilokalorier (kcal) til kilojoule (kJ).

e) Lag en interaktiv versjon av programmet der brukeren kan angi mengden fett, proteiner og karbohydrater i input-felter. Den totale energimengden skal vises på nettsiden.

1.47

Med JavaScript-kode er det ganske enkelt å hente ut all informasjon som har med tid å gjøre. Informasjon om tid er samlet i en klasse som heter date. Vi kan for eksempel hente ut verdien for timen vi er inne i, ved først å skrive koden let idag = new date() og så let time = idag.getHours().

a) Søk på Internett og finn alle JavaScript-kommandoene for tidspunkt og dato. Vær spesielt oppmerksom på hvordan metoden getDay virker.

b) Opprett to arrayer, ett for ukedagene (søndag, mandag, tirsdag, …) og ett for månedene (januar, februar, …). Vis ukedagene og månedene på en effektiv måte med hvert sitt p-element på en nettside.

c) Vis hvilken ukedag og måned det er i dag, ved å bruke metodene du fant i oppgave a.

d) Lag en knapp som brukeren kan klikke på for å vise full dato og klokkeslett. Bildet til høyre viser hvordan datoen og klokkeslettet kan vises.

1.7 Valgsetninger

1.48

a) Lag en nettside med et regnestykke. Brukeren skal oppgi løsningen i et input-felt og få beskjed om hen har svart riktig eller galt.

b) Lag en nettside med et quiz-spørsmål. Brukeren skal svare på spørsmålet i et input-felt og få beskjed om hen har svart riktig eller galt.

1.49

a)

Lag en funksjon som tar inn et tall som argument og sjekker om tallet er et partall.

b) Lag en funksjon som tar inn et array som input og returnerer et nytt array som bare består av partallene fra input-arrayet. Fyll et array med ti tilfeldige heltall og bruk det til å sjekke om funksjonen fungerer som den skal.

1.50

a) Opprett to variabler med tilfeldige heltall mellom 0 og 10. Vis tallene og summen av dem på nettsiden.

b) Oppdater koden slik at brukeren får beskjed om begge tallene er partall, om begge er oddetall, eller om det ene er et partall og det andre et oddetall.

c) Utvid koden slik at brukeren også får beskjed om summen av tallene er større enn, mindre enn eller lik 10.

63Oppgaver

1.51

a) Lag en nettside med et input-felt. Gi brukeren beskjed om å skrive inn et ord som består av seks bokstaver. Dersom ordet som brukeren skriver inn, består av seks bokstaver, skal brukeren få en tommel opp (HTML-kode: &#x1F44D;). Ellers skal brukeren få en tommel ned (HTML-kode &#x1F44E;) og en tilbakemelding om hvor mange bokstaver ordet hen skrev inn, består av.

b) Utvid koden slik at det blir tilfeldig fra gang til gang hvor mange bokstaver ordet skal bestå av.

1.52

Lag en nettside med et input-felt. Brukeren skal få beskjed om å skrive inn et ord som starter på en vokal eller en konsonant. Det skal være tilfeldig om brukeren skal skrive et ord som starter med en vokal eller en konsonant. Det skal ikke spille noen rolle om brukeren skriver liten eller stor forbokstav. Brukeren skal få en tilpasset tilbakemelding som på bildene nedenfor.

1.53

To personer spiller et enkelt terningspill der de kaster en terning annenhver gang. Spillerne får like mange poeng i hver runde som antall øyne terningen viser. Om en spiller får en femmer på terningen, får hen 5 poeng. Spillerne summerer poengene sine etter hvert kast. Spilleren som først får 50 poeng, vinner.

a) Lag tre knapper: én for å nullstille spillet, én for å kaste terningen til spiller1 og én for å kaste terningen til spiller2. Gi knappene forskjellige farger.

b) Programmer funksjonene for hver av knappene. Spillerne skal få beskjed om hvor mange poeng de fikk i det forrige kastet, og den totale poengsummen så langt. Når én av spillerne har 50 poeng eller mer, skal spillerne få beskjed om hvem som har vunnet. Skjermbildet nedenfor viser én mulig løsning.

64 Kapittel 1

c) Utvid spillet slik at spillerne kan skrive navnet sitt i input-felter før spillet starter.

d) Utvid spillet slik at spillerne kan angi hvor mange poeng som må oppnås for å vinne.

e) Spill spillet sammen med noen. Finner dere noe ved spillet dere vil endre på eller utbedre? Prøv å implementere endringsforslagene dere kommer frem til.

1.54

Lag en nettside med en knapp med teksten «Vis». Lag også et blått rektangel, for eksempel med et div-element: <div style="height: 100px; width:200px; background-color: blue"></div>. Når brukeren klikker på «Vis»-knappen, skal rektangelet vises. Knappeteksten skal da endres til«Skjul». Når brukeren klikker på «Skjul»-knappen, skal rektangelet forsvinne.

1.55

a) Velg tre emojier og lagre HTML-koden deres i et array.

b) Lag en funksjon som trekker en av emojiene tilfeldig.

c) Lag en knapp. Når brukeren klikker på knappen, skal tre tilfeldige emojier vises ved siden av hverandre.

Nå har du laget starten på et spill!

d) Utvid koden slik at brukeren får ett poeng når de tre emojiene som vises når hen klikker på knappen, er identiske. Nettsiden skal vise hvor mange ganger brukeren har klikket på knappen du laget i oppgave c, og hvor mange poeng brukeren har fått. Bildene nedenfor viser én mulig løsning.

65Oppgaver

1.56

Utvid spillet du laget i oppgave 1.55, slik at tre rader med tre emojier i hver rad vises når brukeren klikker på knappen. Brukeren får poeng når hen får tre like emojier på rad, overfor hverandre eller diagonalt.

1.57

a) Opprett et tomt array. Bruk en for-løkke til å fylle arrayet med alle heltallene fra 1 til 40 som er delelige med 3. Vis tallene på en nettside.

b) Bruk en for-løkke til å fylle et nytt array med alle heltallene fra 1 til 40 som er delelige med 5. Vis tallene på nettsiden.

Bildet nedenfor viser én mulig løsning.

c) Lag en funksjon som tar inn tre input-verdier. De to første verdiene skal representere det minste og største tallet innenfor et intervall. Funksjonen skal finne alle heltallene innenfor intervallet som er delelige med den tredje input-verdien. Funksjonskallet skal finne alle tallene mellom 30 og 100 som er delelige med 7.

d) Lag tre input-felter slik at brukeren kan angi de tre input-verdiene til funksjonen i oppgave c. Bildet nedenfor viser én mulig løsning.

66 Kapittel 1

1.58

I denne oppgaven skal du lage en dynamisk gangetabell slik som den på bildet nedenfor. Brukeren skal kunne angi antall rader og kolonner som skal vises i tabellen. Bruk CSS til å velge utseendet til tabellen.

1.8 Objekter

1.59

a) Forklar hvordan vi definerer et objekt. Hva menes med et nøkkel–verdi-par?

b) Hvordan kan vi endre verdien til en nøkkel i et objekt?

1.60

a) Velg to norske fotballag og finn resultatene fra de fem siste kampene de har spilt.

b) Lag et objekt for hvert av lagene. Objektene skal ha informasjon om lagnavnet og antall kamper de har vunnet, spilt uavgjort og tapt. Presenter dataene på en nettside.

c) Bruk en if-test til å finne ut hvilket lag som har vunnet flest kamper. Nettsiden skal vise hvilket lag som har vunnet flest kamper.

67Oppgaver

1.61

Gå til nettsiden https://www.worldometers.info/. Her finner du mange interessante data som viser tilstanden til verden i dag.

a) Lag et objekt som lagrer informasjonen i tabellen nedenfor. Bruk oppdaterte tall.

Underernærte mennesker 860 mill. Overvektige mennesker 1726 mill. Ekstremt overvektige mennesker 807 mill.

Mennesker døde av sult 3,3 mill.

Mennesker uten tilgang til rent drikkevann 782 mill.

b) Hent ut dataene fra objektet og presenter dem i en tabell på en nettside.

1.62

a) Søk på Internett og finn informasjon om innbyggertallet i Norge fra de ti siste årene.

b) Bruk et array med objekter for å lagre informasjonen du fant i oppgave a.

c) Presenter dataene i en tabell.

1.63

Finn frem til matvaretabellen på denne nettsiden: https://www.kostholdsplanleggeren.no/. Siden hver matvare i denne tabellen har altfor mange verdier, har vi plukket ut varenavnet og sju typiske verdier som energiinnhold (kcal), fett (g), karbohydrater (g), protein (g), kalsium (mg), jern (mg) og kalium (mg). Hvert objekt skal bestå av åtte nøkkel–verdi-par.

a) Velg tre matvarer fra matvaretabellen på nettet og definer et objekt for hver av dem. For hver matvare skal du lagre navnet på matvaren og verdiene for energiinnhold (kcal), fett (g), karbohydrater (g), protein (g), kalsium (mg), jern (mg) og kalium (mg).

b) Presenter næringsinnholdet i de tre matvarene på en nettside.

Som du merker, er det tungvint å hente ut alle verdiene fra et objekt som inneholder mange verdier. Det finnes heldigvis mange måter å gjøre det mer effektivt på. For eksempel kan vi bruke kommandoen Object.entries(mittObjekt), som returnerer en liste med alle nøklene og verdiene til et objekt. Vi kan bruke en for-of-løkke for å gjøre listen oversiktlig. I koden nedenfor demonstrer vi teknikken:

kr/kg", druer: "34 kr/kg", bananer:

kr/kg"}

68 Kapittel 1
1 <script> 2 let pris = {epler: "25
"30
3 let melding = "" 4 for (let [x, y] of Object.entries(pris)) { 5 melding += x + ": " + y + "<br>" 6 } 7 </script> 8 9 <p>{@html melding}</p>

c) Bruk denne teknikken til å presentere innholdet i hver av de tre matvarene fra oppgave b.

Nå skal vi lage en interaktiv versjon av matvaretabellen.

d) Lag et input-felt der brukeren kan skrive inn navnet til en matvare. Lag også en knapp. Når brukeren klikker på knappen, skal næringsinnholdet til matvaren vises.

e) Gi brukeren en feilmelding dersom han eller hun angir en matvare du ikke har registrert næringsinnholdet til.

69Oppgaver

Gjenbruk og testing

I dette kapittelet skal du jobbe for å nå disse kompetansemålene:

> generalisere løsninger ved å utvikle og bruke gjenbrukbar programkode

> vurdere og bruke strategier for feilsøking og testing av programkode

Når vi gjenbruker en kodesnutt innenfor programmering, for eksempel en funksjon eller en variabel, skriver vi koden i én fil og henter den inn i én eller flere andre filer.

En av fordelene med å gjenbruke kode i flere filer er at vi slipper å gjenta oss selv. Dersom vi har behov for den samme funksjonen eller variabelen ulike steder i et program, trenger vi bare å skrive den ett sted. Og dersom vi må endre koden, trenger vi bare endre den ett sted. Når vi jobber med et program med mange kodelinjer, blir programmet fort uoversiktlig dersom alt ligger i én fil. Ved å dele programmet opp i mindre filer blir koden mer oversiktlig, og det blir lettere å skrive, lese og endre koden.

Varer som fraktes til Norge, blir eksportert fra andre land. Da sier vi at Norge har importert varene.

Før du går gjennom dette kapittelet, bør du sette deg inn i hvordan filsystemet i en datamaskin fungerer, og hvordan du setter opp et Svelte-prosjekt på en datamaskin. Du finner ressurser om dette på elevnettstedet.

KOMPETANSEMÅL
2

2.1

Vi har skrevet inn filnavnet og eventuelle mappenavn som en kommentar i de fleste kodeboksene i dette kapittelet, for eksempel <!-- trapes/+page. svelte -->

Gjenbruke variabler og funksjoner

EKSPORTERE EN FUNKSJON

I mappen src/routes har vi to mapper: trapes og addering. Disse mappene har hver sin +page.svelte-fil. Koden i filene ser slik ut:

1 <!-- trapes/+page.svelte -->

2 <script>

3 let leggSammen = (a, b) => {

4 return a + b

5 }

6

7 let regnUtArealAvTrapes = (topplengde, bunnlengde, hoeyde) => {

8 let sum = leggSammen(topplengde, bunnlengde)

9 return (sum * hoeyde) / 2

10 }

11

12 let a = 1

13 let b = 2

14 let c = 1

15 </script>

16

17 <label>Bunnlinje: <input type="number" bind:value={a} /></label>

18 <label>Topplinje: <input type="number" bind:value={b} /></label>

19 <label>Høyde: <input type="number" bind:value={c} /></label>

20 21 <div>

22 Arealet av trapeset er: {regnUtArealAvTrapes(a, b, c)}

23 </div>

1 <!-- addering/+page.svelte -->

2 <script>

3 let a = 1

4 let b = 2

5

6 let leggSammen = (x, y) => {

7 return x + y

8 }

9 </script>

10

11 <input type="number" bind:value={a} /> + <input type="number" bind:value={b} />

12 = {leggSammen(a, b)}

71Gjenbruk og testing

I begge filene har vi en funksjon som legger sammen to tall: leggSammen. For at vi skal slippe å skrive den samme funksjonen i begge filene, kan vi legge funksjonen inn i en JavaScript-fil, og så importerer begge Svelte-filene funksjonen derfra.

Vi oppretter filen matematikk.js og lagrer den i mappen src/routes. Vi limer inn funksjonen leggSammen. For at det skal være mulig å importere funksjonen, må vi skrive export foran definisjonen av funksjonen.

1 // matematikk.js

2

/* 4 * Fordi vi har skrevet "export" foran funksjonen,

*/

exportlet leggSammen = (x, y) =>

return x +

Pass på at filen slutter på .js når du lagrer den, for dette signaliserer til datamaskinen at filen er en ren JavaScript-fil.

Datamaskinen forstår filer som slutter på .js og .svelte, forskjellig Bokstavene som står etter punktumet i et filnavn, forteller datamaskinen hvordan den skal tolke innholdet i filen. Filer som slutter på .js, inneholder bare kode, mens filer som slutter på .svelte, er nettsider. Hvis vi vil gjenbruke funksjoner og variabler, måde ligge i en fil som slutter på .js.

For å importere funksjonen til +page.svelte-filene skriver vi import { leggSammen } from "../matematikk.js".Det som står etter from, er en veiforklaring til datamaskinen. Tegnene ../ forteller datamaskinen at den skal starte med å gå opp én mappe i strukturen og finne filen matematikk.js som inneholder leggSammen-funksjonen. Vi fjerner leggSammen-funksjonen fra de tidligere filene. Da ser de første linjene slik ut:

1 <!-- trapes/+page.svelte -->

2 <script>

3 import { leggSammen } from "./matematikk.js"

72 Kapittel 2
3
5 6
7
{ 8
y 9 }
4

1 <!-- addering/+page.svelte -->

2 <script>

3 import { leggSammen } from "../matematikk.js"

4

Når du åpner nettsidene igjen, skal de fungere på samme måte som før. Forskjellen er at nå importerer begge filene funksjonen leggSammen fra en felles fil.

Nøkkelordene export og import

Hvis vi skriver export foran en funksjon eller en variabel i en JavaScript-fil, for eksempel export let enVariabel = 1 eller export let enFunksjon = () => { … }, kan vi importere funksjonen eller variabelen inn i andre filer ved hjelp av kode på formen

Når vi importerer en variabel eller en funksjon, oppfører koden for denne seg som om den var definert inni filen som vi importerer den til. Det er ingen begrensning på hvor mange filer som kan importere variabelen eller funksjonen når den først er eksportert.

EKSEMPEL

Eksportere en variabel

Det eneste du trenger å gjøre for å eksportere en variabel, er å skrive export foran den. Når vi jobber med matematikk, kan det for eksempel være nyttig å ha tilgang til hvor mange grader det er i en sirkel, og hva verdien av er.

1 // matematikk.js

2 exportlet leggSammen = (x, y) => {

3 return x + y

4 }

5

6 // Disse to linjene er nye.

7 exportlet PI = 3.14

8 exportlet GRADER_I_SIRKEL = 360

Når vi eksporterer en variabel fra en fil, pleier vi som regel å skrive navnet med store bokstaver og med understrekingstegn mellom ordene. Det signaliserer at verdien er konstant, altså at den ikke bør endres (selv om det er teknisk mulig).

Vi oppretter en ny mappe som vi kaller sirkel. Mappen inneholder en fil som heter +page.svelte

1 <!-- sirkel/+page.svelte --> 2 <script>

3 import { PI, GRADER_I_SIRKEL } from "../matematikk.js"

4 5 let radius = 1 6 </script>

7 8 <h1>Sirkel</h1>

9 <label>Radius: <input type="number" bind:value={radius} /></label>

<div>

11 Areal: {PI * radius * radius}. Sirkelen har {GRADER_I_SIRKEL} grader (som alle sirkler).

13 </div>

73Gjenbruk og testing
10
12

Gi nytt navn til importert kode

Av og til kan det være greit å endre navnet på det vi importerer. Det kan for eksempel hende at det vi importerer, har samme navn som noe annet i filen, eller at det blir lettere å lese koden hvis vi velger et annet navn.

For å endre navnet på det vi importerer, skriver vi nøkkelordet as etterfulgt av det nye navnet:

import { PI as PI_MED_TO_DESIMALER } from "../matematikk.js"

STANDARDEKSPORT

Hvis en fil har et tydelig hovedelement, kan vi definere dette elementet som filens standardeksport. Vi begynner med å se hvordan dette gjøres i praksis.

Vi oppretter mappen loes-andregradsligninger. Hvis vi lager en funksjon som løser andregradsligninger, og lagrer den i filen andregradsligninger.js, har funksjonen en tydelig hovedrolle. Derfor lar vi dette være standardeksporten. For å gjøre funksjonen til filens standardeksport skriver vi export default loesAndregradsligning etter at vi har definert den.

En andregradsligning på formen axbxc20 har løsningene

I matematikken gir abcregelen oss løsningene til en andregradsligning. Vi kan også si at vi finner nullpunktene til en andregradsfunksjon.

Ligningen har to løsninger dersom bac240 og én løsning dersom bac240.

loes-andregradsligninger/andregradsligninger.js

let harKvadratrot = (tall)

}

let harIngenReellLoesning = !harKvadratrot(d)

(harIngenReellLoesning)

let kvadratrot = Math.sqrt(d)

let loesning1 = (-b + kvadratrot) / (2 * a)

let loesning2 = (-b - kvadratrot) / (2 * a)

let harKunEnLoesning = loesning1 === loesning2

if (harKunEnLoesning) {

}

return [loesning1]

return [loesning1, loesning2]

export default loesAndregradsligning

74 Kapittel 2
x bbac a 24 2
1 //
2 export
=> { 3 return tall >= 0 4 } 5 6 let loesAndregradsligning = (a, b, c) => { 7 let d = b * b - 4 * a * c 8
9 if
{ 10 return null 11 } 12
13
14
15
16
17
18
19
20
21 22
EKSEMPEL x2x1 x y f(x) = ax2 + bx + c x = –b ± √ b2 – 4ac 2a

Slik vises andregradskalkulatoren.

Når vi skal importere en standardeksport, skriver vi koden for denne før eventuelle andre importer og uten krøllparenteser. Når vi importerer en standardeksport, står vi fritt til å velge hva funksjonen skal hete i filen vi importerer den til.

Koden nedenfor er et program der brukeren kan angi verdier for koeffisientene a, b og c i input-felter. Programmet importerer funksjonen loesAndregradsligning og bruker den til å finne og vise frem eventuelle løsninger av ligningen. Som du ser i koden nedenfor, velger vi å kalle funksjonen loes når vi importerer den, slik at vi sparer litt plass.

1 <!-- loes-andregradsligninger/+page.svelte -->

2 <script>

3 import loes, { harKvadratrot } from "./andregradsligninger.js"

4 +page.svelte

5 let a = 0

6 let b = 0

7 let c = 0

8

9 $: loesning = loes(a, b, c)

10 </script>

11 12 <h1>Løs andregradsligninger</h1> 13

14 <p>Omform andregradsligningen til du har den på formen: </p>

15

16 <div style="margin: 1rem">

17 ax<sup>2</sup> + bx + c = 0

18 </div>

19

20 <label>a: <input type="number" bind:value={a} /></label>

21 <label>b: <input type="number" bind:value={b} /></label>

22 <label>c: <input type="number" bind:value={c} /></label>

23

24 <div>

25 {#if loesning === null}

26 Ingen reell løsning

27 {:else}

28 Løsninger: {loesning}

29 {/if}

30 </div>

31

32 <h2>Har kvadratrøtter</h2>

33 <ul>

34 <li>{a} har kvadratrot: {harKvadratrot(a)}</li>

35 <li>{b} har kvadratrot: {harKvadratrot(b)}</li>

36 <li>{c} har kvadratrot: {harKvadratrot(c)}</li>

37 </ul>

38 39 <style>

40 input {

41 width: 5rem; 42 } 43 </style>

Hvis du vil bytte navn når du importerer en vanlig eksport, det vil si en navngitt eksport (named export på engelsk), må du nevne elementets opprinnelige navn: import { opprinneligNavn as nyttNavn } from …

75Gjenbruk og testing

Med en standardeksport kan du velge navn selv. Her står du fritt til å velge import opprinneligNavn from eller import nyttNavn from , uten å vise til det opprinnelige navnet.

Standardeksporter er litt kontroversielle. Fordi vi står fritt til å velge hva de skal hete når vi importerer dem, har de ikke et fast navn. Da kan det være vanskelig å søke dem opp i kodebasen. Hvis du vil finne alle filer der en navngitt eksport er importert, kan du søke gjennom kodebasen etter opprinneligNavn. Da finner du garantert alle filene som inneholder eksporten. Vi har ikke den samme garantien med standardeksporter. Hvis kodebasen inneholder mange standardeksporter, kan den bli uoversiktlig. Derfor anbefaler vi at du bare bruker standardeksporter når du har en god grunn til det, og at du ellers bruker navngitte eksporter.

Definere og importere en standardeksport

Hvis en funksjon eller en variabel har en tydelig hovedrolle i en fil, kan vi gjøre dette til filens standardeksport (default export på engelsk).

Når vi skal definere en standardeksport, må vi først definere funksjonen eller variabelen uten å eksportere den: let etEllerAnnet = … Senere i samme fil sk river vi en linje der det står export default etEllerAnnet. Da er etEllerAnnet blitt filens standardeksport.

Når vi skal importere en standardeksport, setter vi ikke krøllparenteser rundt navnet. Dersom standardeksporten ligger i en fil som heter foo.js, og denne filen ligger i den samme mappen som filen vi importerer til, skriver vi: import etEllerAnnet from "./foo.js".

Når vi importerer en standardeksport, kan vi velge et annet navn på eksporten enn den opprinnelig hadde da den ble eksportert. Altså kunne vi også ha skrevet import nyttNavn from "./foo.js". Det regnes imidlertid som dårlig skikk å bytte navn uten en god grunn. En god grunn kunne for eksempel være at det eksporterte navnet allerede er brukt for noe annet i filen det importeres til.

Selv om du ikke planlegger å bruke standardeksporter i koden du skriver selv, forekommer slike eksporter ofte i kode andre har skrevet. Derfor bør du kjenne til hvordan standardeksporter fungerer. Som vi snart skal se, spiller dessuten standardeksporter en viktig rolle når vi gjenbruker Svelte-filer.

76 Kapittel 2

2.2 Lage og gjenbruke komponenter

Når vi skriver inn en adresse i nettleserens adressefelt, for eksempel nrk.no eller youtube.com, får vi opp en nettside som inneholder masse tekst og flere videoer og bilder. Skulle vi ha kodet en av disse sidene selv, hadde sluttresultatet sikkert inneholdt tusenvis av linjer dersom vi skrev nettsiden i én og samme fil.

Når vi lager en stor nettside, har vi så å si aldri bare én fil på datamaskinen. Nesten alle nettsider er bygd opp av flere, gjenbrukbare filer som kalles komponenter. Komponentene settes til slutt sammen til en nettside.

Komponenter

En komponent er en liten bit av en nettside som brukes til å bygge opp en større nettside. En komponent kan brukes i flere filer. Den kan også brukes gjentatte ganger på samme side.

En av de mest åpenbare fordelene med komponenter er at det er lettere å redigere mange små filer enn én gigantisk fil. En annen fordel minner om fordelene vi får ved å dele JavaScript-kode opp i mindre biter: Vi kan gjenbruke en komponent på flere nettsider. De fleste nettsider har for eksempel en navigasjonslinje som går igjen på hele nettstedet. Da er det naturlig å gjøre koden for navigasjonslinjen til en komponent.

Ved å trekke ut navigasjonslinjen som en komponent, kan vi importere den til flere ulike nettsider. Ved å gjenbruke en komponent flere ganger på den samme nettsiden slipper vi å repetere kode. Nettsider inneholder mange elementer som stort sett er like, bortsett fra noen små detaljer. I skjermdumpen fra youtube.com nedenfor er for eksempel videolenkene veldig like utenom teksten og bildeinnholdet.

Her har programmererne hos YouTube sannsynligvis laget en komponent som henter inn videonavnet, miniatyrbildet og litt annen informasjon. Komponenten i koden på neste side heter Videolenke. For å bruke komponenter skriver vi navnet på komponenten som en tagg. Inni taggen kan vi også ha egenskaper som ligner på attributtene til HTML-elementer.

Navigasjonslinjen øverst er synlig på nesten alle nettsidene under nrk.no.
77Gjenbruk og testing

Koden skisserer hvordan YouTube kan ha brukt komponenter med egenskaper. Koden for komponentene er lagret i andre filer.

1 <div>

2 <Videolenke

3 tittel="The Glitch That Kept Sending The FBI To A Tiny Kansas Farm"

4 url="https://www.youtube.com/watch?v=vh6zanS_epw "

5 />

6 <Videolenke

7 tittel="Ten years of coding in 13 minutes"

8 url="https://www.youtube.com/watch?v=1fPWr0d5zBE "

9 />

10 <!-- ... og så videre -->

11 </div>

IMPORTERE EN SVELTEFIL SOM EN KOMPONENT

La oss si at vi har begynt å lage vår egen hjemmeside. På hjemmesiden har vi tenkt å ha tre nettsider som folk kan navigere til.

Vi starter med et tomt SvelteKit-prosjekt. I mappen src/routes oppretter vi følgende filer:

• +page.svelte, som dukker opp hvis folk ikke skriver noen ting etter nettadressen

• filmer/+page.svelte, som dukker opp hvis folk skriver «/filmer» etter nettadressen

• om-meg/+page.svelte, som dukkeropp hvis folk skriver «/om-meg» etter nettadressen

Når vi oppretter prosjektet, ser filene slik ut:

Slik ser src/routes ut når vi starter.

1 <!-- src/routes/+page.svelte -->

<nav>

<!--

nav-elementet endrer ikke utseendet,

men sier til nettleseren at innholdet brukes til navigasjon.

Dette er nyttig for folk som bruker skjermlesere.

<ul>

<!--

Verdien i href viser til nettadressen

<li><a href="/">Hjem</a></li>

<li><a href= >Filmer</a></li>

<li><a href="/om-meg">Om meg</a></li>

</ul>

</nav>

<h1>Velkommen!</h1>

<p>Dette er hjemmesiden min.</p>

<p>Mer innhold kommer.</p>

2 <h1> </h1>

<ol>

<li><a href="https://www.imdb.com/title/tt0068646">Gudfaren</a></li>

<li><a href="https://www.imdb.com/title/tt0050083">12 edsvorne menn</a></li>

7 <li><a href="https://www.imdb.com/title/tt1392190">Mad Max: Fury Road</a></li>

</ol>

78 Kapittel 2
2
3
4
5
6
7 --> 8
9
10
11 12 13 --> 14
15
16
17
18
19 20
21 22
23 24
1
3 4
5
6
8

1 <!-- src/routes/om-meg/+page.svelte -->

2 <h1>Om meg</h1>

3

4 <p>Jeg er en elev på videregående som for øyeblikket velger å være anonym.</p>

Slik ser src/routes ut når vi har opprettet alle filene vi trenger.

Vi har lyst til å legge navigasjonsmenyen fra forsiden inn på toppen av alle sidene, slik at de som besøker hjemmesiden, lettere kan hoppe mellom dem. Vi kunne ha kopiert <nav>...</nav>-delen og limt linjene inn i de andre filene, men da hadde det blitt tungvint å gjøre endringer senere. Hvis vi for eksempel la til en linje, måtte vi ha kopiert og limt alt inn på nytt i de to andre filene også.

For å slippe å gjøre endringer i mer enn én fil lager vi en komponent av navigasjonslinjen. Inni routes lager vi en mappe som vi kaller komponenter. Vi holder koden ryddig ved å lagre alle komponenter på ett og samme sted. Inni mappen komponenter lager vi en fil som vi kaller Navigasjonsmeny.svelte.

I Navigasjonsmeny.svelte limer vi inn det som skal være i navigasjonsmenyen.

1 <!-- src/routes/komponenter/Navigasjonsmeny. svelte -->

2 <nav>

3 <ul>

4 <li><a href="/">Hjem</a></li>

5 <li><a href= >Filmer</a></li>

<li><a href="/om-meg">Om meg</a></li>

</ul>

</nav>

Vi trenger faktisk ikke å gjøre noe som helst for å eksportere denne Svelte-filen som en komponent. Alle Svelte-filer vi skriver og lagrer i mappen komponenter, eksporterer automatisk seg selv som komponenter, og det eneste vi må gjøre, er å importere dem riktig.

79Gjenbruk og testing
6
7
8

Når vi skal importere navigasjonsmenyen som en komponent til de tre nettsidene, legger vi til en script-del i starten av de tre nettsidene. Script-delen inneholder en import-setning som henter standardeksporten fra filen der navigasjonsmenyen ligger. I src/routes/+page.svelte sletter vi den eksisterende navigasjonsmenyen. Deretter skriver vi <Navigasjonsmeny /> i starten av HTML-delen av hver av filene. Da ser starten av hver fil slik ut:

1 <!-- src/routes/+page.svelte -->

2 <script>

3 // Fordi det er en standardeksport, bruker vi ikke krøllparenteser.

4 import Navigasjonsmeny from "./komponenter/Navigasjonsmeny.svelte"

5 </script>

6

7 <Navigasjonsmeny />

8 <h1>Velkommen!</h1>

9 <!-- Resten er likt som før. -->

1 2 <script>

3 import Navigasjonsmeny from "../komponenter/Navigasjonsmeny.svelte"

4 </script>

5 6 <Navigasjonsmeny />

7 <h1> </h1>

8 <!-- Resten er likt som før. -->

1 <!-- om-meg/+page.svelte -->

2 <script>

3 import Navigasjonsmeny from "../komponenter/Navigasjonsmeny.svelte"

4 </script>

5

6 <Navigasjonsmeny />

7 <h1>Om meg</h1>

8 <!-- Resten er likt som før. -->

80 Kapittel 2

Datamaskinen bruker det som står mellom apostrofene i from "..." for å finne komponenten som skal importeres. I filene som ligger i undermappene filmer og om meg begynner veibeskrivelsen med to punktumer. Det betyr at maskinen skal begynne å gå opp én mappe i strukturen til mappen src/routes. I filen som ligger i mappen src/routes trenger vi bare å skrive ./. Da begynner datamaskinen å lete i mappen som filen vi jobber med, ligger i. komponenter/Navigasjonsmeny.svelte leder maskinen til mappen komponenter og videre til filen Navigasjonsmeny.svelte

Eksportere og importere komponenter

Alle Svelte-filer eksporterer automatisk seg selv som komponenter.

Vi importerer en Svelte-fil som en komponent med koden import Komponentnavn from "./mappe/Fil.svelte". Når vi skal bruke komponenter, setter vi vinkelparenteser rundt navnet vi ga komponenten da vi importerte den: <Komponentnavn />

Når filstien starter med to punktumer, går datamaskinen opp én mappe i mappestrukturen fra mappen som filen vi jobber med, ligger i.

MAPPE OG FILNAVN BESTEMMER OM EN FIL ER EN NETTSIDE ELLER EN KOMPONENT

SvelteKit gjør en fil innenfor mappen src/routes, og eventuelle undermapper til denne, om til en nettside dersom, og bare dersom, filen heter +page.svelte. Filer som starter med andre tegn enn +, som filene mine-funksjoner.js og Minkomponent. svelte, brukes til å lagre gjenbrukbare funksjoner og komponenter som vi kan bygge nettsider med.

Det vi skriver inn i adressefeltet i nettleseren for å se resultatet av en gitt +page.svelte fil, avhenger av navnet på mappen som +page.svelte-filen ligger i, og navnet på eventuelle andre undermapper til src/routes vi må gå gjennom for å komme til den aktuelle filen. Tabellen nedenfor viser noen eksempler.

Filplassering URL når vi utvikler

URL til publisert nettside src/routes/+page.svelte http://localhost:5173 https://eksempel.com src/routes/filmer/+page.svelte http://localhost:5173/filmerhttps://eksempel.com/filmer src/routes/notater/it-2/+page. svelte http://localhost:5173/notater/ it-2 https://eksempel.com/notater/ it-2

81Gjenbruk og testing

Slik ser src/routes ut når vi jobber med handlelisten.

2.3 Lage interaktive komponenter

Slik ser telleren ut hvis vi prøver koden uten noe annet på en nettside.

I dette delkapittelet skal vi utvikle en nettside med en handleliste. Her skal vi bruke en interaktiv komponent som brukerne kan klikke på og endre. Komponenten heter Teller og brukes for å holde styr på antall varer i handlelisten.

Nedenfor ser du koden for Teller-komponenten slik den ser ut i utgangspunktet. Telleren har en verdi, og brukeren kan øke og minke denne ved å klikke på pluss- og minusknappene ved siden av verdien. Koden ligger lagret i filen Teller.svelte, som ligger i mappen src/routes/handleliste.

1

handleliste/Teller.svelte -->

<script>

let verdi = 0 // Antallet av en vare

</script>

<span>

<button on:click={() => (verdi = verdi – 1)}> </button>

{verdi}

<button on:click={()=> (verdi = verdi + 1)}>+</button>

</span>

Vi har lyst til å bruke telleren i handleliste/+page.svelte. Vi skriver en import-setning som peker på filen Teller.svelte. For å sette telleren inn som en komponent i filen skriver vi <Teller /> der vi vil at komponenten skal være plassert.

82 Kapittel 2
<!--
2
3
4
5 6
7
8
9
10

1 <!-- handleliste/+page.svelte -->

2 <script>

3 import Teller from "./Teller.svelte"

4 </script>

5

6 <h1>Handleliste</h1>

7 <ul>

8 <li>Løk: <Teller /></li>

9 <li>Epler: <Teller /></li>

10 <li>Melk: <Teller /></li>

11 </ul>

SKRIVESTILENE KEBABCASE, PASCALCASE OG CAMELCASE

Vi navngir undermappene av src/routes med såkalt kebab-case: smaa-bokstavermed-bindestreker. Det er fordi kebab-case følger den anbefalte skrivemåten for nettadresser, slik at brukeren skal slippe å skille mellom små og store bokstaver. Hadde vi lagt en +page.svelte-fil i denne mappen, hadde den blitt gjort om til en nettadresse som ender med /smaa-bokstaver-med-bindestreker.

Navnet på komponenter vi importerer, kan ikke inneholde bindestreker. Derfor skriver vi navnet på slike komponenter i PascalCase. I PascalCase kutter vi ut alle mellomrom og gjør den første bokstaven i hvert ord stor – også i det første ordet. Vi vil at filen vi importerer fra, skal ha samme navn som komponenten vi importerer. Derfor navngir vi filer som skal brukes som komponenter (og ikke som selvstendige sider), med PascalCase: Teller.svelte.

Vi bruker camelCase når vi navngir variabler og funksjoner: navnetTilVariabelEllerFunksjon

Vi bruker PascalCase når vi navngir komponenter og filer som inneholder dem: Komponentnavn

Vi bruker kebab-case i navnet til mapper som inneholder filer som skal gjøres om til nettsider: navnet-til-siden/+page.svelte

83Gjenbruk og testing

EKSTRASTOFF

Navnet på de ulike skrivestilene og deres opprinnelse kebab-case har fått navnet sitt fordi teksten ser ut som matbiter som er stukket på et grillspyd. Grillspyd kalles «shish kebab» i mange land.

PascalCase har fått navnet sitt fra programmeringsspråket Pascal, som igjen er oppkalt etter matematikeren Blaise Pascal.

camelCase har fått navnet sitt fordi de store bokstavene i teksten kan se ut som puklene på en kamel.

SCREAMING_SNAKE_CASE er en stil vi bruker for variabler som vi eksporterer. Denne stilen har fått navnet sitt fordi de store bokstavene får den til å se ut som en ropende variant av skrivestilen snake_case. snake_case er som kebab-case, men med understrekingstegn i stedet for bindestreker.

DEFINERE KOMPONENTEGENSKAPER

Når vi jobber med HTML-elementer, kan vi bruke attributter for å endre måten de oppfører seg og ser ut på. Hvis vi for eksempel skriver <input type="number" min={0} />, blir input-feltet et tallfelt som ikke kan ha lavere verdi enn 0. Vi kan gjøre noe lignende i Svelte-komponenter. Da kaller vi det en egenskap (property på engelsk).

Verdier vi angir i et HTML-element, kalles attributter. Verdier vi angir i en komponent, kalles egenskaper.

I stedet for å skrive <li>Løk: <Teller /></li>, slik vi gjorde i handlelisten tidligere, kan vi for eksempel skrive <li><Teller navn="Løk" /></li>. Da viser telleren navnet på varen med et kolon etterpå. Dette er en fordel hvis vi senere vil endre måten varene vises på, for da kan vi endre koden én gang i Teller.svelte i stedet for tre ganger i handleliste /+page.svelte. Vi kan gjøre en hvilken som helst variabel i en Svelte-komponent til en egenskap ved å skrive export foran den.

1

handleliste/Teller.svelte -->

on:click={() => (verdi = verdi – 1)}> </button>

on:click={()

(verdi = verdi + 1)}>+</button>

84 Kapittel 2
<!--
2 <script> 3 export let navn 4 let verdi = 0 5 </script> 6 7 <span> 8 {navn}: 9 <button
10 {verdi} 11 <button
=>
12 </span>

Handlelisten ser ut akkurat slik som den gjorde før.

Lage komponent-egenskaper

Egenskaper er verdier som sendes inn til en komponent utenfra, via komponentens tagg.

For å si at vi vil ha en verdi utenfra i en Svelte-komponent, skriver vi en linje som begynner med export let egenskapensNavn.

For å angi en verdi for en egenskap skriver vi <Komponenten egenskapensNavn={verdien} />.

I handleliste.svelte angir vi det som tidligere sto foran Teller-taggen, som verdien til egenskapen navn

1 <!-- handleliste/+page.svelte -->

2 <script>

3 import Teller from "./Teller.svelte"

4 </script>

5 6 <h1>Handleliste</h1>

7 <ul>

8 <li><Teller navn="Løk" /></li>

9 <li><Teller navn="Epler" /></li>

10 <li><Teller navn="Melk" /></li>

11 </ul>

EGENSKAPER MED STANDARDVERDI

Av og til ønsker vi at det skal være mulig å slippe å oppgi verdien for en egenskap. I HTML-attributter kan vi for eksempel la være å oppgi verdien for attributtet type i et input-felt, og da får det automatisk verdien "text". Det er med andre ord likegyldig om vi skriver <input /> eller <input type="text" />. Det er også mulig å gi egenskapene i Svelte-komponenter slike standardverdier.

For å angi en standardverdi for en egenskap trenger vi bare å skrive et likhetstegn fulgt av standardverdien etter at vi har definert egenskapen, altså export let egenskapensNavn = standardverdi.

Vi vil at brukeren skal kunne oppgi et antall for Teller, og vi vil at standardverdien skal være 0. For å få til dette i Teller-komponenten trenger vi bare å sette inn export foran let verdi = 0. Vi hadde allerede bestemt at verdi skulle starte med verdien 0, men nå tillater vi altså at brukeren kan overstyre denne verdien.

1 <!-- handleliste/Teller.svelte -->

2 <script>

3 exportlet navn

4 // Vi skriver "export" foran og "= 0" etter "let verdi".

5 exportlet verdi = 0

6 </script>

7 <!-- HTML-delen er lik som før. -->

85Gjenbruk og testing

Løk får antallet 0, slik standardverdien tilsier.

For å angi startverdier skriver vi verdi={ startverdi } i Teller-taggen for varene i Handleliste.svelte. For å teste at standardverdien fungerer som den skal, lar vi være å sende en startverdi til løk-telleren.

1 <!-- handleliste/+page.svelte -->

2 <script>

3 import Teller from "./Teller.svelte"

4 </script>

5

6 <h1>Handleliste</h1>

7 <ul>

8 <li><Teller navn="Løk" /></li>

9 <li><Teller navn="Epler" verdi={5} /></li>

10 <li><Teller navn="Melk" verdi={3} /></li>

11 </ul>

Når vi definerer en egenskap, angir vi en standardverdi ved å skrive koden export let egenskapensNavn = standardverdi

Vi angir egenskapens verdi i taggen til en komponent, slik: <Komponent egenskapensNavn={verdi} />

BINDE KOMPONENTERS EGENSKAPER TIL VARIABLER

I Svelte kan vi binde HTML-elementenes attributter til verdien av variabler. Kodesnutten nedenfor gjør for eksempel at variabelen verdi får samme verdi som en bruker skriver inn i input-feltet.

1 <!-- input-binding/+page.svelte -->

2 <script>

3 let verdi = ""

4 </script>

5 <label>Verdi: <input bind:value={verdi} /></label>

6 <div>Du skrev {verdi}</div>

Det er mulig å binde Svelte-komponentenes egenskaper til verdien av variabler på samme måte. Hvis vi vil binde de ulike varene i handlelisten til en variabel, kan vi skrive bind:verdi={variabelnavn} for hver enkelt vare. Koden i Teller.svelte trenger vi ikke å endre i det hele tatt.

1 <!-- handleliste/+page.svelte -->

2 <script>

3 import Teller from "./Teller.svelte"

4

5 let antallLoek

6 let antallEpler = 5

7 let antallMelk = 3

8 </script>

9

10 <h1>Handleliste</h1>

11 <ul>

12 <li><Teller navn="Løk" bind:verdi={antallLoek} /></li>

13 <li><Teller navn="Epler" bind:verdi={antallEpler} /></li>

14 <li><Teller navn="Melk" bind:verdi={antallMelk} /></li>

15 </ul>

16

17 <p>Du har {antallLoek + antallEpler + antallMelk} varer i handlelisten.</p>

86 Kapittel 2

Fordi vi ikke har gitt antallLoek noen verdi, får denne variabelen standardverdien

0 når vi binder den. Du kan prøve å endre standardverdien til 1 i Teller.svelte. Da skal du få opp en melding om at du har 9 varer i handlelisten i stedet for 8, og verdien for løk vil være 1.

Når en egenskap verken har en standardverdi eller får en verdi i komponentens tagg, får den verdien . Hvis vi bare skriver <Teller /> og glemmer å sende inn en verdi for navnet, ser det altså ut som på bildet til venstre.

LAGRE VARENE I ET ARRAY OG VISE DEM MED EN EACHBLOKK

I kapittel 1 lærte du å iterere over et array med en each-blokk. I handlelisten vi holder på å utvikle, er det en fordel at varene er lagret i et array. Da kan brukeren legge til så mange varer hun vil, og ikke et forhåndsbestemt antall. Vi venter litt med å legge til funksjonalitet som gjør det mulig for brukeren å legge til flere varer, og begynner med å flytte det vi allerede har, over i et array.

1 <!-- handleliste/+page.svelte -->

2 <script>

3 import Teller from "./Teller.svelte"

4

5 let varer = [

6 { navn: "Løk", antall: 0 },

7 { navn: "Epler", antall: 5 },

8 { navn: "Melk", antall: 3 }, 9 ]

11 const summerAntall = (varer) => {

12 let sum = 0

13 for (let vare of varer) {

}

sum = sum + vare.antall

return sum

}

$: totaltAntall = summerAntall(varer)

20 </script>

<h1>Handleliste</h1>

<ul>

{#each varer as vare}

<li><Teller navn={vare.navn} bind:verdi={vare.antall} /></li>

{/each}

</ul>

<p>Du har {totaltAntall} varer i handlelisten.</p>

Det første vi gjorde, var å legge varene til som objekter i arrayet varer. Siden arrayet kan inneholde mange verdier, er vi nødt til å bruke en løkke for å regne ut summen. Derfor har vi laget funksjonen summerAntall, som tar inn antall varer som input og bruker en løkke til å summere alle varene.

Linjen $: totaltAntall = summerAntall(varer) gjør at verdien til variabelen totaltAntall regnes ut på nytt hver gang brukeren endrer verdien til varer

87Gjenbruk og testing
10
14
15
16
17
18 19
21 22
23
24
25
26
27
28 29

Etter at vi har klikket på knappen tre ganger, ser det slik ut.

ved å klikke på pluss- og minusknappene. Du husker kanskje fra tidligere at $: markerer at linjen skal reagere på alle endringer i stedet for å bare kjøres når vi åpner en nettside. Hvis vi hadde startet linjen med let i stedet for $:, hadde programmet bare regnet ut verdien når nettsiden åpnes, og ikke oppdatert den ved senere endringer.

I HTML-delen av dokumentet har vi skrevet en each-blokk som oppretter en Teller-komponent for hver verdi i varer-arrayet. Legg merke til at vi i for-løkken skrev let vare of varer. Da sier vi at en verdi i arrayet midlertidig skal få navnet vare inni denne iterasjonen av blokken, på samme måte som i en each-blokk.

LEGGE TIL VARER I HANDLELISTEN

For å gjøre handlelisten litt mer spennende vil vi gi brukerne muligheten til å legge til varer. Vi velger å lage en knapp og definere en funksjon som legger til en vare i listen. Nå som brukerne kan legge til varer selv, fjerner vi de tre varene fra handlelisten og lar varer være et tomt array.

1 <!-- handleliste/+page.svelte -->

2 <script>

3 // Likt før dette, men varer er et tomt array når vi starter.

4 let varer = []

5 // Resten av script-delen er lik.

6 </script>

7

8 <h1>Handleliste</h1>

9 <ul>

10 {#each varer as vare}

11 <li><Teller navn={vare.navn} bind:verdi={vare.antall} /></li>

12 {/each}

13 <li>

14 <button

15 on:click={() => {

16 varer = [...varer, { navn: "Ny vare", antall: 0 }]

17 }}

18 >

Legg til vare

</button>

</li>

</ul>

24 <p>Du har {totaltAntall} varer i handlelisten.</p>

ENDRE NAVN PÅ VARER

Teller har en åpenbar mangel: Når brukerne legger til nye varer, ønsker de å sette egne navn på dem. Kanskje vil de også redigere navnet på varer de allerede har lagt til.

Vi bør legge til en knapp i Teller.svelte som gjør at brukerne kan endre navnet på telleren. Når brukerne trykker på denne knappen, bør hele telleren bli til et input-felt, slik at de bare har muligheten til å redigere navnet, ikke antallet. Brukerne bør få to knapper å trykke på: én for å lagre resultatet og en annen for å avbryte og gå tilbake til navnet slik det var før de redigerte det. Dette løser vi i koden på neste side.

88 Kapittel 2
19
20
21
22
23

1 <!-- handleliste/Teller.svelte -->

2 <script>

3 export let navn

4 export let verdi = 0

5

6

// Variabler for å styre endringen

7 let endrerNavn = false

8 let endringsforslag = ""

9 </script>

10

11 {#if endrerNavn}

12

<!-- Dette vises hvis man trykker på Endre-knappen. -->

13 <label>Nytt navn: <input bind:value={endringsforslag} /></label>

14 <button

15 on:click={() => {

16 navn = endringsforslag

17 endrerNavn = false

18 }}

19 >

20 Lagre

21 </button>

22 <button on:click={() => (endrerNavn = false)}> Avbryt </button>

23 {:else}

24 <span>

25 <!--

26

Vi har lagt navn i en span-tagg med litt rom til høyre

27 og kuttet ut kolonet.

28 -->

29 <span style="margin-right: 0.5rem">

30 {navn}

31

<!-- Knapp for å aktivere endring -->

32 <button 33 on:click={() => { 34 endringsforslag = navn 35 endrerNavn = true 36 }} 37 > 38 39 </button> 40 </span>

41 <button on:click={() => (verdi = verdi - 1)}> </button> 42 {verdi}

43 <button on:click={() => (verdi = verdi + 1)}>+</button> 44 </span> 45 {/if}

Merk: Når du prøver ut denne handlelisten, oppdager du kanskje at den oppfører seg litt rart i noen situasjoner. Dette er en feil vi har beholdt med vilje, slik at vi kan se på den i neste delkapittel.

89Gjenbruk og testing

1. Definer testen.

2. Gjennomfør testen.

2.4 Teste et helt dataprogram

I dataprogrammering er en test en kontroll av om det vi har utviklet, oppfører seg som forventet. Det vi tester, kan være en funksjon, en komponent eller et helt program.

Vi gjennomfører en test i to steg. Først definerer vi testen ved å gi en tydelig beskrivelse av hvordan testen skal utføres, og hvilket resultat vi forventer. Deretter gjennomfører vi testen ved å følge beskrivelsene og sjekke om resultatet blir som forventet.

Hvis resultatet blir som forventet, sier vi at testen passerte. Hvis resultatet ikke blir som forventet, sier vi at testen feilet. Når en test feiler, er det én eller flere feil i programmet. Da må vi finne ut hva som er årsaken til feilene, og fikse dem hvis det er mulig.

I dette delkapittelet skal vi se nærmere på hvordan vi lager tester for et helt dataprogram. Disse testene utfører vi selv. Vi beskriver hvordan vi skal utføre dem, med vanlig skriftspråk, og av og til supplerer vi med bilder eller illustrasjoner.

I delkapittel 2.6 skal vi se nærmere på hvordan vi skriver enhetstester, som tester at utdataene er som forventet når vi sender visse inndata til funksjoner. Da skriver vi testene som kode, og det er datamaskinen som utfører dem for oss.

90 Kapittel 2

TESTTILFELLER, TESTSAMLINGER OG DEKKENDE TESTER

Et testtilfelle er en beskrivelse av hvordan vi skal utføre en test, og testens forventede resultater. Når vi skal teste et helt dataprogram, har vi som regel flere testtilfeller. Alle disse testtilfellene kaller vi for en testsamling. Målet er å ende opp med en testsamling som gjør at vi kan være rimelig trygge på at programmet oppfører seg som det skal. Testsamlingen bør være satt sammen slik at testtilfellene dekker alt som kan skje når brukerne tar programmet i bruk. Da sier vi at testsamlingen er dekkende

Det er vanskelig å teste alt som kan skje med et dataprogram, uansett hvor lite det er. Målet er å være borti all kode som er utviklet, minst én gang i løpet av testen. Vi vil med andre ord at datamaskinen skal innom alle kodelinjer minst én gang, for eksempel alle deler av en if-else-setning, gjerne med litt forskjellige inndata. Når vi tester et dataprogram med brukergrensesnitt, bør den tenkte brukeren for eksempel ha trykket på alle knapper i brukergrensesnittet, gjerne i litt ulike rekkefølger.

KOMME PÅ TESTTILFELLER TIL ET DATAPROGRAM MED BRUKERGRENSESNITT

Når du skal lage tester, er det lurt å gå ut fra at du er en av dem som skal bruke programmet:

• Hva vil du oppnå med å bruke programmet?

• For hver ting du vil oppnå: Hvilke handlinger må du utføre? Hva forventer du at handlingene skal føre til?

• Hvordan forventer du at ting skal se ut underveis og helt til slutt?

Vi kan bruke bestigning av topper i et fjellandskap som et bilde på alt som er mulig å gjøre i et program. Vi tenker oss at vi står ved foten av den første fjelltoppen når vi åpner programmet. Hver topp representerer et mål som brukerne ønsker å oppnå.

91Gjenbruk og testing

Hvis vi overfører dette til handlelistenettsiden vår slik den ser ut nå, er det egentlig bare mulig å oppnå ett mål, nemlig å lage en handleliste til en handletur. For illustrasjonens skyld har vi tegnet inn tre mål som brukeren kunne ha oppnådd hvis programmet hadde flere funksjoner, i figuren nedenfor.

Lage en handleliste til en handletur

Sende en handleliste til en venn

Lage en handleliste som jeg kan lagre og hente senere

«Den glade sti»

Når du skal lage testtilfeller, kan du starte med å lage en test der brukerne følger den glade sti (the happy path på engelsk) til målet: De trykker på alle knapper i riktig rekkefølge, skriver alt riktig og gjør ingen feil. De oppnår målet uten problemer, som i fjellbildet vil si at de går den raskeste veien til fjelltoppen uten å ta en eneste omvei og uten å bli hindret av dårlig vær.

Brukerne følger sjelden den glade sti. De trykker på knapper de ikke burde trykke på (fordi de bommer, blir distraherte eller misforstår), og de skriver ikke alltid riktig på første forsøk når de skal skrive inn noe i et input-felt. Etter at du har skrevet et testtilfelle der brukerne følger den glade sti, kan du skrive ett eller flere testtilfeller der brukerne tar omveier og gjør feil underveis. Slike testtilfeller kaller vi realistiske tilfeller.

Når du har bestemt deg for hvilke testtilfeller du vil ha med i testsamlingen, skriver du ned hva de som tester programmet, skal gjøre, og hvilke resultater de skal forvente. Beskrivelsen må være så detaljert at andre kan utføre testene uten å spørre deg. Når andre kan utføre en test på nytt uten å spørre deg, sier vi at testen er reproduserbar.

Du står selv fritt til å velge hvordan du vil beskrive testene. Avslutt hvert testtilfelle med en beskrivelse av de forventede resultatene, eller sluttresultatet, som godt kan være et bilde. Du kan godt beskrive forventede delresultater underveis når det er nyttig.

Faktisk bruk
92 Kapittel 2

Testsamling for handlelisten

Nå skal vi teste handlelistekoden fra forrige delkapittel. Vi ser for oss at brukeren ønsker å lage en handleliste med 1 kaffe, 3 epler og 4 brød.

I den-glade-sti-testtilfellet klarer brukeren å legge til de tre varene, redigere navnene og angi antallet uten å trykke feil en eneste gang. I et annet mer kaotisk testtilfelle ønsker vi at testen skal omfatte følgende handlinger:

• endre antall før man skriver inn navn

• skrive inn feil navn på en av varene

• skrive inn et navn som ikke har bokstaver

• skrive inn et navn som inneholder rare bokstaver (vi velger «crème fraîche»)

• avbryte redigeringen av et varenavn

• bruke minusknappen for å redusere antallet av en vare fordi man har trykket for mange ganger

Vi har skrevet de to testene slik:

#1 Lage handleliste, den glade sti Dersom du følger de fire stegene nedenfor, skal det ligge ett punkt i handlelisten: «kaffe» med verdien 1.

1.Klikk på «Legg til vare».

2.Klikk på blyantknappen ved siden av den siste varen i listen.

3.Skriv inn «kaffe» og klikk på «Lagre».

4.Klikk på plussknappen én gang.

Gjenta deretter steg 1 til 4, men skriv inn «epler» og klikk på plussknappen tre ganger. Da skal

• et nytt punkt ha dukket opp til slutt i listen: «epler», med verdien 3

• de tidligere punktene være uendrede

Gjenta til slutt steg 1 til 4, men skriv inn «brød» og klikk på plussknappen fire ganger. Da skal

• et nytt punkt ha dukket opp til slutt i listen: «brød», med verdien 4

• de tidligere punktene være uendrede

Sluttresultatet skal se slik ut:

#2 Lage handleliste med forviklinger

I dette tilfellet skal du gjøre akkurat som i testtilfelle #1, men når du har lagt til epler, gjør du følgende før du fortsetter med brød:

1.Klikk på «Legg til vare».

2.Klikk på plussknappen tre ganger og deretter på minusknappen én gang.

Nå skal varen ha verdien 2.

3.Klikk på blyantknappen ved siden av den siste varen i listen.

4.Slett innholdet i feltet og klikk på «Lagre».

Nå skal varen vises uten navn.

5.Klikk på blyantknappen ved siden av den siste varen i listen.

6.Skriv inn «krem fresj» og klikk på knappen «Avbryt». Varen skal gå tilbake til forrige verdi, som var uten navn.

7.Skriv eller lim inn teksten «crème fraîche» og klikk på knappen «Lagre».

Nå skal navnet være «crème fraîche».

Da skal

• et nytt punkt ha dukket opp til slutt i listen: «crème fraîche», med verdien 2

• de tidligere punktene være uendrede

Fortsett som i testtilfelle #1 fra steget der du legger til brød.

Sluttresultatet skal se slik ut:

Her har vi prøvd så godt vi kan å få med alt brukerne kan finne på. Vi har klikket på alle knappene, og takket være testtilfelle #2 har vi også klikket på dem i litt ulik rekkefølge. Derfor vil vi si at disse testene er dekkende. Hvis vi utfører testene med et vellykket resultat, kan vi lansere nettsiden med handlelisten med visshet om at de fleste brukerne vil få en god opplevelse.

93Gjenbruk og testing
EKSEMPEL

Som sagt står vi fritt til å velge hvordan vi skriver ned testene. Her er noe av det vi liker med formatet vi valgte i testsamlingen for handlelisten i eksemplet på forrige side:

• Testene har en ID. Dette gjør det lett å snakke om testene med andre, for eksempel kan vi si at «Testtilfelle #1 feilet».

• Hver test har et navn som beskriver hva målet med akkurat denne testen er. Da blir det lett for folk å forstå hva vi ønsker å teste. Jo større testsamlingen er, desto nyttigere er det å ha gode navn på testene.

• Det er tydelig hva som er instrukser, og hva som er forventede resultater. Det er tydelig hva som skal gjøres, og hva som er de forventede mellom- og sluttresultatene.

• Vi har lagt ved et bilde av sluttresultatet. Dette burde bidra til å avklare eventuelle utydelige instruksjoner.

EKSTRASTOFF

Tenke som en motstander

Når du skal skrive tester for realistiske tilfeller, kan det være nyttig å tenke som en motstander

som prøver så godt han kan å ødelegge programmet ditt.

En slik motstander kunne for eksempel ha funnet på å gjøre følgende:

• skrive inn en veldig lang streng i input-feltet, for eksempel lime inn en hel avisartikkel

• la strengen inneholde forskjellige tegn, som norske bokstaver, bokstaver med aksenter (for eksempel é, à eller ö) eller emojier

• la være å skrive inn noe

• klikke på helt andre knapper enn «Lagre»- og «Avbryt»-knappen etter at han har redigert innholdet

• lime inn tekst på andre skriftspråk, for eksempel arabisk, kinesisk eller gresk

• prøve å lime inn et bilde i input-feltet

Når du har skrevet ned alt en motstander kunne ha gjort for å ødelegge programmet, tar du stilling til om du synes det er verdt å lage tester som prøver ut disse punktene.

Mye av det som står på listen ovenfor, er rimelig å teste:

• Noen matvarer har rare tegn i navnet, som crème fraîche.

• Brukere gjør feil, som å lagre tomme verdier.

• Folk liker å bruke emojier.

• Hvis brukerne blir distrahert, kan de fort glemme at de holdt på å redigere navnet på én vare og klikke på pluss- og minusknappen for en annen vare.

Når det gjelder handlelisten, har vi allerede tatt hensyn til de to første punktene ovenfor i testtilfelle #2. De to siste punktene har vi ikke tatt hensyn til.

Selv forslag som kan virke urimelige ved første øyekast, kan være verdifulle. Det virker for eksempel urimelig at programmet skal tåle at brukerne limer inn en hel avisartikkel. Men brukere kan jo lime inn lange strenger uten at de har til hensikt å ødelegge noe. En bruker kan for eksempel ha prøvd å kopiere én ingrediens fra en lengre matoppskrift og ved en feil ha kopiert hele matoppskriften. Dermed kan det være lurt å teste om programmet tåler det, slik at brukeren kan rette opp i feilen etterpå.

Noen forslag kan vi overse med god samvittighet. De fleste nettlesere nekter å lime inn bilder i tekstfelter, så det er unødvendig å teste dette. Hvis vi lager en handleliste med norsk brukergrensesnitt, klarer brukerne seg sannsynligvis uten arabiske og kinesiske tegn.

94 Kapittel 2

DISKUTER

Synes du at disse testene dekker alt det er naturlig å bruke handlelisten til? Er det noe du burde ha lagt til? Er det for eksempel noen knapper som det ikke er klikket på?

EKSTRASTOFF

Det er lurt å skrive testene før koden

I dette delkapittelet har vi testet kode som vi allerede har skrevet. Det er imidlertid god praksis å skrive testene før vi skriver koden. Når vi skriver testene etter at koden ferdig, er det flere menneskelige faktorer som gjør at kvaliteten på testene blir dårligere, blant annet:

• Vi har ikke lyst til å finne feil i noe vi allerede har lagt mye arbeid i. Derfor har vi lett for å forhaste oss, og vi tar ikke oppgaven med å tenke som en motstander på alvor.

• Testingen virker som unødvendig ekstraarbeid: Vi eksperimenterte jo mens vi laget programmet, og det må da være godt nok. Andre oppgaver haster, og det er fristende å droppe testingen, slik at vi kan begynne på dem.

• Vi er sliten og lei av oppgaven som vi har holdt på med en stund nå. Vi har ikke overskudd til å skrive like gode tester som vi hadde gjort dersom vi hadde skrevet dem før vi begynte på oppgaven.

Hvis vi skriver testene, eller et utkast til dem, på forhånd, klarer vi sannsynligvis å komme på flere av forventningene en ny bruker møter nettsiden eller programmet med, og vi tar arbeidet mer alvorlig. Å skrive testene trenger ikke å ta mer enn noen få minutter. Det er ikke nødvendig å skrive ned alle stegene og få med alle kravene med en gang. Det er heller ikke sikkert at alle kravene til programmet er klare før vi har jobbet litt med det. Det viktigste er at vi gjør så mye vi kan, slik at vi kan forbedre testene etter hvert.

Det er ingen som forventer at du som er elev alltid skal skrive tester på forhånd. Det er helt greit at du skriver tester etter at du har skrevet koden. Når du har fått mer erfaring, kan du prøve deg litt frem. Du kan for eksempel skrive en test før du legger til en ny knapp i et eksisterende program.

2.5 Feilsøking

Feilsøking handler om å finne ut hvorfor et resultat ikke er som forventet. Med mindre du har rettet opp i handlelistekoden, feilet begge testene i forrige delkapittel. Når vi klikker på «Legg til vare» og pluss- og minusknappene, tilbakestilles navnet på varene vi har lagt til tidligere, men ikke antallet. Dette er en utilsiktet feil som oppsto da vi skrev koden, men som vi har beholdt, slik at vi kunne bruke den til å demonstrere feilsøking.

NOTER DET DU TROR ER FEIL, OG UNDERSØK DET

Det første du bør gjøre når du skal feilsøke, er å skrive ned alt du tror kan være opphav til feilen, i en tekstfil. Da unngår du å miste tråden underveis eller glemme gode ideer. Hvis du må be andre om hjelp, er det veldig nyttig for dem å vite hva du har sett på, og da kan du vise dem tekstfilen. Når du har funnet feilen og løst den, kan du ta vare på filen, slik at du kan lære av det du har gjort.

95Gjenbruk og testing

Da testene fra forrige kapittel feilet, noterte han som hadde skrevet koden, følgende:

• Har jeg misforstått hvordan bind: virker?

• Fungerer bind: bare på attributter i HTML-elementer og ikke på egenskaper i Svelte-komponenter?

• Fungerer det bare på tall? (Jeg har jo klart å binde til antall, og det ser ut til å virke selv om vi legger til varer.)

• Har jeg skrevet feil noe sted?

Når du har funnet feil, bør du notere deg hva feilen er, og hva du tror er årsaken til den. Hvis du ikke finner ut hva feilen skyldes med én gang, kan du

• lese dokumentasjonen for språket eller verktøyet du bruker

• logge kjørende kode med funksjonen console.log

• bruke utviklerverktøyet i nettleseren

LESE DOKUMENTASJON OG HJELPERESSURSER PÅ NETTET

For å sjekke om vi har forstått det kodetekniske riktig, kan vi lese dokumentasjonen for programmeringsspråket eller kodeverktøyet vi jobber med. Dokumentasjonen er bruksanvisningen til språket eller verktøyet vi bruker. Den forklarer hva vi kan gjøre, og er ofte supplert med interaktive kodeeksempler og bilder av forventede resultater.

Hvis du har lastet ned et kodeverktøy fra en nettside, finner du ofte dokumentasjonen ved å se etter en lenke på siden med teksten «Getting started», «Documentation», «Docs», «API», «Readme» og lignende. Du kan også søke på nettet etter verktøyets navn etterfulgt av «documentation».

96 Kapittel 2

Ikke alle verktøy har en egen hjemmeside. Det finnes for eksempel ingen nettside der du laster ned HTML, CSS og JavaScript. Disse språkene er bygd inn i nettleseren. Det betyr at nettleseren kan lese koden og vise frem resultatet. Hvis du åpner «Hjelp»-menyen i nettleseren, får du bare hjelp til å bruke nettleseren, ikke til å lage dine egne nettsider. Det betyr at du må finne dokumentasjon for språkene andre steder.

Dokumentasjon for Svelte, Javascript, HTML og CSS

Du finner dokumentasjon om hvordan du lager Svelte-komponenter, på https://svelte.dev/docs. Hvis du bruker SvelteKit, som brukes for å sette sammen flere filer til større nettsider, finner du dokumentasjonen på https://kit.svelte.dev/docs.

www.w3schools.com er et begynnervennlig nettsted der du kan finne dokumentasjon for HTML, CSS og JavaScript. Mer viderekomne programmerere pleier som regel å bruke Mozilla Developer Network (MDN), som de finner på https://developer.mozilla.org/. Sidene til MDN er ofte mer oppdatert og innholdsrike, men bruker språk og eksempler som er mer teknisk avanserte enn sidene til W3Schools.

For å få svar på spørsmålet «Har jeg misforstått hvordan bind: virker?» og de to tilhørende spørsmålene gikk vi til Svelte-dokumentasjonen og søkte på teksten «bind:».

Vi fikk nesten 70 treff, som vi skumleste på leit etter relevante opplysninger.

Følgende setning ga et ganske tydelig svar på det ene spørsmålet: «You can bind to component props using the same syntax as for elements.» Det betyr at vi kan skrive bind: både i HTML-elementer og Svelte-komponenter og forvente at det fungerer likt. Det var dessuten ingenting i dokumentasjonen som sa at vi bare kan binde til tall og ikke strenger. Med andre ord hadde vi forstått hvordan bind: fungerer.

FEILSØKING I KJØRENDE PROGRAMKODE

Vi kan se på hendelsesforløpet fra programmet starter til det uønskede resultatet oppstår, som en tidslinje som beveger seg mot høyre etter hvert som brukeren trykker på knapper og angir informasjon i grensesnittet og linjene i programmet kjører. Feilsøking handler om å finne ut akkurat hvor på tidslinjen programmet begynner å oppføre seg annerledes enn forventet.

Det enkleste – og kanskje mest brukte – verktøyet for å få oversikt over tidslinjen, er funksjonen console.log. Denne funksjonen henter inn data og viser dem i den såkalte konsollen, slik at vi kan se hva de underliggende verdiene er. Vi setter inn console.log før og etter en kodelinje for å undersøke hva verdien var før og etter at denne linjen ble kjørt. Det er også nyttig å bruke console.log til å forstå når og i hvilken rekkefølge koden kjøres. Hvis meldingene aldri dukker opp i konsollen når vi forventer dem, eller hvis de dukker opp i en uventet rekkefølge, har vi sannsynligvis skrevet noe feil.

97Gjenbruk og testing

Se konsollen på Svelte.dev/repl

På https://svelte.dev/repl kan du trykke på «Console» nederst til høyre for å se hva som har blitt skrevet til konsollen.

Nederst til høyre ser vi at strengen "Hei" har blitt lagret i konsollen.

ÅPNE UTVIKLERVERKTØYET PÅ EN HVILKEN SOM HELST NETTSIDE

De færreste nettsider har et sted i dokumentet der vi kan klikke for å se hva som er skrevet til konsollen. Derfor må vi åpne utviklerverktøyet (developer tool på engelsk) til nettleseren, som er et eget vindu der vi kan finne informasjon som er interessant for utviklere, men ikke for vanlige brukere.

Når du er inne i en spesifikk fane i nettleseren og vil åpne utviklerverktøyet for å se på innholdet i denne fanen, kan du bruke følgende tastesnarveier:

• Windows og Linux: Ctrl + Shift + I

• Mac: Command + Option + I

For å beskytte brukere mot ondsinnede angrep har Apple valgt å deaktivere utviklerverktøyet i Safari som standard. Hvis du bruker Safari, må du derfor slå på utviklerverktøyet ved å åpne innstillingene (trykk på Cmd + ,), gå til fanen «Avansert» og klikke på «Vis Utvikle-menyen i menylinjen».

98 Kapittel 2

Når du har åpnet utviklerverktøyet, klikker du på fanen «Console» (eller «Konsoll» i Safari), hvis den ikke allerede er åpen.

Konsollen som angrepsflate

Folk med ondsinnede hensikter kan lure intetanende ofre til å lime skadelig kode inn i konsollen og kjøre den. Ofte dukker slik kode opp i kjedebrev med løfter om at koden for eksempel skal hjelpe mottakerne med å se hvem som er inne på profilen deres, eller med å få flere «likes». Slik ondsinnet kode klikker på knapper og sender forespørsler på brukerens vegne. Resultatet er som regel at angriperen får tilgang til offerets konto og sensitiv informasjon. Noen ganger sprer slik kode seg til offerets omgangskrets ved at den sender meldinger til offerets venner eller legger ut innlegg på offerets vegne med de samme oppfordringene og løftene.

For å stoppe slike angrep viser noen populære nettsteder en advarsel når noen åpner konsollen på det aktuelle nettstedet.

Du kan trygt bruke konsollen på nettsider du selv har skrevet.

Nå skal vi se hvordan vi brukte console.log for å finne feilen i handlelisteprogrammet. Det første vi ville gjøre, var å forsikre oss om at navn faktisk ble endret inni Teller når koden kjører. Da endret vi funksjonen som lå i «Lagre»-knappen ved å legge inn to console.log-utsagn.

EKSEMPEL
99Gjenbruk og testing

Prøv å legge til denne linjen i handleliste/+page.svelte på datamaskinen din, og gjennomfør testtilfelle #1 fra 2.4 på side 93 igjen. Noter det du observerer.

Prøv å legge inn de tilsvarende endringene i koden på datamaskinen din, og gjennomfør testtilfelle #1 fra kapittel 2.4.

1 <button

2 on:click={() => {

3 console.log("Navn var", navn)

4 navn = endringsforslag

5 console.log("Navn endret til", navn)

6 endrerNavn = false

7 }}

8 >

9 Lagre

10 </button>

Når du har utført testen, ser konsollen slik ut:

Linjen oppfører seg med andre ord som forventet. Variabelen navn som inneholdt verdien "Ny vare", får den nye verdien etter at du har klikket på «Lagre». Her begynte vi å mistenke at det var noe galt i måten handleliste/+page.svelte reagerte på endringer fra Teller på. Derfor la vi inn følgende linje i slutten av scriptblokken i handleliste/+page.svelte:

$: console.table(varer)

console.table er en variant av console.log. Forskjellen er at console. table viser dataene vi gir den, som en tabell. Det er praktisk når vi jobber med arrayer. Fordi linjen starter med $:, kjører den når en av verdiene i varer endrer seg. Altså burde vi se en melding i konsollen hver gang vi endrer antall eller navn for en av varene.

100 Kapittel 2

Da vi utførte testen, så loggen slik ut etter at vi hadde lagt til kaffe og epler:

Hvis vi følger med på loggen mens vi utfører testen, er det lett å se når ting går galt. Når vi har gitt et nytt navn til det første objektet i arrayet, bør vi for eksempel se en melding i konsollen, men den dukker aldri opp. Når vi deretter legger til en ny vare i listen, dukker det opp en melding som viser at det første objektet i arrayet aldri fikk en ny verdi.

Hvor tror du det er sannsynlig at feilen ligger med utgangspunkt i det vi har gjort av logging og feilsøking til nå? Hva ville ha vært ditt neste steg i feilsøkingsprosessen hvis du ikke har noen mistanke?

DISKUTER
101Gjenbruk og testing

På dette tidspunktet bestemte vi oss for å lese gjennom all koden som hadde med sammenkobling av listen og Teller-komponenten å gjøre, og da så vi fort hva feilen var. Vi hadde glemt å sette inn bind: foran egenskapen navn i Teller-komponenten. Koden var altså:

1 <Teller

2 navn={vare.navn}

3 bind:verdi={vare.antall}

4 />

Vi oppdaterte koden slik:

1 <Teller

2 bind:navn={vare.navn}

3 bind:verdi={vare.antall}

4 />

Hvis vi retter denne feilen og kjører testene på nytt, blir resultatet som forventet både for testtilfelle #1 og #2.

FEILSØKING ER SJELDEN GØY, MEN FEILEN ER SOM REGEL ENKEL

Når feilsøking forklares i undervisningssammenheng, er det lett å få inntrykk av at det er en enkel og følelsesløs prosess: «Finn feilen, gjør sånn og slik, og vips så har du løst det.» I virkeligheten er feilsøking forbundet med en del frustrasjon. Selv de som har mange års erfaring som programmerere, blir frustrert når koden ikke virker som forventet.

Når vi oppdager årsaken til en feil, virker den ofte veldig åpenbar. Slike feil er både en lettelse og en skuffelse. Det tar kort tid å rette dem opp, men de burde jo ikke ha

102 Kapittel 2

Slik ser src/routes ut når vi jobber med dette delkapittelet.

En samling med funksjoner som kan være til nytte flere steder i et dataprogram, kalles for et bibliotek (library på engelsk).

oppstått i utgangspunktet. Det er imidlertid umulig å ikke gjøre feil i ny og ne, men en god strategi kan være som følger: Fiks, le og lær! Først retter du opp det som gikk galt, så ler du litt, og så gjør du det du kan for å unngå at det skjer igjen. I vårt tilfelle lærte vi at vi alltid må dobbeltsjekke bindinger i koden. Bonusen ble at vi fikk et eksempel vi kunne bruke til å demonstrere feilsøking og testing.

Kanskje skjønte du hva feilen var, allerede før vi begynte å feilsøke. Det er i så fall kjempebra! Det er ofte lettere å se feil i koden som andre har skrevet, enn i koden man skriver selv. Dette er en av grunnene til at programmerere ofte ser over hverandres kode, gjerne mens de skriver den.

2.6 Enhetstester

En enhetstest er en test som sjekker et lite stykke kode, altså en enhet. Det vanligste formålet med en enhetstest er å sjekke at dataene vi får tilbake fra en funksjon, stemmer overens med det vi forventer. I motsetning til testene vi lærte om i delkapittel 2.4, utfører vi ikke disse enhetstestene selv. I stedet skriver vi kode og lar datamaskinen utføre testene for oss.

I dette delkapittelet jobber vi med disse filene:

• bibliotek/hjelpemidler-strenger.js er et bibliotek vi holder på å skrive.

• komponenter/ErLikTest.svelte er en komponent som utfører én enhetstest.

• streng-testsamling/+page.svelte er en testsamling med hjelpemiddelstrenger som bruker komponenten ErLikTest til å utføre tester.

Vi begynner med å lage ErLikTest.svelte som skal regne ut utfallet av en test og si om resultatet er som forventet eller ikke.

1 <!-- komponenter/ErLikTest.svelte -->

2 <script>

3

/** Funksjonen vi ønsker å teste. */

4 exportlet funksjon

5

/** Argumentene funksjonen skal få. Oppgis som et array. */

6 exportlet inndata

7

/** Resultatet vi forventer at funksjonen skal returnere. */

8 exportlet forventetUtdata

9

10 let feil

11 let erLike

12 let resultat

13

14 try {

15 /*

16

17

18

* Når vi skriver "enFunksjon(...etArray)",

* legger datamaskineninn verdiene i etArray

* som argumenter til funksjonen:

19 * Første verdi blir første argument, andre verdi

20 * blir andre argument og så videre.

21 */

103Gjenbruk og testing

22 resultat = funksjon(...inndata)

23 erLike = resultat === forventetUtdata

24 } catch (error) {

25 /*

26

* Fordi funksjon er under utvikling mens vi tester,

27 * kan den krasje. I så fall lagrer vi feilen

28 * til variabelen "feil" og logger den til konsollen.

29 */

30 feil = error

31 console.log(error)

32 }

33 </script>

34

35 <!--

36

Emojier som gjør det lett å se om testene

37 passerte, feilet eller krasjet.

38 Vi har valgt emojier med forskjellig form

39 og farge for å hjelpe fargeblinde.

40 -->

41 {#if feil} {:else if erLike} {:else} {/if}

42 <!--

43 Viser forventede inndata og utdata.

44 Bruker JSON.stringify for å vise kodedetaljer,

45 som hakeparenteser og hermetegn, rundt dataene.

46 -->

47 <span class="data">{JSON.stringify(inndata)}</span>

48 ->

49 <span class="data">{JSON.stringify(forventetUtdata)}</span>

50 <!-- Hvis testen feilet eller krasjet, vil vi vise mer. -->

51 {#if feil || !erLike}

52 <ul>

53 <li> 54 {#if feil} 55 <!--

56 Begrenser oss til feil.message, som er en oppsummering.

57 Brukeren kan åpne konsollen for å se hele feilmeldingen.

58

59

-->

KRASJET: <span class="data">"{feil.message}"</span>

60 {:else}

61 Fikk -> <span class="data">{JSON.stringify(resultat)}</span>

{/if}

</li>

</ul>

{/if}

<style>

.data {

font-family: monospace; /* Kodeskrift */

white-space: pre; /* La alle mellomrom stå. */

}

</style>

Øverst i komponenten har vi angitt følgende egenskaper: funksjon, inndata og forventetUtdata. Ovenfor disse har vi skrevet kommentarer som forklarer hva slags data de skal motta. Like nedenfor har vi angitt de tre variablene feil, erLike og resultat, som vi skal bruke til å lagre utfallet av testen.

104 Kapittel 2
62
63
64
65
66 67
68
69
70
71
72

I de siste linjene i script-blokken kaller vi på funksjonen. Vi har lagt dette funksjonskallet inni en try-catch-blokk. En try-catch-blokk prøver å gjøre det som står mellom krøllparentesene etter try. Hvis det oppstår en feil som ville fått programmet til å krasje, angrer datamaskinen på alt den har gjort hittil, og gjør i stedet det som står mellom krøllparentesene etter catch. Du får se nytten av dette ganske snart.

I HTML-delen av filen viser vi informasjon om hvordan testen gikk. Aller først viser vi en emoji som varierer etter om testen passerte, feilet eller krasjet. Etter emojien viser vi forventede inndata og utdata. Hvis funksjonen krasjet eller testen feilet, viser vi hva som var galt, som et kulepunkt under testen.

Try-catch-blokker

En try-catch-blokk ser slik ut:

1 try {

2 /*

3 * Datamaskinen prøver å gjøre det

4 * som står mellom krøllparentesene,

5 * men hvis en feil som ville fått

6 * programmet til å krasje, oppstår, …

7 */

8 } catch (error) {

9 /*

10 * … angrer datamaskinen på alt den gjorde i try,

11 * og gjør det som står mellom

12 * krøllparentesene etter catch.

13 * Feilen som oppsto, er lagret i parameteren error.

14 */ 15 }

Du kan tenke på en try-catch-blokk som en variant av en if-else-setning: if (alt kjører uten å krasje) { /* gjør det vanlige */ } else { /* gjør noe annet */ }. Forskjellen på en try-catch-blokk og en if-else-setning er at datamaskinen ikke vet hvilken vei den skal velge i trycatch-blokken, før den starter, og derfor må prøve seg frem.

UNNGÅ Å BRUKE TRYCATCH MED MINDRE DU ABSOLUTT MÅ

Try-catch-blokker er en nødløsning. Vi tyr til dem når det viser seg å være umulig å skrive en if-else-setning som forhindrer feilen.

I ErLikTest.svelte tar vi inn en hvilken som helst funksjon. Siden det finnes uendelig mange måter en ukjent funksjon kan krasje på, kan vi umulig skrive en if-else-setning som beskytter oss mot alle disse krasjene. Derfor tillater vi oss å bruke try-catch i ErLikTest.svelte

105Gjenbruk og testing

I oppgavedelen skal du legge inn flere funksjoner i hjelpemidler-strenger.js og lage tester for dem.

LAGE FUNKSJONENE VI SKAL TESTE

Før vi begynner med å lage tester, må vi ha et utkast til det vi skal teste. Vi åpner filen hjelpemidler-strenger.js og lager funksjonen gjoerForbokstavStor. Som tidligere nevnt, er det som regel en fordel å skrive testene før man skriver koden.Derfor setter vi inn en funksjon som bare inneholder return. Da gjør ikke funksjonen noe.

1 // bibliotek/hjelpemidler-strenger.js

2 exportlet gjoerForbokstavStor = (streng) => {

3 return

4 }

BEGYNNE PÅ TESTSAMLINGEN

Vi begynner på testsamlingen ved å lage én enkelt test for funksjonen

gjoerForbokstavStor. Vi åpner filen streng-testsamling/+page.svelte. Vi importerer funksjonen gjoerForbokstavStor og komponenten ErLikTest til denne filen og skriver testen.

1 <!-- streng-testsamling/+page.svelte -->

2 <script>

3 import { gjoerForbokstavStor } from "../bibliotek/hjelpemidler-strenger.js"

4 import ErLikTest from "../komponenter/ErLikTest.svelte"

5 </script>

6

7 <h1>Enhetstester for hjelpemidler-strenger.js</h1>

8

9 <h2>gjoerForbokstavStor</h2>

10 <!-- Legg merke til arrayet i inndataene. -->

11 <ErLikTest

12 inndata={["liten"]}

13 forventetUtdata={"Liten"}

14 funksjon={gjoerForbokstavStor}

15 />

Når vi åpner nettsiden /streng-testsamling, viser den testen som feilet. Dette er et godt tegn, for nå vet vi at ErLikTest-komponenten faktisk kommer til å si fra hvis dataene ikke er som forventet.

LAGE EN DEKKENDE TESTSAMLING FOR gjoerForb okstavStor

Som nevnt i delkapittel 2.4 bør en testsamling være dekkende. Det vil si at den kontrollerer det meste som brukerne kan finne på å gjøre når de bruker programmet.

Vi ser for oss at funksjonene vi lager i hjelpemidler-strenger.js, først og fremst skal brukes av norskspråklige programmerere. Vi kan blant annet sette sammen funksjonene slik at de gjør om en streng som en bruker har skrevet inn, til et egnet variabelnavn, for eksempel «hent2SoekeresultaterFraNorge». Derfor kan vi begrense oss til å teste tilfeller som består av de 29 bokstavene i det norske alfabetet, tall og mellomrom.

106 Kapittel 2

Nedenfor ser du testtilfellene vi har laget. Vi har lagt testtilfellene i arrayet storForbokstavTilfeller, slik at vi kan iterere over dem. I linjen før hver verdi i arrayet har vi skrevet en kommentar om hvorfor vi har med akkurat den verdien.

Nederst har vi laget en each-løkke som lager en ErLikTest-komponent for hvert testtilfelle.

1 <!-- streng-testsamling/+page.svelte -->

2 <script>

3 import { gjoerForbokstavStor } from "../bibliotek/hjelpemidler-strenger.js"

4 import ErLikTest from "../komponenter/ErLikTest.svelte"

5

6

// Første verdi er inndataene, andre er resultatet.

7 let storForbokstavTilfeller = [

8 // Tom streng, fordi man ofte glemmer denne

9 [[""], ""],

10 // Grunntilfelle: én bokstav

11 [["i"], "I"],

12 // Flere bokstaver, men ikke norske

13 [["liten"], "Liten"],

14 // Starter med norsk bokstav

15 [["år"], "År"],

16 // Starter allerede med stor bokstav

17 [["Stor"], "Stor"],

18 // Starter med tall

19 [["1-er"], "1-er"],

20 // Hvis strengen starter med mellomrom, skal ingenting skje.

21 [[" fortsatt liten"], " fortsatt liten"],

22 // Streng som inneholder komma

23 [["ja, vi elsker"], "Ja, vi elsker"],

24 // Ikke bruk store bokstaver etter punktum.

25 [["bare. første"], "Bare. første"],

26 ]

27 </script>

28

29 <h1>Enhetstester for hjelpemidler-strenger.js</h1>

30 <h2>gjoerForbokstavStor</h2>

31 <ul>

32 {#each storForbokstavTilfeller as data}

33 <li>

34 <ErLikTest 35 inndata={data[0]}

36 forventetUtdata={data[1]}

/>

</li>

{/each}

</ul>

funksjon={gjoerForbokstavStor}

107Gjenbruk og testing
37
38
39
40
41

Vi har valgt disse testtilfellene, slik at vi har testtilfeller som starter både med internasjonale bokstaver, særnorske bokstaver, mellomrom og tall. Vi ser for oss at dette representerer de strengene brukerne våre kan tenkes å sende inn til funksjonen. Vi valgte også å ha med punktum, bindestrek og kommaer i noen av strengene (men ikke som første tegn) fordi dette er tegn som ofte forekommer i en norsk tekststreng.

Vi har også tatt med et testtilfelle med en tom streng. Mange funksjoner som fungerer på strenger med ett eller flere tegn, kan krasje hvis strengen er tom. Vi glemmer ofte å tenke på tomme strenger når vi skriver kode, enda det er vanlig når brukeren ikke har skrevet noe i et input-felt.

Tomme strenger og arrayer Det er vanlig at funksjoner må håndtere tomme strenger, for eksempel når et input-felt er tomt. Husk å ta med testdata med tomme strenger for funksjoner som behandler strenger, med mindre du vet at funksjonen aldri kommer til å motta tomme strenger.

Hvis du skriver tester der inndataene er et array, bør du også lage testtilfeller der arrayet er tomt: [].

EKSTRASTOFF

Testtilfeller vi har utelatt

En gang i fremtiden kan det hende vi skal bruke gjoerForbokstavStor på en måte som gir oss større variasjon i inndataene. Vi kunne for eksempel ha brukt funksjonen til å gi brukerne av en chattetjeneste muligheten til å rette meldingene sine automatisk. I så fall burde vi lage testtilfeller der strengene starter med emojier og annet som chattemeldinger typisk starter med. Men siden funksjonen bare skal brukes av programmerere foreløpig, får vi lite igjen for å skrive slike testtilfeller nå. Programmererne skriver sannsynligvis ikke inn slike tegn. Vi kan heller legge til slike testtilfeller etter hvert.

For å si det billedlig: En fabrikk som lager bokseåpnere, tester bare bokseåpnerne på hermetikkbokser, ikke på tankskip og pengeskap.

FÅ FUNKSJONEN TIL Å GJØRE SOM TESTENE VIL

Når vi har skrevet testsamlingen, går det neste steget ut på å få funksjonen til å gjøre det testene ber om. Derfor skal vi fylle ut gjoerForbokstavStor slik at testene lykkes. Gjør gjerne et forsøk selv før du leser løsningsforslaget vårt. Ha testsamlingen åpen i nettleseren og se hva som skjer underveis.

Vi begynner med å returnere strengen akkurat som vi fikk den, og allerede da blir nesten halvparten av tilfellene grønne, det vil si de tilfellene der teksten skal være uendret, men det er i alle fall en start.

108 Kapittel 2

1 // bibliotek/hjelpemidler-strenger.js

2 exportlet gjoerForbokstavStor = (streng) => {

3 return streng

4

}

Nå gjør vi et forsøk på å gjøre første bokstav stor. Etter litt prøving og feiling har vi følgende kode:

// hjelpemidler-strenger.js

exportlet gjoerForbokstavStor = (streng) => {

let foersteBokstav = streng[0]

let resten = streng.slice(1)

return foersteBokstav.toUpperCase() + resten

}

Dette forsøket var stort sett vellykket, men funksjonen krasjer på den første testen i samlingen. For å se hele feilen åpner vi konsollen. Nedenfor ser du hvordan det ser ut i Chrome.

109Gjenbruk og testing

Opplistingen ovenfor viser hvor datamaskinen befant seg i koden da krasjet som vi avverget, oppsto. Når vi skal løse en slik feil, starter vi øverst i listen og jobber oss nedover for å se om vi finner årsaken.

I starten av hver linje står navnet på funksjonen eller komponenten datamaskinen var inni da krasjet oppsto. I slutten av hver linje er det en lenke med formatet filnavn:linjenummer:tegnnummer. Denne angir filen og nummeret på linjen og tegnet der datamaskinen befant seg. Vi kan klikke på lenken for å se filen i utviklerverktøyet, eller vi kan finne filen i utviklerverktøyet. Nedenfor ser du hvor vi havner når vi klikker på det første resultatet.

når vi klikker det første resultatet.

Hvis inndataene e er , altså en helt t tom streng, vet vi atdet

, altså en helt tom streng, vet vi at det skaper trøbbel fordi variabelen foersteBokstav har verdien . Som feilmeldingen sa, kan vi ikke skrive .toUpperCase() i en variabel som inneholder . For å unngå krasjen kan vi sjekke om strengen har lengde 0 og i så fall returnere en tom streng og dermed avslutte kjøringen av koden i funksjonen.

1 // hjelpemidler-strenger.js

2 exportlet gjoerForbokstavStor = (streng) => {

if (streng.length === 0) {

return

let foersteBokstav = streng[0]

let resten = streng.slice(1)

return foersteBokstav.toUpperCase() + resten

Og da går alt

110 Kapittel 2
3
4
"" 5 } 6
7
8
9 }
bra!

REFAKTORERE  GJØRE KODEN MER ELEGANT

Når funksjonen har passert alle testene våre, lagrer vi funksjonen. Deretter prøver vi å finne ut om det er mulig å gjøre funksjonen kortere og mer elegant. Det kalles å refaktorere.

I vårt tilfelle har vi jo måttet legge til en if-setning for å ta høyde for tomme strenger. Finnes det en måte å hente ut første bokstav på der vi ikke ender opp med , slik at vi kan kutte ut if-setningen?

Hvis du ikke kjenner til alle muligheter, kan det være nyttig å lese dokumentasjonen for datatypen du jobber med. I dette tilfellet kan du søke på «w3schools string documentation» på nettet. Da vil «JavaScript String Reference - W3Schools» være et av de øverste resultatene: https://www.w3schools.com/jsref/jsref_obj_string.asp

Hvis du klikker på lenken til dokumentasjonen for charAt, får du vite litt om hvordan funksjonen fungerer. Under overskriften «Return value» står det at resultatet blir en tom treng hvis indeksen er ugyldig, altså hvis det ikke finnes noen bokstav på den nevnte plassen. Da blir "".charAt(0) === "" i stedet for . Dette kan vi teste i konsollen.

111Gjenbruk og testing

Dersom vi bruker streng.charAt(0) i stedet for streng[0] til å hente ut første bokstav, bør det med andre ord være mulig å kutte ut lengdesjekken. Vi endrer koden slik:

1 // bibliotek/hjelpemidler-strenger.js

2 export let gjoerForbokstavStor = (streng) => {

3 let foersteBokstav = streng.charAt(0)

4 let resten = streng.slice(1)

5 return foersteBokstav.toUpperCase() + resten

6 }

Når vi har lagret filen, ser vi en hake i en grønn firkant foran alle testene i listen. Det betyr at de fortsatt lykkes. Nå ser vi ikke noe mer vi kan forbedre, og vi sier oss fornøyd med funksjonen.

Enhetstester

En enhetstest er en test som sjekker om koden oppfører seg som forventet.

Når vi skriver enhetstester, lager vi en samling testtilfeller. Målet er at disse skal være dekkende, altså at de representerer den typen data som vi forventer å få fra brukere.

Vi kan skrive enhetstester for en funksjon etter at vi har laget den, men det beste er å skrive testene før vi skriver funksjonen. Dette kalles testdrevet utvikling og omfatter disse stegene:

1. Skriv en funksjon som ikke returnerer noe.

2. Lag en testsamling med dekkende testtilfeller.

3. Gjennomfør ett og ett testtilfelle og sørg for at alle testtilfellene lykkes. Ofte lykkes flere testtilfeller samtidig.

4. Når alle testtilfellene passerer, refaktorerer du.

2.7 Vanlige problemer når du tester med tall

På grunn av måten datamaskinen lagrer tall på, blir ikke resultatet alltid slik vi forventer. Her er en testsamling vi har laget for funksjonen leggSammen fra filen matematikk.js.

1 // bibliotek/matematikk.js

2 export let leggSammen = (x, y) =>

3 return x

4

112 Kapittel 2
{
+ y
}

1 <!-- matematikk-testsamling/+page.svelte -->

2 <script>

3 import ErLikTest from "../komponenter/ErLikTest.svelte"

4 import { leggSammen } from "../bibliotek/matematikk.js"

5

6

let leggSammenTilfeller = [

7 // Noen enkle heltall

8 [[0, 0], 0],

9 [[0, 1], 1],

10 [[1, 1], 2],

11 // Desimaltall

12 [[0.5, 0.5], 1],

13 [[0.1, 0.2], 0.3],

14 /*

15 * Store tall

16 *

17

* I JavaScript kan man bruke understrekingstegn

18 * for å gjøre lange tall lettere å lese.

19 */

20 [[9_007_199_254_740_991, 1], 9_007_199_254_740_992],

21 [[9_007_199_254_740_991, 2], 9_007_199_254_740_993],

22 [[9_007_199_254_740_991, 3], 9_007_199_254_740_994],

23 [[9_007_199_254_740_991, 4], 9_007_199_254_740_995],

24 ]

25 </script>

26

27 <h1>Enhetstester for matematikk.js</h1>

28

29 <h2>leggSammen</h2>

30 <ul>

31 {#each leggSammenTilfeller as data}

32 <li>

33 <ErLikTest

34 inndata={data[0]}

35 forventetUtdata={data[1]}

36 funksjon={leggSammen}

37 />

38 </li>

39 {/each}

40 </ul>

Utfallet av det femte testtilfellet er uventet: I stedet for 0,3 får vi et langt tall. Og selv om de påfølgende testtilfellene passerer, har vi fått et annet resultatet enn vi oppga, i to av dem, nærmere bestemt i de tilfellene der resultatet skulle ha blitt et oddetall.

113Gjenbruk og testing

DATAMASKINEN LAGRER IKKE ALLE TALL SLIK VI SKRIVER DEM

Årsaken til begge disse feilene er at datamaskinen bruker totallssystemet, der tall bare består av tallene 0 og 1. Derfor er det mange desimaltall datamaskinen ikke klarer å representere nøyaktig. Store heltall er også et problem fordi datamaskinen ikke har plass nok til å lagre dem.

EKSTRASTOFF

Totallssystemet og flyttall

I totallssystemet er det slik at den plassen som står til venstre for desimaltegnet, er verdt 1, og derfra dobler verdien seg for hver plass man går mot venstre: 2, 4, 8, 16, 32 og så videre. Titallssystemet følger et lignende mønster der verdien tidobler seg for hver plass man går mot venstre: 1, 10, 100, 1000 og så videre.

Så lenge vi jobber med heltall, kan vi oversette nøyaktig mellom alle tall i begge systemer. Når vi passerer kommaet, blir ting vanskeligere. Siden vi går mot høyre i titallssystemet, får plassene verdiene 1 10 , 1 100 , 1 1000 og så videre, mens plassene i totallsystemet får verdiene

1 2 , 1 4 , 1 8 og så videre. Det går dessverre ikke an å summere brøkene som står til høyre for kommaet i totallsystemet, og ende opp med brøker som kan forkortes til 1 10 , 2 10 eller 3 10 , altså 0,1, 0,2 og 0,3. Når vi skriver desimaltall, lagrer datamaskinen disse tallene med så mange sifre som det er plass til.

Datamaskinen lagrer store og små tall på en plassbesparende normalform som kalles for flyttall (floating point numbers på engelsk). Hvis vi skal skrive veldig store eller veldig små tall i titallssystemet, kan vi for eksempel skrive én million som 1 · 106 eller én milliontedel som 1 · 10–6. Systemet datamaskinen bruker for å lagre tall, er basert på samme mønster, bortsett fra at den ikke bruker en tierpotens for å forstørre eller forminske verdien, men en toerpotens. For eksempel vil verdien 1 2 bli lagret som 1 · 2–1.

Fordi datamaskinen har en bestemt mengde bits, altså plasser til 1- og 0-tegn, som den kan bruke på eksponenten og på tallet som står foran gangetegnet, klarer den ikke å lagre oddetall nøyaktig hvis tallet er større enn 253 eller mindre enn –253

Hvis du vil se den verdien som datamaskinen egentlig lagrer når du skriver inn et tall, kan du skrive (tallet).toPrecision(100) i konsollen i nettleseren. Da får du tilbake en streng med den verdien som faktisk er lagret (med mange overflødige nuller på slutten). Hvis du bruker toPrecision med tallene 0,1, 0,2 og 0,3, får du se at datamask inen egentlig lagrer følgende verdier (her har vi kuttet bort de bakerste nullene):

• 0,1000000000000000055511151231257827021181583404541015625

• 0,200000000000000011102230246251565404236316680908203125

• 0,299999999999999988897769753748434595763683319091796875

Disse verdiene returneres som strenger, men hvis vi kopierer tallverdien som står mellom anførselstegnene, og limer den inn igjen i konsollen, får vi verdien vi startet

114 Kapittel 2

med: 0,1, 0,2 og 0,3. Det er fordi datamaskinen bruker avrundingsregler når den viser tallverdier. Disse reglene er bestemt slik at overraskende mange tall vises som den verdien vi skrev inn.

Disse avrundingsreglene er imidlertid ikke ufeilbarlige. Selv om vi legger sammen to tall som avrundes riktig, blir ikke resultatet alltid som vi forventer. Regnestykket 0,1 + 0,2 har for eksempel resultatet 0,300000000000000044408920985006261616945266 72363, som datamaskinen runder av til 0.30000000000000004 når den viser tallet. Denne verdien er ikke lik verdien som 0,3 blir konvertert til, og derfor gir 0.1 + 0.2 === 0.3 resultatet false. Som en parallell kan vi forestille oss at vi ble bedt om å vurdere om 1 3 1 3 2 3 , men måtte regne med desimaltall i stedet for brøker. Da ville vi ha skrevet om til 0,333 + 0,333 = 0,666 ≈ 0,67 og funnet at 0,66 ≠ 0,67. Utfallet er feil, men vi kunne ikke ha gjort det noe bedre med de begrensningene vi hadde.

LAGE EN TESTKOMPONENT SOM SAMMENLIGNER

ET VISST ANTALL DESIMALER

For å løse problemet med desimaler som rundes av, i testene våre, kan vi lage en ny komponent, ErLikTestMedPresisjon, som sjekker om resultatet er likt innenfor et visst antall desimaler. Den er stort sett identisk med ErLikTest, men har egenskapen antallDesimaler, som vi bruker for å bestemme hvor mange desimaler tallene skal ha når vi sammenligner dem. Vi velger at denne egenskapen skal ha standardverdien 2. For å runde av tallene bruker vi toPrecision

1 <!-- komponenter/ErLikTestMedPresisjon.svelte -->

2 <script>

export let funksjon

export let inndata

export let forventetUtdata

// Ny egenskap

export let antallDesimaler = 2

let feil

let erLike

let resultat

try {

resultat = funksjon(...inndata)

// Runder av før sammenligning

erLike =

resultat.toPrecision(antallDesimaler) ===

forventetUtdata.toPrecision(antallDesimaler)

} catch (error) {

feil =

console.log(error)

</script>

{#if feil} {:else if erLike} {:else} {/if}

<!-- Lik visning, bortsett fra to detaljer: -->

<span class="data">{JSON.stringify(inndata)}</span>

<span class="data">{JSON.stringify(forventetUtdata)}</span>

<!-- Opplys om antall desimaler etter testen … -->

(innenfor {antallDesimaler} desimaler)

115Gjenbruk og testing
3
4
5
6
7
8 9
10
11
12 13
14
15
16
17
18
19
20
error 21
22 } 23
24 25
26
27
28 -> 29
30
31

32 {#if feil || !erLike}

33 <ul>

34 <li>

35 {#if feil}

36

KRASJET: <span class="data">"{feil.message}"</span>

37 {:else}

38 Fikk -> <span class="data">{JSON.stringify(resultat)}</span>

39 <!-- … og hva det avrundede resultatet var i feilvisningen. -->

40 , som avrundes til

41 <span class="data">{resultat.toPrecision(antallDesimaler)}</span>

42 {/if}

43 </li>

44 </ul> 45 {/if}

46

47 <style>

48 .data {

49

font-family: monospace; /* Kodeskrift */ 50 white-space: pre; /* La alle mellomrom stå. */ 51 } 52 </style>

I matematikk-testsamling/+page.svelte bytter vi til ErLikTestMedPresisjon.

1 <!-- matematikk-testsamling/+page.svelte -->

2 <script>

3 import ErLikTestMedPresisjon from "../komponenter/ErLikTestMedPresisjon.svelte"

4 // Ellers lik script-del

5 </script>

6

7 <h1>Enhetstester for matematikk.js</h1>

8 9 <h2>leggSammen</h2>

10 <ul>

11 {#each leggSammenTilfeller as data}

12 <li>

13 <!-- ... og her bruker vi den nye komponenten. -->

14 <ErLikTestMedPresisjon

15 inndata={data[0]}

16 forventetUtdata={data[1]}

18 funksjon={leggSammen}

19 antallDesimaler={2}

20 />

21 </li>

22 {/each} 23 </ul>

Da blir resultatet:

116 Kapittel 2

Hvis vi sender inn en høyere verdi til egenskapen antallDesimaler, for eksempel 20 med antallDesimaler={20}, vil testen feile igjen, for da er ikke lenger de avrundede verdiene like.

HVA VI SKAL GJØRE MED STORE TALL, AVHENGER AV SITUASJONEN

Du kan se det høyeste heltallet som datamaskinen klarer å lagre nøyaktig, ved å skrive Number.MAX_SAFE_INTEGER. Da får du ut verdien 9007199254740991. Når et heltall er over denne grensen, er det ikke sikkert at datamaskinen klarer å lagre tallet nøyaktig. Hvis datamaskinen ikke klarer å lagre den nøyaktige verdien, runder den av til den nærmeste verdien den klarer å representere. Burde vi gjøre noe med leggSammen for å hanskes med tall som er større enn dette?

Hvis vi kan akseptere litt unøyaktighet, kan vi godt la være å gjøre noe. Det er ikke sikkert at funksjonen leggSammen noensinne skal brukes til å legge sammen tall som er så store som dem vi brukte i denne testen. Number.MAX_SAFE_INTEGER er et veldig stort tall, over 9 billiarder. Når vi jobber med så store tall, blir et avvik på 1 forsvinnende lite – under én billiarddel. I slike situasjoner klarer vi oss som regel fint med et avrundet, litt unøyaktig svar.

I visse sammenhenger er det ikke akseptabelt med unøyaktige tall. Hvis vi for eksempel leter etter store primtall, nytter det ikke å jobbe med en avrundet verdi – da må vi jobbe med det nøyaktige tallet. Hvis leggSammen skal brukes i en slik sammenheng, er det bedre at funksjonen sier fra til brukeren. Nedenfor ser du hvordan vi kan få funksjonen leggSammen til å gi en feilmelding dersom resultatet er for høyt til å være nøyaktig. Da vil testtilfellene si fra når tallet er for høyt.

117Gjenbruk og testing
1 // matematikk.js 2 exportlet leggSammen = (x, y) => { 3 let resultat = x + y 4 if (resultat > Number.MAX_SAFE_INTEGER) { 5 throw new Error( 6 "Resultatet var høyere enn Number.MAX_SAFE_INTEGER" 7 ) 8 } 9 return resultat 10 }

EKSTRASTOFF

Noen tall bør lagres som strenger

En av bokas forfattere hadde en gang et oppdrag for et firma som laget et salgssystem. Dette salgssystemet hadde bestillings-ID-er som besto av tallrekker på 20 sifre. Den dagen firmaet lanserte hjemmesiden sin, fikk de feilmeldinger fra kunder som fikk opp andre bestillinger enn den de hadde søkt på. Feilen viste seg å ligge på nettsiden der kundene skulle taste inn bestillings-ID-en. Etter at kunden hadde tastet bestillings-ID-en inn i et input-felt for tekst, ble den gjort om til et tall. Fordi tall på 20 sifre ligger langt over Number.MAX_SAFE_INTEGER, ble mange tall rundet av til et nærliggende tall som tilsvarte en annen bestilling. De klarte heldigvis å fikse feilen samme dag.

I hverdagen bruker vi ofte tallrekker av ulik lengde for å identifisere personer, steder, bestillinger og lignende. Noen eksempler er fødselsnumre, telefonnumre og postnumre. Disse tallene er godt under Number.MAX_SAFE_INTEGER, men de starter ofte med 0-tegn. JavaScript fjerner overflødige 0-tegn fra starten av et tall, så slike 0-tegn vil forsvinne dersom disse numrene lagres som tall. Skatteetaten.no oppgir «011299 55131» som et eksempel på et fødselsnummer.

Postnumrene i Oslo starter på 0, for eksempel 0010 (postnummeret til Det kongelige slott).

Prøver vi å lagre disse verdiene som tall, kan det skape små og store problemer.

Når vi bruker en tallrekke til å identifisere noe, er det altså best å lagre den som en streng. Da slipper vi å få problemer hvis tallrekken starter på 0 eller blir veldig lang.

Viktige grenser for tall

Number.MAX_SAFE_INTEGER og Number.MIN_SAFE_INTEGER er det høyeste heltallet og det laveste heltallet datamaskinen klarer å representere nøyaktig. Når et heltall befinner seg innenfor dette området, klarer datamaskinen alltid å lagre tallverdien nøyaktig. Når et heltall befinner seg utenfor dette området, runder datamaskinen av til den nærmeste verdien den klarer å lagre. Jo lenger man beveger seg utenfor grensene, desto større blir unøyaktigheten i absoluttverdi, men den er som regel bitte liten i forhold til hvor stort tallet er. Number.MAX_VALUE er det største tallet datamaskinen i det hele tatt klarer å lagre. Denne verdien er større enn 10300, altså et titall med 300 nuller bak. Hvis du skriver inn et tall som er større enn dette, klarer ikke datamaskinen engang å runde det av.

118 Kapittel 2

SAMMENDRAG

> I programmering handler gjenbruk om å eksportere og importere for eksempel funksjoner og variabler fra én fil til én eller flere andre filer. Det er vanlig å lagre funksjoner og variabler som skal eksporteres, i en JavaScript-fil.

> Vi eksporterer en funksjon ved å skrive nøkkelordet export foran klassedefinisjonen, slik: export let funksjonsnavn = ... For å importere en funksjon til en fil skriver vi .

> Vi eksporterer en variabel ved å sette inn nøkkelordet export foran definisjonen av variabelen, slik: export let variabelnavn = ... Vi importerer variabelen ved å skrive .

> Hvis en funksjon eller en variabel har en tydelig hovedrolle i en fil, kan vi gjøre den til filens standardeksport. Når vi skal definere en standardeksport, må vi først definere funksjonen eller variabelen uten å eksportere den: let etEllerAnnet = ... Senere i samme fil skriver vi en linje der det står export default etEllerAnnet. Da er etEllerAnnet blitt filens standardeksport.

> Når vi skal importere en standardeksport, setter vi ikke krøllparenteser rundt navnet når vi importerer den. Dersom standardeksporten ligger i en fil som heter foo.js, og denne filen ligger i samme mappe som filen vi importerer til, skriver vi import etEllerAnnet from "./foo.js".

> Når vi importerer en standardeksport, står vi fritt til å velge et annet navn på eksporten enn navnet den hadde da den ble eksportert. Vi kunne altså også ha skrevet import nyttNavnSelvOmDetErDaarligSkikk from "./foo.js"

> En komponent er en liten bit av en nettside som brukes til å bygge opp en større nettside. En komponent kan brukes i flere filer. Den kan også brukes gjentatte ganger på samme side.

> Alle Svelte-filer eksporterer automatisk seg selv som komponenter, slik at vi kan bruke dem som nettopp det. Vi importerer en Svelte-fil som en komponent med koden import Komponentnavn from "./eventuelle-mappenavn/Filnavn.svelte". Når vi skal bruke komponenter, setter vi vinkelparenteser rundt navnet vi ga komponenten da vi importerte den: <Komponentnavn />

119Gjenbruk og testing

> Vi bruker skrivestilen camelCase når vi navngir variabler og funksjoner: navnetTilVariabelEllerFunksjon

> Vi bruker skrivestilen PascalCase når vi navngir komponenter: Komponentnavn

> Vi bruker skrivestilen kebab-case i navnet på mapper som har filer som skal gjøres om til nettsider: navnet-til-filen/+page.svelte

> Egenskaper er verdier som angis i komponentens tagg. For å si at vi vil ha en verdi fra taggen i en Svelte-komponent, skriver vi en linje som begynner med export let egenskapensNavn. For å angi verdien til en egenskap skriver vi <Komponenten egenskapensNavn={verdien} />

> Vi angir standardverdien til en egenskap slik: export let egenskapensNavn = standardverdi Egenskapen får denne verdien dersom vi ikke angir en annen verdi i komponentens tagg.

> Et testtilfelle er en beskrivelse av hvordan en test skal gjennomføres, og testens forventede resultater. En samling av testtilfeller kalles en testsamling. En testsamling er dekkende dersom testtilfellene er innom alt som kan skje når programmet tas i bruk.

> En enhetstest er en test som sjekker en funksjon for å se om den oppfører seg som forventet. Når vi skriver enhetstester, lager vi en samling testtilfeller. Målet er at disse skal være dekkende, altså at de representerer den typen data som brukerne kan finne på å sende inn til funksjonen.

> Når vi skriver testene før vi skriver programkoden, praktiserer vi testdrevet utvikling.

> Number.MAX_SAFE_INTEGER gir det høyeste heltallet som en datamaskin klarer å representere nøyaktig, mens Number.MIN_SAFE_INTEGER gir det laveste. Number.MAX_VALUE er det største tallet datamaskinen klarer å lagre.

120 Kapittel 2

Oppgaver

2.1 Gjenbruke variabler og funksjoner

2.01

a) Sett at du har én Svelte-fil og én JavaScript-fil som er lagret i samme mappe. Gjør rede for hvordan vi eksporterer variabler og funksjoner fra JavaScript-filen og importerer dem til Svelte-filen.

b) Hvordan kan vi endre navnet til variablene og funksjonene vi importerer til Svelte-filen?

c) Sett at JavaScript-filen ligger i en undermappe til mappen som Svelte-filen er lagret i. Hva må du nå skrive i filstien når du importerer variabler og funksjoner fra JavaScript-filen?

2.02

a) Opprett en mappe på datamaskinen din og gi den navnet gjenbruk. Opprett en JavaScript-fil i denne mappen og gi den navnet konstanter.js

b) I tabellen nedenfor finner du noen konstanter som ofte er brukt i matematikk og i naturfagene. Lagre verdiene for konstantene i variabler i filen konstanter.js.

Navn (enhet) SymbolVerdi Pi 3,14159 Eulertallet e 2,71828

Lysfarten i vakuum (m/s) c 30010 8 ,

Avogadrokonstanten (mol–1) N A 6021023 , Bohrkonstanten (J) B 2181018 ,

c) Eksporter alle variablene med én kodelinje. Tips: export {konstant1, konstant2}

d) Opprett en Svelte-fil og gi den navnet +page.svelte. Du velger selv om den skal ligge i src/routes eller i en undermappe. Importer variablene fra filen konstanter.js.

e) Bruk den importerte verdien for pi til å regne ut arealet av en sirkel. Definer radiusen til sirkelen selv. Vis resultatet med et p-element.

f) Vis den importerte verdien for lysfarten med et p-element. Vis verdien med enhetene m/s og km/s.

2.03

a) Opprett en ny versjon av filen konstanter.js fra oppgave 2.02 og gi den navnet mineVariabler.js.

Du er kanskje vant til å oppgi vinkler i grader. Et annet mål for vinkler er radianer. Vi regner om vinkeltallet fra grader til radianer ved å gange med og dele på 180.

b) Definer en variabel med verdien 180 i mineVariabler.js. Eksporter variabelen.

121Gjenbruk og testing

Vi regner om vinkeltallet fra radianer til grader ved å gange med 180 og dele på

c) Definer en variabel med verdien 180 i mineVariabler.js. Eksporter variabelen.

d) Lag et program med et input-felt der brukeren kan angi en vinkel i grader. Brukeren skal kunne klikke på en knapp og få frem vinkeltallet i radianer.

e) Utvid programmet med et nytt input-felt der brukeren kan angi en vinkel i radianer, og en ny knapp som brukeren kan klikke på for å få frem vinkeltallet i grader.

2.04

Vi kan bruke bilder fra Internett på våre egne nettsider. Da kan vi kopiere lenken til bildet og lime den inn i koden.

a) Lag en tabell med to rader og tre kolonner. Gi den en stil du liker.

b) Gå til en nettbutikk og velg ut tre varer. Høyreklikk på hvert varebilde og velg «kopier bildeadressen». Lagre bildeadressene som strenger i variabler.

Vi kan vise bilder på en nettside med img-elementet, slik: <img src="bildeadresse">. Legg merke til anførselstegnene rundt bildeadressen.

c) Vis bildene i den første raden i tabellen. Skriv varenavnene i den andre raden. Bildet nedenfor viser én mulig løsning.

2.05

For å bruke bilder som er lagret lokalt på datamaskinen, på en nettside må vi først lagre bildene i mappen static i et SvelteKit-prosjekt.

a) Lagre noen bilder du har tatt selv, i mappen static. Gi bildefilene korte og relevante navn.

b) Bruk img-elementet og vis bildene på en nettside. Som verdi til src-attributtet bruker vi filstien til bildet.

c) Det finnes mange CSS-stiler for img-elementet. Bruk Internett til å finne ulike CSS-egenskaper og prøv dem ut.

2.06

Nedenfor ser du HTML-koden som trengs for å lage en nedtrekksmeny. Med bind:value binder vi en valgt verdi til en variabel, mens on:change kaller på en funksjon vi har kalt giMelding.

1 <select bind:value={valgt} on:change={giMelding}>

2 <option value="velg"> </option>

3 <option value="poteter"> poteter </option>

4 <option value="gulrøtter"> gulrøtter </option>

5 <option value="tomater"> tomater </option>

6 </select>

122 Kapittel 2

a) Lag en nedtrekksmeny med tre av dine favorittgrønnsaker.

b) Lag en funksjon som returnerer en streng om hvilken grønnsak brukeren har valgt. Dersom brukeren endrer valget sitt, skal meldingen oppdateres umiddelbart.

c) Legg til to nye grønnsaker i nedtrekksmenyen. Bildet nedenfor viser én mulig løsning.

2.07

a) Opprett en ny JavaScript-fil og gi den navnet mineFunksjoner.js. Definer en funksjon i denne filen som genererer et tilfeldig heltall mellom to gitte tall. Kall denne funksjonen tilfeldigTallMellom (min, maks). Eksporter funksjonen, slik at du kan gjenbruke den i senere oppgaver.

b) Lag et program der brukeren kan oppgi verdier for tallene min og maks og klikke på en knapp for å generere det tilfeldige tallet mellom min og maks.

2.08

La n være et heltall. I matematikken sier vi at n!, som leses «n-fakultet», er produktet av alle tall fra 1 til n. For eksempel regner vi ut 5! slik: 554321120 !

a) Definer fakultet-funksjonen i filen mineFunksjoner.js fra oppgave 2.07. Eksporter funksjonen, slik at du kan gjenbruke den i senere oppgaver.

b) Bruk fakultet-funksjonen til å regne ut fakultetet til et tilfeldig tall generert av funksjonen tilfeldigTallMellom (min, maks) fra oppgave 2.07.

2.09

a) Skriv tallene 1, 2 og 3 på hver sin lapp. Brett lappene og bland dem godt. Trekk først én lapp og deretter én til. Du skal ikke legge den første lappen tilbake før du trekker den andre. De to tallene du trakk, er sifrene i et tosifret tall. Hvor mange forskjellige tosifrede tall kan du få?

Måten du trakk lapper på for å danne et tosifret tall i oppgave a, kalles et ordnet utvalg fordi rekkefølgen er av betydning.

Når vi har n objekter og skal trekke r av dem uten å legge objektene tilbake mellom hvert trekk, kan vi bruke denne formelen til å regne ut antall mulige kombinasjoner (permutasjoner):

P n nr ! () !

b) Lag en ny funksjon i mineFunksjoner.js som tar imot n og r som argumenter og returnerer antall mulige permutasjoner. Gi funksjonen navnet ordnetUtvalg. Eksporter funksjonen, slik at du kan gjenbruke den i senere oppgaver.

123Oppgaver

c) Lag et program hvor brukeren kan oppgi tallene for n og r og klikke på en knapp for å regne ut antall mulige permutasjoner vi kan lage med disse n tallene, og vise alle permutasjonene. Tips: Det er lettest å definere n som en streng som inneholder tallene som kan trekkes. For eksempel skal funksjonskallet ordnetUtvalg ("123", 2) returnere «Antall ordnede utvalg: 6» og «Ordnede utvalg: [12, 13, 21, 23, 31, 32]».

2.10

a) Lag en ny funksjon i mineFunksjoner.js som tar imot to tall og regner ut gjennomsnittet av dem. Kall funksjonen gjennomsnittAv (a, b).

b) Lag en ny funksjon i mineFunksjoner.js som tar imot et array som vi kaller minetall, og som regner ut summen av tallene. Kall funksjonen sumArray(mineTall)

c) Lag et program hvor brukeren kan oppgi en mengde tall i et eget input-felt av typen string og klikke på en knapp for å regne ut gjennomsnittet av alle tallene. Be brukeren om å skrive et komma mellom hvert av tallene, slik: 10,22,33,45. Tips: String-metoden split(",") kan komme til nytte.

2.11

I naturfag har du kanskje lært om arveanlegget til alle levende organismer, nemlig DNA-molekylet. DNA-molekylet består av to komplementære DNA-tråder. Hver tråd består blant annet av fire forskjellige nitrogenbaser som kalles A (adenin), C (cytosin), T (tymin) og G (guanin). Disse nitrogenbasene kommer i en tilsynelatende tilfeldig rekkefølge. Det er slik at A fra den ene tråden alltid er koblet til T fra den andre tråden. Det samme gjelder for C og G. Studer figuren nedenfor nøye.

A

GG AA C TTT CCC AA C ATT

T CC TT G AAA GGC TT G TAA

U CC UU G AAA GGC UU G UA

Den komplementære tråden DNA-tråd mRNA-tråd DNA-molekyl A

a) Lag en funksjon i filen mineFunksjoner.js som tar imot n nitrogenbaser som input og genererer én enkelt DNA-tråd med n nitrogenbaser. Kall funksjonen lagDNAtråd (n).

b) Lag en ny funksjon som tar imot en DNA-tråd som input og genererer den komplementære tråden. Kall funksjonen lagKompDNA (DNA_tråd)

En av de viktigste oppgavene til DNA er å lage proteiner. Denne prosessen starter med at et bestemt utsnitt av én av DNA-trådene kopieres. I denne kopieringsprosessen, som heter transkripsjon, byttes alle T-ene ut med en annen nitrogenbase som heter U (uracil). Ellers er resten av nitrogenbasene akkurat de samme som i originalen. Kopien som dannes, heter Messenger DNA, eller mRNA, og inneholder oppskriften til et protein.

c) Lag en tredje funksjon som tar imot en DNA-tråd som input og lager en tilsvarende mRNA. Kall funksjonen lagmRNA (DNA-tråd).

d) Lag et program hvor brukeren kan oppgi antall nitrogenbaser i en DNA-tråd. Bruk funksjonen fra oppgave c til å finne det tilsvarende mRNA-et. Husk å importere alle nødvendige funksjoner.

124 Kapittel 2
… … … … … …

2.12

En vektor er et linjestykke med en bestemt lengde og retning. Fysiske størrelser som forflytning og krefter beskrives best som vektorer fordi de har en bestemt lengde og retning. Med symboler skriver vi vektoren som går fra punktet A(x1, y1) til punktet

B(x2, y2), slik: AB . Vi finner vektorkoordinatene til vektoren slik: ABxxyy[,] 2121 . Vi kan lagre vektorkoordinatene som et array med to elementer.

I et koordinatsystem tegner vi en vektor som en pil, slik som i figuren nedenfor.

2 1 3 4 5

A =(1,2) B =(6,5)y x 2 134567

AB =(5,3)

a) Lag en ny funksjon i mineFunksjoner.js som tar imot fire tall for koordinatene til punkt A og B og returnerer et array med vektorkoordinatene til vektoren fra A til B. Kall funksjonen vektor (x1, y1, x2, y2)

Lengden til en vektor er den korteste avstanden mellom punkt A og B som definerer vektoren. Vi regner ut lengden av vektoren AB slik: ||()() ABxxyy 21 2 21 2

b) Lag en ny funksjon som tar imot en vektor (array) og returnerer lengden av denne vektoren. Kall funksjonen lengde(vektor)

c) Lag en interaktiv nettside hvor brukeren kan skrive inn fire tall for koordinatene til to punkter og klikke på en knapp for å regne ut lengden til vektoren mellom punktene.

2.13

I denne oppgaven skal du lage to nye funksjoner med vektorer. Det er veldig nyttig å vite hvordan to vektorer står i forhold til hverandre, spesielt om to vektorer står vinkelrett på hverandre eller ikke. Vinkelen mellom to vektorer er alltid mellom 0 og 180 grader.

Studer figuren nøye før du går videre.

Når vi skal regne ut vinkelen mellom to vektorer, får vi bruk for skalarproduktet, som er en måte å gange to vektorer med hverandre på. Vi regner ut skalarproduktet til vektor ux y [,] 11 og vx y [,] 22 slik:

125Oppgaver
2 1 0 –1 –2 3 =53,1301° y x v u 2 134567
u vxxyy 1212

a) Lag en funksjon som tar imot to vektorer, u = [x1, y1] og v = [x2, y2], som argumenter og regner ut skalarproduktet. Kall funksjonen skalarprodukt (vektor1, vektor2).

b) Lag en funksjon som tar imot to vektorer, u og v, som arrayer og regner ut vinkelen mellom vektorene ved å bruke formelen

cos |||| 1 uv uv

Kall funksjonen vinkelenMellom (vektor1, vektor2).

c) Lag en interaktiv nettside hvor brukeren kan skrive inn to vektorer i egne input-felter og klikke på en knapp for å regne ut vinkelen mellom vektorene. Husk å importere nødvendige funksjoner.

2.14

Mengden karbondioksid (CO2) som slippes ut ved forbrenning av ulike fossile brennstoffer, varierer mye. I tabellen nedenfor ser du en oversikt over gjennomsnittlige CO2-utslipp per kg av ulike fossile brennstoffer.

Type brennstoff CO2-utslipp per kWh produsert energi

Ved 0,42 kg CO2 / KWh

Brunkull0,29 kg CO2 / kWh

Naturgass 0,23 kg CO2 / kWh

Biodiesel 0,24 kg CO2 / KWh

Metan 0,18 kg CO2 / kWh

a) Lag en funksjon som lager en tabell med det samme innholdet som i tabellen ovenfor. Kall funksjonen lagUtslipsptabell().

b) Lag en ny funksjon som tar imot typen brennstoff som argument og returnerer CO2-utslippsdataene for brennstoffet. Kall funksjonen utslippFor(brennstoff)

c) Lag en ny funksjon som tar imot både typen brennstoff og ønsket mengde energiproduksjon i kWh som argumenter og returnerer det totale CO2-utslippet i kg. Kall funksjonen utslippDataFor(brennstoff, energimengde).

d) Søk på Internett og finn utslippsdata for flere typer brennstoff. Lag en interaktiv nettside hvor brukeren kan angi typen brennstoff og ønsket mengde energiproduksjon i kWh. Nettsiden skal regne ut og vise CO2-utslippet i kg. Importer alle nødvendige funksjoner.

2.15

a) Søk og finn to–tre ulike valutakalkulatorer på Internett. Gjør deg godt kjent med hvordan de virker. Skriv ned vekslingskursen til norske kroner for fire ulike valutaer.

I denne oppgaven skal du lage en enkel variant av en valutakalkulator. Funksjonene du lager, skal lagres i filen mineFunksjoner.js.

b) Lag en funksjon som lager en oversikt over hvor mye hver av de fire utenlandske valutaene er verdt i forhold til 1 norsk krone.

126 Kapittel 2

c) Lag en funksjon med én parameter for beløpet (norske kroner) vi ønsker å veksle, og én parameter for valutaen vi ønsker å veksle til. Funksjonen skal returnere beløpet vi kan få av den utenlandske valutaen.

d) Lag en ny funksjon med tre parametere: beløpet vi vil veksle, valutaen vi ønsker å veksle fra, og valutaen vi ønsker å veksle til. Kall funksjonen veksleFraTil (beløp, fraValuta, tilValuta).

e) Lag en interaktiv nettside og design alle elementene som trengs for at brukeren skal kunne veksle et beløp fra én valuta til en annen. Husk å eksportere og importere alle nødvendige funksjoner.

2.16

Innenfor elektronikk brukes Kirchhoffs 1. lov, som sier at den totale mengden strøm som går inn i et kontaktpunkt, er lik den totale mengden strøm som går ut fra punktet. Strøm som går inn i kontaktpunktet, regnes med positivt fortegn, mens strøm som går ut fra punktet, regnes med negativt fortegn.

I figuren nedenfor ser vi fem ledninger som er koblet sammen i kontaktpunktet K. I to av ledningene går det elektrisk strøm inn i kontaktpunktet, og i tre av ledningene går det elektrisk strøm ut fra punktet. Figuren nedenfor angir strømstyrkene.

I1 =2A

I5=3A

I2 = 8A

I3 = 2A K

10 A går inn i kontaktpunktet, og 10 A går ut fra punktet.

I4 =5A

a) Anta at det går strøm gjennom to ledninger inn i et kontaktpunkt. La arrayet strømInn ha to elementer, ett element for strømmengden i hver ledning. Lag en funksjon som tar imot arrayet som argument. Funksjonen skal fordele den totale inngående strømmengden til to utgående ledninger og returnere de to utgående strømmengdene i et array med to elementer. Kall funksjonen strømUt(strømInn)

b) Generaliser funksjonen fra a slik at strømInn kan ha et vilkårlig antall elementer, og slik at vi med en parameter kan angi hvor mange ledninger den utgående strømmen skal fordeles til. Kall funksjonen fordelStrøm (strømInn, antallLedningerUt).

c) Lag en nettside hvor brukeren først kan oppgi inngående strøm og ønsket antall utgående ledninger i to input-felter og deretter kan klikke på en knapp for å fordele den inngående strømmen til ledningene.

127Oppgaver

2.17

Et svar fra en blodundersøkelse viser som regel en liste over mengden kjemiske stoffer pasienten har i blodet. Slike kjemiske stoffer er for eksempel hemoglobin, natrium, kalium, protein, kolesterol, jern og lymfocytter. Legene sammenligner mengden av disse stoffene med referanseverdier. Det regnes som normalt å ha en verdi mellom disse referanseverdiene. Det regnes som unormalt å ha verdier som er utenfor referanseverdiene.

Type stoff HemoglobinNatriumKaliumProteinJernLymfocytter Referanseverdier 13,4–17,0137–1453,6–5,062–7810,0–25,01,5–6,5

a) Lag en nettside som viser denne tabellen.

b) Utvid mineFunksjoner.js med en ny funksjon som tar imot navnet til et av stoffene fra tabellen ovenfor og returnerer referanseverdiene til stoffet. Kall funksjonen RefVerdiTil(stoffnavn).

c) Lag en ny funksjon som sjekker om en verdi for et gitt stoff er innenfor referanseverdiene eller ikke. Kall funksjonen erNormalt (stoffnavn, pasientensVerdi)

d) Utvid nettsiden fra oppgave a slik at en pasient kan oppgi verdier for stoffene i egne input-felter og klikke på en knapp for å sjekke om verdiene er innenfor referanseverdiene.

e) Søk på Internett og finn ut hvilke medisinske råd som gis til pasienter som har unormale verdier av stoffene i tabellen. Lag en ny funksjon som gir pasienten et passende råd dersom han eller hun har unormale verdier av ett eller flere stoffer.

2.2 Lage nettsidekomponenter og gjenbruke dem

2.18

I teoridelen viser vi hvordan du kan lage en enkel navigasjonsmeny og bruke den som en komponent på flere nettsider. Lag din egen variant av navigasjonsmenyen og bruk komponenten på tre nettsider.

2.19

Nederst på nettsidene til ulike bedrifter er det vanlig å finne et felt med overskriften «Kontakt oss» som inneholder besøksadressen, telefonnummeret og e-postadressen til bedriften.

a) Lag en enkel visning av kontaktinformasjonen til en bedrift. Lagre koden i en egen Svelte-fil. Husk stor forbokstav i filnavnet.

b) Importer kontaktinformasjonen som en komponent til en annen Svelte-fil og vis den på en nettside.

128 Kapittel 2

2.20

Vi skal lage en nettside som har mange undersider som komponenter. Temaet er fakta om frukter.

a) Lag en komponent hvor du definerer en variabel for ananas i form av HTML-koden for ananas-emojien: "&#127821". Skriv noen korte faktasetninger om ananas og finn en lenke til en nettside som forteller mer om ananas. Lagre denne komponenten som Ananas.svelte.

b) Lag en komponent for vannmelon med samme oppbygning som i oppgave a. Lagre denne komponenten som Vannmelon.svelte.

c) Vis komponentene fra oppgave a og b på hovedsiden. Bildet nedenfor viser hvordan nettsiden kan se ut.

d) Utvid nettsiden med tre nye frukter. Bruk vanlige bilder for de nye fruktene.

2.21

a) Lag en komponent med en rund knapp. Knappeteksten skal være et ensifret tall.

b) Bruk komponenten fra oppgave a til å utforme et talltastatur med tallene fra 0 til 9.

c) Når en bruker klikker på en av talltastene, skal tallet vises på skjermen. Når brukeren klikker på flere knapper, skal de forskjellige tallene legges til i visningen.

d) Lag en ny knapp og funksjon for å fjerne alle tallene som brukeren har tastet inn.

e) I hvilke situasjoner kan et talltastatur være mer hensiktsmessig enn et vanlig tastatur i mobilapper?

To vanlige måter å organisere talltastene på.

129Oppgaver

2.22

Vi ønsker å lage en forenklet versjon av periodesystemet for grunnstoffer der vi deler grunnstoffene i tre hovedkategorier: metaller, halvmetaller og ikke-metaller. Nettstedet skal bestå av fem sider som brukeren kan navigere mellom: Hjem, Periodesystemet, Metaller, Halvmetaller og Ikke-metaller. Opprett et eget SvelteKit-prosjekt for denne oppgaven.

a) Gå til https://www.periodesystemet.no/, velg filteret «metalliske egenskaper» og gjør deg godt kjent med hvilke metalliske egenskaper grunnstoffene kan ha, og hvor i periodesystemet de ulike egenskapene er fordelt.

b) Lag et nettsted med følgende innhold:

• Hjem: Her ønsker vi å ha en kort intro om nettstedet.

• Periodesystemet: Denne siden skal bestå av et bilde av det fullstendige periodesystemet.

• Metaller: På denne siden kan du lage en oversikt over minst ti ulike metaller. Ta med både navnet og det kjemiske symbolet til grunnstoffene.

• Halvmetaller: På denne siden skal du liste opp alle halvmetallene.

• Ikke-metaller: På denne siden skal du liste opp alle ikke-metallene.

c) Lag en komponent for navigasjonen slik at brukeren enkelt kan navigere mellom de fem sidene. Navigasjonslinjen kan for eksempel være en tabell med én rad og fem kolonner.

2.3 Lage interaktive komponenter

2.23

Hva er forskjellen mellom skrivestilene kebab-case, PascalCase og camelCase? Når bruker vi de ulike skrivestilene?

2.24

Ta utgangspunkt i talltastaturet fra oppgave 2.21. Gjør det mulig for programmeren å angi tallet på knappen med en egenskap, for eksempel slik: <TallTast tall="1" />.

2.25

a) Lag et nytt SvelteKit-prosjekt og kall det hilseVenner. Lag en ny fil i mappen src/ routes og kall den +page.svelte hvis den ikke finnes fra før.

b) Lag en ny mappe med navnet Komponenter. Opprett en ny fil i mappen og kall den Hilse.svelte.

c) Legg inn en overskrift på nivå 3 i Hilse.svelte. Overskriften kan være «Skriv navnet til en venn her».

d) Sett inn et input-felt for tekst etter overskriften i oppgave c. Navnet som brukeren skriver inn, skal bindes til en variabel. Når brukeren har skrevet inn navnet sitt, skal han eller hun få en hilsen, for eksempel «Hei på deg, Henrik».

e) Importer hilsekomponenten i +page.svelte-filen. Legg inn et eksemplar av komponenten og sjekk at den fungerer som den skal.

130 Kapittel 2

2.26

a) Opprett et eget SvelteKit-prosjekt for denne oppgaven og kall det Nedtrekksmeny. Hovedfilen til prosjektet er +page.svelte. Legg til en annen fil og kall den DropdownMenu.svelte.

b) Lag en overskrift med teksten «Sommeraktiviteter» i DropdownMenu.Svelte. Overskriften skal være midtstilt, og hele siden skal ha en fin bakgrunnsfarge.

c) Sett opp en nedtrekksmeny med fem ulike sommeraktiviteter, for eksempel kano, orientering, klatring, fiske og svømming. Brukeren skal få beskjed om hvilket alternativ som er valgt.

d) Legg komponenten inn i +page.svelte-filen. Åpne nettsiden i en nettleser og sjekk om du kan velge en aktivitet fra listen.

e) Oppdater DropdownMenu.svelte slik at den samme brukeren kan velge flere aktiviteter. Tips: Attributtet multiple gjør det mulig å velge flere alternativer fra samme nedtrekksmeny. Bildet nedenfor viser én mulig løsning.

131Oppgaver

2.4 Teste et helt dataprogram

2.27

a) Hva mener vi med begrepet test innenfor programmering?

b) Hva vil det si at en test passerer?

c) Gjør rede for begrepene testtilfelle og testsamling.

d) Hva vil det si at en test er dekkende?

e) Hva er forskjellen mellom den-glade-sti-testtilfellet og realistiske tilfeller?

f) Velg ut ett eller flere programmer du har laget tidligere, og test dem.

2.28

I denne oppgaven skal du teste programmet nedenfor.

1 <script>

2 let tekst = "Skriv eller kopier inn tekst med små og STORE bokstaver."

3

4 const stor = () => {console.log(tekst.toUpperCase())}

5 const liten = () => {console.log(tekst.toLowerCase())}

6 </script>

7

8 <input style="height:200px; width:600px;" bind:value={tekst}/> <br />

9 <button on:click={stor(tekst)}> STOR </button>

10 <button on:click={liten()}> liten</button>

Merk at vi bruker Svelte-editoren i nettleseren. Når vi skal ta utskrift bruker vi Consolevinduet, så sørg for at du ser hele Console-vinduet.

a) Skriv en testsamling for dette programmet.

b) Gjennomfør det første testtilfellet du har satt opp. Hva ble resultatet av testen?

c) Gjennomfør de andre testtilfellene du har satt opp.

d) Knappen merket med «liten» skal gjøre all teksten om til små bokstaver. Test om den fungerer etter intensjonen. Snakk med en medelev og finn ut hva du må gjøre for at denne knappen skal fungere som den skal.

2.29

I denne oppgaven skal du teste programmet nedenfor. Programmet skal generere en firesifret PIN-kode hvis brukeren oppgir riktig brukernavn og passord.

Math.round(9999*Math.random())

inn både brukernavn og passord."

132 Kapittel 2
1 <script> 2 let brukernavn = "" 3 let passord = "" 4 let pinkode = "" 5 6 const sendPin = () => { 7 if(passord.length < 8) { 8 pinkode = "Passordet er for kort!" 9 } else { 10 pinkode = "PIN-kode: " +
11 } 12 if(brukernavn == "" || passord == "" ){ 13 pinkode = "Skriv

14 }

15 console.log(pinkode)

16 }

17 </script>

18

19 <body style="background-color: khaki">

20 <h1>PIN-kodegenerator</h1>

21 <p> Skriv inn brukernavn og passord (minst 8 tegn) for å lage en PIN-kode.</p>

22 Brukernavn: <input bind:value={brukernavn}/> <br />

23 Passord: <input bind:value={passord}/> <br />

24 <button style="background-color: tomato" on:click={sendPin}>

25 LAG PIN-kode

26 </button>

27 </body>

a) Skriv en testsamling for denne appen. Husk å markere alle testtilfellene med en egen ID.

b) Gjennomfør hvert testtilfelle og noter om testen passerer eller feiler.

c) Generer veldig mange PIN-koder ved å klikke på knappen. Er alle PIN-kodene firesifrede?

d) Hvordan kan du forbedre programmet slik at PIN-koden alltid blir firesifret?

2.30

Ta utgangspunkt i talltastaturet fra oppgave 2.21 (og eventuelt oppgave 2.24). Lag en testsamling for programmet og gjennomfør testene. Få en medelev til å utføre de samme testene. Får dere samme resultat?

2.5 Feilsøking

2.31

a) Hva går feilsøking ut på?

b) Hvilke strategier kan du bruke når du feilsøker?

c) Hvor kan du søke etter hjelp dersom du ikke finner feilen?

2.32

Besøk nettstedene nedenfor og gjør deg kjent med dokumentasjonen for HTML, CSS, JavaScript og Svelte. Lag gjerne bokmerker til det du tror du kan få bruk for senere.

• www.w3schools.com

• https://svelte.dev/docs

• https://kit.svelte.dev/docs

133Oppgaver

2.6 Enhetstester

2.33

Vi skal utføre en enhetstest på et enkelt program som konverterer temperatur fra grader celsius til kelvin. Som du kanskje husker fra tidligere, er sammenhengen mellom kelvin (K) og grader celsius (°C)gitt ved formelen K = °C + 273.15.

a) Lag et program som består av et input-felt for temperaturen i grader celsius.

b) Lag en funksjon som konverterer den inntastede verdien til kelvin og viser svaret på nettsiden.

Bildet nedenfor viser én mulig løsning.

c) Bruk følgende verdier for å lage en enhetstest for funksjonen du laget i oppgave b: Input-verdiene [273.15, 0, 100, 5000] i celsius skal gi output-verdiene [0, 273.15, 373.15, 5273.15] i kelvin. Får du noen feil i testresultatene med disse verdiene?

d) Gjør om plusstegnet i formelen K = C + 273.15 til gangetegn (*) og kjør enhetstesten fra oppgave c på nytt. Hva blir resultatene av enhetstesten nå?

e) Gjør om desimaltegnet i formelen til et komma, altså K = C + 273,15. Gjenta enhetstesten.

f) Ut fra formelen vet vi at 0 kelvin tilsvarer –273,15 °C. Det er den absolutt laveste temperaturen som er fysisk mulig. Snakk med en medelev og finn ut hvordan dere kan forbedre programmene deres slik at de ikke viser lavere temperaturer enn 0 kelvin.

134 Kapittel 2

2.34

Vi skal utføre en enhetstest som tilsvarer den vi utførte i forrige oppgave, men nå skal

vi bruke sammenhengen mellom temperatur i grader fahrenheit (°F) og grader celsius (°C): °F = 32 + °C · 9/5.

a) Ta utgangspunkt i koden fra oppgave 2.33 a og b. Endre formelen, men legg inn denne feilen: Skriv 9,5 i stedet for 9/5.

b) Bruk følgende testverdier til å lage en enhetstest for funksjonen som konverterer fra grader celsius til grader fahrenheit: Input-verdiene [–273.15, 0, 37, 100] i grader celsius skal gi output-verdiene [–459.67, 32, 98.6, 212] i grader fahrenheit.

c) Rett opp feilen i formelen og kjør enhetstesten på nytt. Se nøye på testresultatene.

2.7 Vanlige problemer når du tester med tall

2.35

a) Lag et enkelt program hvor brukeren kan skrive inn et tall. Tallet skal vises med 50 desimaler, slik at vi får et innblikk i tallet datamaskinen lagrer.

b) Skriv inn noen heltall. Lagres tallene med helt eksakte verdier?

c) Skriv inn disse desimaltallene: 0,1, 0,25, 1,5, 1,6 og 1,75. Hvilke lagres med helt eksakte verdier? Hvorfor er det slik, tror du?

d) Hvordan kan vi ta høyde for at datamaskinen ikke kan representere alle tall eksakt, når vi programmerer og tester?

2.36

a) Hvilken verdi får du når du viser tallet Number.MAX_SAFE_INTEGER på en nettside?

b) Skriv tallet du fikk i oppgave a, i input-feltet fra oppgave 2.35. Øk tallet med én og noter deg tallet som vises. Gjenta femten ganger. Hva legger du merke til?

135Oppgaver

Brukervennlighet

I dette kapittelet skal du jobbe for å nå disse kompetansemålene:

> vurdere brukervennligheten i egne og andres programmer og foreslå forbedringer

> utforske og vurdere alternative løsninger for design og implementering av et program

3.1 Hva er brukervennlighet?

Har du noen gang slitt med å forstå hvordan du skal bruke en app? Eller irritert deg over at du får feilmelding mens du skriver inn en opplysning i et skjema?

Når du tar i bruk produkter, enten det er en app, en nettside eller en digital tjeneste, blir du i IT-verdenen ansett som en bruker. Hvis du som bruker ikke forstår hvordan du skal bruke et produkt, er det ikke nødvendigvis du som har gjort noe feil. Det kan like gjerne være at de som har laget produktet, ikke har vurdert brukervennligheten til produktet godt nok.

Vi bruker ordet produkt som en samlebetegnelse for nettsider, apper og digitale tjenester.

Brukervennlighet, eller brukskvalitet (usability på engelsk), er et begrep vi bruker for å beskrive produkter som har egenskaper eller kvaliteter som gjør at de kan bli brukt. For at et produkt skal bli kalt brukervennlig, må det oppfylle følgende kriterier:

• Det må være lett å lære seg å bruke produktet.

• Det må være lett å huske hvordan det brukes.

• Det må være effektivt å bruke.

3

• Det må være vanskelig å gjøre feil.

• Det må være enkelt å rette opp i feil.

• Produktet må ha funksjonalitet som er nyttig for brukerne.

Tenk tilbake på den første gangen du åpnet boka du har foran deg nå, og på senere leseopplevelser. Hva tenkte du da du så forsiden og innholdsfortegnelsen og senere dykket ned i selve boka? Alle disse tankene og erfaringene du har gjort deg med de forskjellige kontaktpunktene i boka, det vil si forsiden, tittelen, forordet, innholdsfortegnelsen og kapitlene, påvirker helhetsinntrykket ditt av boka.

Erfaringene du gjør deg når du leser boka eller bruker et produkt, blir kalt en brukeropplevelse. På engelsk kalles det user experience, som forkortes til UX. I motsetning til brukervennlighet handler ikke brukeropplevelsen bare om hvorvidt det er mulig å bruke et produkt, men også om hvordan det er å ta det i bruk. Er det morsomt? Er det strevsomt? De som lager et produkt, kan for eksempel legge inn animasjoner eller illustrasjoner for å gjøre det morsomt å bruke produktet, eller de kan legge til detaljer som gir produktet personlighet og det lille ekstra. Summen av slike detaljer kan være med på å gi brukeren en god opplevelse. Brukeropplevelsen er altså den totale opplevelsen du får når du bruker et produkt.

Brukeropplevelsen er ikke noe vi kan designe, men vi kan prøve å forbedre de forskjellige kontaktpunktene i produktet (nettsidene, appene, kontakten med kundeservice), for det er de som til sammen skaper en god eller dårlig brukeropplevelse.

137Brukervennlighet

Brukervennlighet og brukskvalitet er synonymer og viser til egenskapene eller kvalitetene i et produkt som gjør at det er mulig å ta det i bruk.

Brukeropplevelse viser til den totale opplevelsen brukerne har når de bruker et produkt. Den skapes i de ulike kontaktpunktene mellom brukeren og produktet.

DISKUTER

Har du noen gang brukt en nettside som var så vanskelig å bruke at du ble irritert? Kan du huske om det var noe som var spesielt vanskelig eller tregt å gjøre på nettsiden?

EKSEMPEL

Har du noen gang fylt ut et skjema på en nettside og opplevd å få feilmelding idet du skriver inn dataene, altså før du har rukket å skrive inn noe feil? I så fall bidro sikkert dette til å gi deg en dårlig brukeropplevelse.

Det kan være irriterende å få opp feilmeldinger før du har rukket å fylle ut et felt.

DISKUTER

Har du brukt en app eller en nettside som er så god å bruke at den gjør deg glad? Klarer du å beskrive hvorfor den gjorde deg glad?

138 Kapittel 3

Forsiden til nav.no er kategorisert etter situasjoner som brukerne kanskje befinner seg i når de besøker nettsiden. Hver situasjon er dessuten illustrert med et ikon som gjør det lettere å finne frem til rett innhold. Dette er et eksempel på design som kan bidra til å gi brukerne en god brukeropplevelse.

Lengst oppe på nettsiden i det øverste bildet finner vi blant annet situasjonene «Arbeidssøker eller permittert», «Trenger hjelp til å komme i jobb», «Venter barn» og «Pensjon». Dette er situasjoner mange av oss kommer til å befinne oss i en eller annen gang i livet. Da er det bra at disse situasjonene er plassert slik at de er lett tilgjengelige for brukerne.

Nav kunne valgt å presentere innholdet på andre måter på forsiden. De kunne for eksempel fremstilt det alfabetisk eller vist frem alle undersidene til nettstedet. Men dette kunne fort skapt rot og gjort det vanskelig å finne frem for brukerne. Hvis nettsiden inneholder for mye informasjon, kan det bli vanskelig for brukerne å finne frem til det de egentlig leter etter. Nav har valgt å vise frem undersidene til nettstedet i navigasjonsmenyen i stedet (den man får opp når man trykker på «Meny»-knappen).

Navigasjonsmenyen til nav.no viser undersidene til nettstedet.

3.2 Hvem lager gode brukeropplevelser?

Det er lett å glemme at alle produkter og tjenester er laget av mennesker, og at disse menneskene har tatt valg i design- og utviklingsprosessen som har ført til at du sitter igjen med den opplevelsen du har av produktet.

De fleste produktene vi omgir oss med, er laget av mennesker som har jobbet sammen i team. Gode brukeropplevelser er ofte et resultat av godt samarbeid. Her gjør selvsagt designerne som jobber spesielt med brukeropplevelsen, en viktig jobb, men resten av teamet må også være opptatt av å lage gode brukeropplevelser.

Gode brukeropplevelser er også et resultat av godt håndverk. Sett at du bruker et produkt og det oppstår en feil. Dersom noen har tenkt gjennom dette scenarioet på forhånd og bestemt at du i slike tilfeller skal få en forståelig tilbakemelding som gjør

139Brukervennlighet
EKSEMPEL

at du selv kan rette opp feilen, vil du sitte igjen med et godt inntrykk av produktet (og av dem som har laget produktet). Og det at du selv kan rette opp feilen, vil være tidsbesparende både for deg og for dem som har laget produktet. Hvis du ikke kunne rette opp feilen selv, hadde du kanskje måttet kontakte kundeservice for å finne ut hva som har skjedd. Å legge vekt på gode brukeropplevelser er gunstig for alle!

INTERAKSJONSDESIGN

En interaksjonsdesigner er en person som jobber med å gjøre interaktive produkter og tjenester brukervennlige. Digital interaksjonsdesign handler ofte om å utforme brukergrensesnitt (UI/user interface på engelsk), det vil si knapper, tekstbokser og andre elementer som brukes til å manipulere og kommunisere med en datamaskin. Hvordan skal for eksempel knappene se ut, og hvor på siden de bør plasseres? Interaksjonsdesign handler stort sett om å ta valg som sørger for at det er mulig å bruke digitale tjenester og produkter, og at de er enkle og fornøyelige å ta i bruk.

Interaksjonsdesigneren må gjøre seg kjent med hva slags problemer som skal løses, og så komme med forskjellige løsningsforslag. Vi kan tenke på interaksjonsdesignere litt som forskere: De har en hypotese (antakelse) om hva som kan fungere, før de tester ut mulige løsninger. Til slutt ender de opp med den løsningen som fungerer best.

Interaksjonsdesignerne må tenke som brukere og ta utgangspunkt i brukernes mål og behov når de foreslår ulike løsninger. En av interaksjonsdesignernes oppgaver går ut på å gjennomføre aktiviteter som hjelper dem med å finne ut hvilke mål og behov brukerne har, for eksempel gjennom brukerundersøkelser. Deretter er målet å lage et design som treffer brukerne og støtter brukernes mål og behov. Senere kan de gjennomføre brukertester for å finne ut om det de har designet, er forståelig og lett å bruke.

140 Kapittel 3

Interaksjonsdesign er et fagområde som kombinerer blant annet grafisk design, informasjonsarkitektur og tjenestedesign. Grafisk design handler om fargebruk, visuell oversikt, skrifttyper og merkevareprofil, mens informasjonsarkitektur handler om hvordan informasjon skal grupperes og struktureres slik at det blir lett å finne frem. Tjenestedesign handler om å få oversikt over de forskjellige kontaktpunktene til et produkt og innsikt i hva slags informasjon brukerne trenger, og når de trenger den. Målet med interaksjonsdesign er å skape en så god brukeropplevelse som mulig.

Løsningen man til slutt ender opp med, må være teknisk mulig å lage, den må være i tråd med forretningsmålene, og den må være brukervennlig. Interaksjonsdesign er derfor et fag som krever både logiske, analytiske og kreative evner.

For å finne ut om en løsning er teknisk mulig å lage, må interaksjonsdesignerne samarbeide med utviklerne, de som skriver koden. For å finne ut om en løsning er i tråd med forretningsmålene, må de samarbeide med personer som kjenner strategien bak produktet som skal utvikles.

Et forretningsmål for musikktjenesten Spotify kan for eksempel være å få flere kunder til å betale for tjenesten ved å tilby betalende kunder unik funksjonalitet.

Det er mulig å bruke Spotify uten å betale, men da kan du bare spille av sanger i tilfeldig rekkefølge, og det er reklameinnslag mellom sangene. I 2019 hadde Spotify en konversjonsrate på 46 prosent. Konversjonsraten viser hvor mange betalende kunder det er i forhold til det totale antallet brukere. Spotify har selvsagt satt seg godt inn i hvordan folk bruker musikktjenester. De bruker all kunnskapen de har om brukernes adferd, til å lage en tjeneste som gir gratiskundene en helt grei brukeropplevelse og de betalende kundene en enda bedre brukeropplevelse.

Et annet designknep Spotify bruker, er at de lar deg hoppe til neste sang på avspillingslisten åtte ganger før du blir fortalt at du har kommet til en funksjon som krever at du betaler for å fortsette. Legg også merke til at knappen du må trykke på hvis du ikke vil oppgradere abonnementet, ikke sier «No thanks», men «Not now». Denne detaljen kan virke ubetydelig, men den er designet bevisst for at du skal tenke «Ikke nå, men kanskje senere?».

3.3 Hvordan lage en god brukeropplevelse?

Å designe er en form for problemløsning. Godt design handler imidlertid ikke bare om problemløsning, men om å finne de rette problemene å løse.

Se for deg en flyplass der det viser seg at mange av de reisende ikke finner frem til rett gate i tide. Flyplassen vil fremstå som moderne og ønsker derfor å lage en mobilapp som skal hjelpe folk med å navigere rundt på flyplassen. De engasjerer en interaksjonsdesigner og et par utviklere og ber dem om å lage en mobilapp som skal forbedre de reisendes opplevelse av flyplassen.

EKSTRASTOFF
141Brukervennlighet
You discovered a Premium feature! PREMIUM FEATURE Upgrading to Spotify Premium will unlock it. UNLOCK PREMIUM NOT NOW

FEM HVORFORSPØRSMÅL

Hvis vi vil finne ut om vi løser de rette problemene, kan vi bruke en øvelse som vi kan kalle for fem-hvorfor-spørsmål-øvelsen (The 5 whys; Norman, 2013). Denne øvelsen går ut på at vi stiller oss selv fem hvorfor-spørsmål for å finne ut om vi har forstått hvilket problem vi skal løse. Hvis vi ikke forstår hvilket problem vi skal å løse, risikerer vi å lage en løsning til feil problem. Her er et eksempel på hvordan øvelsen kan utarte seg for interaksjonsdesigneren som ble engasjert av den ovennevnte flyplassen:

• Flyplassen ønsker å lage en mobilapp som skal hjelpe de reisende med å finne frem til restauranter, toaletter og riktig gate på flyplassen.

• Hvorfor finner ikke de reisende frem i dag?

• De er stresset og har dårlig tid.

• Hvorfor er de stresset og har dårlig tid?

• Det er ofte mye kø i sikkerhetskontrollen, så de bruker lang tid på å komme seg gjennom den.

• Hvorfor er det mye kø i sikkerhetskontrollen?

• Det er ikke nok ansatte i sikkerhetskontrollen, og flyplassen har for få metalldetektorer

• Hvorfor er det ikke nok ansatte i sikkerhetskontrollen?

• Hvor mange reisende som skal gjennom sikkerhetskontrollen, varierer fra dag til dag, og flyplassen kan ikke ha for mange på jobb i sikkerhetskontrollen på rolige dager. Det betyr at flyplassen ikke har nok ansatte til å ta seg av de reisende på de travleste dagene.

• Hvorfor finner ikke flyplassen ut hvor mange ansatte de bør ha på jobb på de travleste dagene?

• Flyplassen har ikke systemer som kan forutse dette.

Her går det frem at problemet, altså det som gjør at folk ikke finner frem på flyplassen, er at de er stresset og har dårlig tid. Kan en app hjelpe dem i denne situasjonen?

Hvis vi tenker gjennom hva de reisende på en flyplass har med seg, finner vi fort ut at en mobilapp forutsetter at de reisende

• har en smarttelefon, noe de fleste, men ikke alle har

• er koblet til wifi eller mobilnett, noe som kan være vanskelig hvis man er tilreisende fra et annet land

• har tid til å laste ned og ta appen i bruk

Med tanke på at GPS fungerer veldig dårlig innendørs, forutsetter en mobilapp også at flyplassen finner en god måte å hente posisjonen til mobiltelefonene på.

Hvis vi ser nærmere på det som kom frem i svarene på de fem hvorfor-spørsmålene, viser det seg at det er mange andre ting flyplassen kan gjøre noe med, og at en mobilapp ikke nødvendigvis er den beste løsningen på problemet. Flyplassen kan blant annet

142 Kapittel 3

• utvikle et system som forutser trafikken i sikkerhetskontrollen, slik at den kan planlegge og tilpasse bemanningen bedre

• øke kapasiteten i sikkerhetskontrollen og kjøpe inn flere metalldetektorer

• plassere et stort kart over flyplassen akkurat der de reisende kommer ut av sikkerhetskontrollen

• be restaurantene om å opplyse hva som er vanlig ventetid på mat, eller utvikle et system der de reisende kan bestille mat på forhånd

• informere de reisende om hvor lang tid før avreise de bør ankomme flyplassen

Flyplassen kan utvikle en mobilapp som kan være til hjelp for de som har god tid på flyplassen, men de bør ikke prioritere å gjøre dette først. Flyplassen bør heller samle inn mer informasjon fra de reisende og få en dypere forståelse av hvorfor de ikke finner frem til gaten i tide. Deretter kan de finne ut hvilke tiltak de kan sette inn for å skape en best mulig brukeropplevelse for de reisende.

143Brukervennlighet

DESIGNPROSESS

For å finne ut hvilke problemer vi egentlig prøver å løse, og for ikke å bruke for lang tid på feil løsning, kan vi følge en oppskrift. Denne oppskriften blir gjerne kalt for designprosess, og den kan bestå av fasene nedenfor.

• Utforske – forstå brukerne og deres mål, utfordringer og oppgaver

• forstå hva vi skal løse

• forstå hvem vi skal løse det for

• kartlegge brukernes behov

• kartlegge eksisterende løsning eller praksis og eventuelle konkurrerende løsninger

• Utforme – vurdere mulige løsninger for at brukerne skal nå målene sine

• utarbeide forskjellige konsepter (ideer)

• beskrive designet i detalj (farger, fonter osv.)

• konkretisere hva som skal lages

• lage prototype, det vil si sette sammen ulike skjermbilder for å få en oversikt over strukturen til et konsept og gjøre det mulig å gjennomføre en brukertest av konseptet

• Utvikle – detaljere og lansere produktet

• spesifisere hva og hvordan noe skal lages

• utføre systemtest og akseptansetest

• lansere det endelige produktet

• Evaluere – finne ut om det vi har laget, fungerer i praksis

• gjennomføre brukertester

• gjennomføre ekspertevalueringer

Hovedmålet med en designprosess er å sørge for at teamet konsentrerer seg om riktige ting til riktig tid. Det er for eksempel ikke lurt å bestemme farger og fonter før vi har forstått hvilke behov brukerne har, og hvordan vi skal ivareta dem.

En designprosess er iterativ. Det vil si at du repeterer noen steg eller aktiviteter flere ganger. For hver iterasjon finner du ut hva som fungerer og ikke fungerer, gjennom prøving og feiling. Derfor er det ikke så farlig om den første versjonen av produktet ikke er helt perfekt. Da har du kanskje lært noe om hva som ikke fungerer, og kan prøve noe annet i neste iterasjon.

Gjennom hele designprosessen bør du evaluere (vurdere/teste) løsningen og involvere ekte brukere for å forsikre deg om at du har god forståelse for problemet du skal løse, og at det du har laget, kan hjelpe brukerne med å utføre oppgavene sine. Dette kan du gjøre ved å gjennomføre brukertester, helst med noen du vet kommer til å bruke det du lager, eller ved å få en annen fagperson til å gå gjennom løsningen.

UTFORSKE

Det er viktig å ikke forelske seg i én løsning, men å utforske mange forskjellige løsninger for å finne frem til den som kan ivareta brukernes behov på best mulig måte. Den enkleste måten å finne frem til en god idé på, er å samle mange ideer.

Kilde: Nordbø,
144 Kapittel 3
2017

Vi kan lage enkle skisser og prototyper på papir.

Det er viktig at du husker på at det ikke er du som er brukeren. Husk også at et produkt gjerne blir brukt i en spesiell sammenheng av brukere som har et bestemt mål. Hvis du skal lage et produkt som skal brukes i en politibil, må du ta høyde for at brukerne kan være stresset eller opptatt av å lytte til politiradioen. Det betyr at du for eksempel må sørge for at eventuelle knapper er lette å trykke på, og at displayet ikke viser for mye informasjon på én gang. Det vil også være strenge krav til personvern siden politiet betjener sensitive data.

I utforskingsfasen kan det være nyttig å snakke med noen som skal ta i bruk det du lager. Still åpne spørsmål, altså spørsmål som starter med hva og hvorfor, for å forstå hvilke mål de har med å bruke produktet. Lager du noe som du vet skal brukes i en spesiell sammenheng, kan det være lurt å observere brukerne i akkurat den sammenhengen. Hvis du skal forbedre eller erstatte et produkt de allerede bruker, er det fint om du kan observere dem mens de bruker dette produktet.

UTFORME OG UTVIKLE

Når du har fått en god forståelse for hva målet med produktet er, og en god oversikt over hvem du skal lage det for, kan du begynne å skissere mulige løsninger. Dette kan du gjøre enkelt med penn og papir eller en skisseprogramvare, eller du kan gjøre det på en litt mer komplisert måte ved å kode en løsning.

For å finne ut om en idé er god, må du lage en testversjon, ofte kalt en prototype, som du tester på brukerne. Da begynner du med å tenke gjennom stegene brukerne må ta for å komme i gang og gjennomføre det de vil bruke produktet til. Deretter lager du en enkel prototype. Det er viktig at du ikke bruker lang tid på å lage prototypen, for det er bare en midlertidig løsning. Poenget med denne fasen er å teste flere ideer og finne ut hvilken av dem som fungerer best.

145Brukervennlighet

Prototypen kan som nevnt gjerne være en enkel skisse på papir, noe som ofte kalles for lavnivåskisser og -prototyper. En av fordelene med å gjøre det enkelt, er at de du tester prototypen på, vil forstå at det ikke er et ferdig produkt og dermed vil gi ærligere tilbakemeldinger. De vil også føle at de kan påvirke sluttresultatet ved å bidra tidlig i prosessen. En annen fordel er at det går raskt å lage lavnivåskisser og -prototyper.

I den andre enden av skalaen har vi høynivåskisser og -prototyper. Da bruker vi materiale (komponenter, farger, fonter, knapper osv.) som etter planen skal være med i den endelige versjonen av produktet. Slike skisser og prototyper bruker vi gjerne hvis vi skal kommunisere med utviklere eller andre og forklare dem hvordan de skal utforme et konsept eller en løsning, eller hvis vi ønsker en prototype som fremstår som et ferdig produkt. En ulempe med å designe høynivåskisser og -prototyper er at de du kommuniserer med, kan henge seg opp i feil detaljer, og at vi ikke får svar på det vi ønsker hvis vi bruker dem i en brukertest. Brukerne kan da henge seg opp i farger eller skrivefeil i stedet for å konsentrere seg om innholdet eller om flyten i programmet virker logisk for dem.

EVALUERING

For å finne ut om det du lager, er liv laga, kan du som nevnt ovenfor gjennomføre en brukertest. Finn en håndfull (rundt fem) testpersoner som er typiske brukere av produktet du skal lage. Gi dem oppgaver individuelt som dekker den funksjonaliteten du ønsker å teste. Få tydelig frem at dette ikke er en test av dem, men at de skal hjelpe deg med å lage et godt produkt. Be dem tenke høyt når de bruker prototypen eller produktet ditt. Det er viktig at du ikke hjelper dem mer enn nødvendig, slik at du forstår hvordan de tenker og oppfører seg. Si fra om at det er lov å gi opp hvis de sitter fast og ikke finner ut hvordan de skal gå videre. Gi dem gjerne en liten gave som takk for hjelpen!

Når alle testpersonene har prøvd ut prototypen eller produktet, oppsummerer du det du har funnet ut. Deretter bruker du resultatene til å forbedre prototypen eller produktet til neste test.

Med én gang du har ideer som du ikke klarer å velge mellom, er det lurt å gjennomføre en brukertest. Ikke spør brukerne hva de synes om ideene dine, for det er ofte stor forskjell på hva folk sier de vil ha, eller hvordan de sier de kommer til å bruke noe, og hvordan de faktisk bruker det. Da er det bedre å observere hvordan de faktisk bruker produktet ditt. Husk at alle feil brukerne gjør, bidrar til at du kan lage et bedre produkt.

EKSTRASTOFF

Som regel gjør testpersonene mange feil som virker helt ulogiske for dem som laget systemet. Testpersonene får kanskje ikke øye på informasjon som er helt åpenbar, og de trykker kanskje ikke på de forventede knappene. Når vi blir presentert for mye informasjon, forsøker hjernen vår å finne den informasjonen som sannsynligvis er relevant. Når brukeren ikke får med seg relevant informasjon, kan det tyde på at plasseringen av informasjonen er feil eller at den ikke er synlig nok. For å lage et brukervennlig system, må vi tilpasse systemet etter hvordan folk faktisk tenker og handler, og ikke etter hvordan vi ser for oss at de handler, eller ønsker at de skal handle.

146 Kapittel 3

Tenk deg at du går inn i en matbutikk du aldri har vært i før, og skal finne melk og havregryn. Hvordan finner du ut hvordan du skal lete? Leser du skiltet på toppen av alle hyllene, eller bruker du annen informasjon til å finne frem?

Gå til en nettbutikk for dagligvarer. Hvordan finner du melk og havregryn i nettbutikken?

3.4 Mål for brukskvalitet

Mål for brukskvalitet er et designprinsipp som vi kan bruke for å sørge for at vi lager produkter med høy brukskvalitet/brukervennlighet og unngår de verste designproblemene. Vi kan også bruke mål for brukskvalitet for å evaluere egne og andres produkter.

Vi bruker Preeces seks mål for brukskvalitet (Sharp et al, 2019) for å diskutere hvordan vi kan lage og forbedre produkter med tanke på brukskvalitet:

• anvendbarhet (effectiveness)

• effektivitet (efficiency)

• sikkerhet (safety)

• nytte (utility)

• lett å lære (learnability)

• enkelt å huske når man først har lært det (memorability)

Det er vanlig å stille hjelpespørsmål til hvert av målene for brukskvalitet. Hjelpespørsmålene skal hjelpe designeren med å reflektere over arbeidet. De kan også fungere som en sjekkliste man kan gå gjennom selv eller sammen med andre. Spørsmålene bør være så konkrete som mulig. For eksempel er spørsmålet «Hvor lang tid tar det for en ny bruker å finne ut hvordan hun skal bruke den grunnleggende funksjonaliteten?» mer konkret enn «Er det lett å lære seg programmet?». Jo mer konkret et spørsmål er, desto lettere er det å finne ut hvordan man kan forbedre produktet.

Anvendbarhet er et generelt mål som handler om hvor god løsningen er til å gjøre det den er ment å gjøre. Hvis løsningen ikke fungerer for dem som skal bruke den, spiller det ingen rolle om alle målene for god brukskvalitet er oppfylt. Det er viktig å være oppmerksom på hvilket problem produktet skal løse for brukerne, eller hvilket mål de har med å bruke produktet.

Får kundene kjøpt klær i nettbutikken? Får lærerne vurdert arbeidet til elevene sine? Vi kan få svar på slike spørsmål ved hjelp av spørreundersøkelser, intervjuer eller brukertester eller ved å analysere data som viser hvor i appen eller nettsiden brukerne trykker, hvordan de havnet der, eller hvor de faller av, for eksempel i en kjøpsprosess.

DISKUTER
147Brukervennlighet

Når det er snakk om handlinger som brukerne ikke kan angre på, kan det være lurt å legge inn en bekreftelsesdialog.

Effektivitet handler om at det skal være raskt for brukerne å navigere og utføre oppgaver. Får brukerne gjennomført oppgavene sine på en effektiv måte? Kan vi redusere antall klikk som kreves for at de skal komme i mål? Kan vi gjøre om på strukturen på nettsiden hvis vi ser at mange gir opp og heller bruker søkefunksjonen?

Sikkerhet kan handle om å hindre at brukerne gjør feil, og å gjøre det enkelt for dem å rette opp eventuelle feil.

Er det enkelt for brukerne å angre hvis de har slettet et dokument? En teknisk løsning for å oppnå dette kan være å legge dokumentene i en midlertidig søppelkasse, slik at de ikke blir slettet med én gang. Da kan dokumentet gjenopprettes hvis brukerne angrer senere.

Dette målet handler også om at brukerne skal være sikre på at data som skal bli helt slettet, faktisk blir det. Når de tømmer søppelkurven, skal det ikke være tvil om at det de har slettet, er borte for godt.

Sikkerhet kan også handle om utformingen av grensesnittet. Det er for eksempel ikke lurt å plassere en sletteknapp rett ved siden av en lagreknapp, for da er det fort gjort for brukeren å klikke på feil knapp. Ved å plassere lagreknappen og sletteknappen på forskjellige steder eller i forskjellige steg kan vi gjøre det litt vanskeligere å ta feil valg.

Det er også vanlig å bruke bekreftelsesdialoger der brukerne må bekrefte at de vil utføre handlingen de prøver å gjøre. Slik dialoger bør imidlertid ikke brukes for ofte og spesielt ikke når handlingene er av mindre betydning.

Tøm handlekurv

Er du sikker på at du vil tømme handlekurven?

Denne handlingen kan ikke angres.

Avbryt

Jeg er sikker, tøm

Nytte handler om at produktet skal ha funksjoner som er nyttige for brukerne, at brukernes behov blir ivaretatt, og at brukerne kommer i mål med det de skal gjøre. Det finnes faktisk verktøy som er irriterende å bruke, men som likevel har mange brukere fordi de har en spesiell nytteverdi for folk.

Lett å lære. Kan brukerne ta i bruk produktet uten å måtte sette seg inn i altfor mye på forhånd? Hvis for eksempel brukerne av en kokebok-app må lese en detaljert veiledning for å komme i gang med appen, vil de sannsynligvis velge en annen kokebok-app som er lettere å ta i bruk. Hvis du har laget et produkt, er det kanskje best å

148 Kapittel 3

finne ut om produktet er lett å lære gjennom brukertesting, eller å introdusere funksjonaliteten litt etter litt. Gjør det enkelt for brukerne å komme i gang!

Enkelt å huske når man først har lært det. Dette målet er ganske selvforklarende. Er det enkelt for brukerne å hente frem igjen kunnskapen de tilegnet seg forrige gang de brukte produktet? Dette er spesielt relevant for produkter som ikke skal brukes så ofte. Siden brukerne antakelig bruker mer tid på andre produkter enn ditt, bør du sørge for at de kjenner seg igjen i det du lager. Når du designer for å skape gode brukeropplevelser, er det lurt å stjele ideer fra tjenester og produkter du vet fungerer bra. Det er som regel kloke hoder bak populære løsninger, og det kan du godt dra nytte av!

EKSEMPEL

Du har sikkert vært borti funksjonen som lar deg oppdatere innholdet i en app ved å dra fingeren nedover skjermen. Denne funksjonen ble oppfunnet i 2008 av Appleansatte Loren Brichter, som på fritiden laget Twitter-applikasjonen Tweetie for iOS.

Funksjonen, eller interaksjonsmønsteret, er ganske intuitiv og lar brukeren selv bestemme når innholdet skal oppdateres. Når innholdet oppdateres automatisk, er det lettere for brukeren å miste oversikten.

I dag er dette interaksjonsmønsteret tatt i bruk i nesten alle innholdsrike apper. Det er ikke bare et tegn på at Brichter er en smart fyr, men også et eksempel på at alle kan dra nytte av gode ideer. Det er med andre ord mange interaksjonsdesignere som synes at denne løsningen er så god at de har valgt å bruke den i sine egne produkter. Når vi lager nye produkter, er det ofte lurt å bruke – eller la seg inspirere av – gode eksisterende løsninger som mange brukere allerede kjenner til, fremfor å lage våre egne fra bunnen av.

Dra for å oppdatere.

Brichter fant opp interaksjonsmønsteret som gikk ut på å dra fingeren nedover skjermen for å oppdatere innholdet, i smarttelefonens spede begynnelse. Da hadde det ikke etablert seg noen gode standarder for hvordan vi mennesker bruker smarttelefoner ennå. Det faktum at dette var et mer behagelig interaksjonsmønster enn de eksisterende alternativene – som gjerne var en knapp du måtte finne frem til og trykke på – gjorde at dette etter hvert ble en standard i innholdsrike apper på smarttelefoner.

Trekk ned Oppdaterer Oppdatert
149Brukervennlighet

Kanskje du kan være med og finne opp nye interaksjonsmønster for moderne teknologi som virtuell virkelighet, VR (virtual reality på engelsk), eller blandet virkelighet (mixed reality på engelsk)?

3.5 Ekspertevaluering

Ekspertevaluering er en type test som blir gjennomført av eksperter (deg selv, kollegaer, andre som kan mye om design eller teknologi). Vi kan bruke en slik test hvis vi ikke har tilgang til brukere, eller når vi vil evaluere brukskvaliteten til et produkt. Den kan bli gjennomført av én eller flere eksperter, og den kan også være god sjekkliste som vi kan gå gjennom for å rette opp de verste feilene før vi gjennomfører en brukertest.

Den danske professoren Jakob Nielsen er en av verdens mest anerkjente eksperter på å lage gode brukergrensesnitt. Tidlig i 1990-årene laget han ti heuristikker eller tommelfingerregler som kan hjelpe oss med å utforme brukervennlig interaksjonsdesign. Heuristikkene til Nielsen har blitt et av de mest brukte verktøyene under ekspertevalueringer, og vi kan også bruke dem som prinsipper når vi designer. Det fine med disse heuristikkene er at de er like relevante enten du lager en brødrister eller et VR-spill. De er basert på psykologi ved at de tar hensyn til at den menneskelige hjernen utvikler seg saktere enn teknologien.

Når du skal gjennomføre en ekspertevaluering ved hjelp av Nielsens heuristikker, tar du for deg produktet du har laget, og vurderer om det bryter med noen av heuristikkene. Hvis det gjør det, må du finne ut hvordan du kan fikse det.

150 Kapittel 3

Nielsens ti heuristikker

1. Sørg for at systemets status er synlig.

2. Systemet og den virkelige verden må stemme overens.

3. Gi brukeren kontroll og frihet.

4. Vær konsekvent og følg standarder.

5. Forhindre feil.

6. La brukerne gjenkjenne fremfor å huske.

7. Sørg for at systemet er fleksibelt og raskt å bruke.

8. Utform systemet på en estetisk og minimalistisk måte.

9. Hjelp brukeren med å kjenne igjen, diagnostisere og rette opp feil.

10. Tilby hjelp og dokumentasjon. (Nielsen, 2020)

I resten av dette delkapittelet skal vi se nærmere på hver enkelt heuristikk.

1. SØRG FOR AT SYSTEMETS STATUS ER SYNLIG

Dette prinsippet handler om klar kommunikasjon. Hva skjer når brukerne trykker på en knapp? Får de tilbakemelding på at det de gjør, har en effekt? Får de nok informasjon til å ta gode valg? Hvis brukerne er usikre eller må gjette på statusen for en oppgave fordi de får vage beskjeder fra systemet, er det et tegn på at dette prinsippet er brutt.

Tenk deg at du har satt på en vaskemaskin. Hvordan vet du at den er ferdig med å vaske?

Tenk deg at du skal handle en genser i en nettbutikk. Du har funnet riktig farge og størrelse, og du velger å kjøpe den. Når du trykker på «Kjøp», forteller en animasjon deg at genseren legges til i handlekurven, og det dukker opp et tall i handlekurven for å indikere at du har lagt til en vare. Uten animasjonen hadde det ikke kommet klart frem at genseren hadde blitt lagt til i handlekurven. Det kunne ha gjort deg usikker og gitt deg en dårlig brukeropplevelse.

2. SYSTEMET OG DEN VIRKELIGE VERDEN MÅ STEMME OVERENS

Dette rådet handler om at vi bør bruke ord og konsepter som stemmer overens med den virkelige verden, altså verden slik den fremstår for brukeren og ikke for datamaskinen.

Den som har innsikt i programkoden til et system, har en tendens til å velge ord som stemmer overens med den forståelsen personen har som programmerer. Hvis en programmerer lager en nettside der bibliotekarer skal legge til nye bøker i en database med data som tittel og forfatter, kan programmereren for eksempel synes at

DISKUTER
151Brukervennlighet

Når noen ringer, kan vi trykke på den grønne knappen for å ta telefonen eller den røde for å avvise samtalen.

knappeteksten «Lag bok» gir mening. Når bibliotekarene trykker på knappen, lagres kanskje informasjonen i en variabel med navnet bok i dataprogrammet. Fra bibliotekarenes ståsted er knappeteksten forvirrende. Det er jo ikke de som lager boka, det er det forfatteren og forlaget som har gjort.

3. GI BRUKEREN KONTROLL OG FRIHET

Det er menneskelig å gjøre feil. Ofte er det slik at de som bruker produktet du lager, ikke går den stien du har planlagt, eller leser alle instruksjonene og feilmeldingene som du har lagt opp til. Derfor er det lurt å sørge for at det er vanskelig å gjøre feil og enkelt å rette dem opp. Har du tenkt på hva som skjer hvis brukerne ikke har nett? Sørg for at du gir brukerne en beskjed som gjør at de forstår hvorfor det de gjør, ikke fungerer.

4. VÆR KONSEKVENT OG FØLG STANDARDER

Hvert produkt har en avsender, og avsenderen har gjerne et designspråk. Dette språket bør gå igjen i hele produktet for å sikre at designet blir likt overalt. Hvis en grønnfarge signaliserer positiv status én plass og brukes på overskrifter en annen plass, kan dette føre til at brukerne blir forvirret, og at de ikke lenger kan stole på det de har lært, nemlig at grønnfargen er en positiv beskjed.

Siden brukerne antakelig bruker mer tid på andre produkter enn ditt, er det viktig at du bruker standarder, språk og konsepter de er vant med fra disse produktene. Brukerne forventer at nettbutikker skal være utformet og oppføre seg noenlunde likt. Hvis en nettbutikk bryter veldig med konvensjonelle nettbutikker, kan kundene bli frustrerte og heller begynner å se etter en annen nettbutikk.

5. FORHINDRE FEIL

Det er lurt å tenke gjennom hvilke feil brukerne kan gjøre underveis, og formidle hvordan de kan rette dem opp, på en forståelig måte. Det kan også være lurt å hindre at det oppstår feil ved å bruke bekreftelsesdialoger, men vær oppmerksom på at det kan være irriterende for brukerne å måtte bekrefte at de vil gjøre noe de med vitende og vilje har gått inn for å gjøre. Derfor kan det noen ganger være lurt å gjøre det lett for brukerne å angre på en handling i stedet for å be om bekreftelse.

6. LA BRUKERNE GJENKJENNE FREMFOR Å HUSKE

Det er enklere å kjenne igjen noe enn å huske det. Da de første datamaskinene kom, hadde de ikke noe grafisk brukergrensesnitt, og brukerne måtte huske og skrive inn kommandoer for å navigere. Et grafisk brukergrensesnitt med menyvalg, som er standard i dag, gir brukerne en bedre brukeropplevelse siden de slipper å huske kommandoer for å navigere.

152 Kapittel 3

Når vi skal bruke Google Drive for første gang, får vi en veiledning i tre steg som hjelper oss med å komme i gang.

Du skal lage den delen av en klesbutikk på nettet hvor kundene skal gjennomføre et kjøp. Hvordan vil du ivareta prinsippet om at kundene skal kunne gjenkjenne fremfor å huske? Legg opp til at kundene skal skrive inn leveringsadresse (navn, adresse, postnummer osv.). Hvordan designer du denne delen for å skape en god brukeropplevelse?

7. SØRG FOR AT SYSTEMET ER FLEKSIBELT OG RASKT Å BRUKE

Dette prinsippet handler om å ivareta både førstegangsbrukernes og ekspertbrukernes behov. Folk som har mye erfaring med et dataprogram – og gjerne også med mange andre dataprogrammer – har ofte andre krav enn førstegangsbrukerne. De som har lite erfaring med dataprogrammer generelt, eller med akkurat dette dataprogrammet spesielt, trenger ofte litt støtte.

Noen nettsider og applikasjoner har en veiledning (tutorial på engelsk) som vises for førstegangsbrukere. For at ekspertbrukere eller de som har brukt applikasjonen før, skal slippe å gå gjennom denne hver gang de bruker den, har disse nettsidene ofte en knapp med teksten «Hopp over veiledning» eller en knapp med et kryss som lar brukeren gjør det samme.

DISKUTER
153Brukervennlighet

På nettsiden til den medisinske kunnskapsbasen Norsk Helseinformatikk (NHI) får brukerne spørsmål om de er helsepersonell før de får tilgang til å lese en artikkel. Dersom de klikker på «Nei», vil informasjon som personer uten medisinsk kompetanse kan misforstå, bli skjult eller omformulert.

Mange applikasjoner har tastatursnarveier. Ctrl + S / Cmd + S er for eksempel snarveien for å lagre et dokument. Hvis du lager en applikasjon der brukeren skal skrive inn store mengder data, bør du ifølge dette prinsippet legge til en tastatursnarvei for å lagre. I editoren på Svelte.dev/repl har du for eksempel mulighet til å lagre programmet ditt både ved å trykke på en lagreknapp og ved å trykke Ctrl + S / Cmd + S.

8. UTFORM SYSTEMET PÅ EN ESTETISK OG MINIMALISTISK MÅTE

Dette prinsippet handler ikke om at du skal lage et kunstverk, men om at du ikke skal la dekorative elementer ta unødvendig plass. Alle elementer du bruker på en nettside, tar plass og er potensielt forstyrrende hvis de ikke er relevante for oppgaven som skal løses.

9. HJELP BRUKERNE MED Å GJENKJENNE, DIAGNOSTISERE

OG RETTE OPP FEIL

Hvor mange ganger har du ikke irritert deg over uforståelige feilmeldinger? Hvis du lager et produkt og bare gir brukerne beskjed om at noe har gått galt, eller en feilkode, for eksempel «Feilkode 34545», gir du dem en dårlig brukeropplevelse.

Det er viktig å gi brukerne relevant informasjon, slik at det er enkelt for dem å finne ut av hva som har gått galt, og hvordan de kan rette opp i det. Slik informasjon kan gis i form av rød tekst, et ikon som indikerer feil, eller en kombinasjon.

154 Kapittel 3

10. TILBY HJELP OG DOKUMENTASJON

Det aller beste er om produktene du lager, er selvforklarende. Men hvis du lager komplekse produkter som skal brukes til å utføre arbeidsoppgaver, kan det være lurt å ha opplæringsmateriale eller en oversikt over hvilke funksjoner produktet tilbyr, hva de gjør, og hvordan de brukes. Men sørg for at denne oversikten blir oppdatert når produktet endres. Tenk også gjennom formatet på informasjonen. Et opptak av en person som forklarer og går gjennom produktet, gjerne sammen med et skjermopptak, kan for eksempel være mer effektivt enn en lang tekst med instruksjoner.

En annen type opplæringsmateriale er en veiledning som blir vist første gang et produkt tas i bruk, slik vi nevnte ovenfor. En slik veiledning bør du imidlertid bare ta med når det er strengt nødvendig. Det kan være irriterende og litt slitsomt for brukerne å måtte gå gjennom en slik veiledning når de helst bare vil komme i gang med å bruke produktet. Når du skal lage et produkt, bør du derfor teste det på brukere uten veiledning først. Finner du ut at det er hensiktsmessig med en veiledning, kan du lage det, men husk å teste den på nye brukere for å forsikre deg om at den har en nytteverdi. Hvis du først skal ha med en veiledning, må du gjøre det mulig for brukeren å hoppe over veiledningen og sørge for at den bare vises én gang per bruker. Dette kan du gjøre ved hjelp av informasjonskapsler eller lignende som lagres på brukerens telefon eller datamaskin. Pass også på at veiledningen ikke inneholder for mange steg.

Før vi gjennomfører brukertesting, eller i situasjoner der vi ikke har tilgang på faktiske brukere, kan det være lurt å få gjennomført en ekspertevaluering av et produkt. En ekspert kan peke på problemer med brukskvaliteten ved å vurdere produktet ut fra gitte kriterier, for eksempel Nielsens ti heuristikker.

155Brukervennlighet

SAMMENDRAG

> Brukervennlighet og brukskvalitet er synonymer og viser til egenskapene og kvalitetene som gjør det mulig å ta i bruk et produkt. Brukeropplevelsen viser til den totale opplevelsen brukerne har når de bruker et produkt. Den skapes i de ulike kontaktpunktene mellom brukeren og produktet.

> Interaksjonsdesignere jobber med å gjøre interaktive produkter og tjenester brukervennlige. Brukertester er et sentralt verktøy som interaksjonsdesignerne bruker for å undersøke om de har forstått hva brukerne vil ha, og om produktet er lett å bruke.

> Å designe er en form for problemløsning. Når vi skal designe et produkt, er det viktig at vi finner ut hvilke problemer produktet skal løse, blant annet ved å snakke med brukerne eller ved å bruke fem-hvorfor-spørsmål-øvelsen (se neste punkt).

> Ved å stille fem hvorfor-spørsmål kan vi finne ut om vi løser de rette problemene med produktet vi skal lage. (På engelsk kalles denne øvelsen for The 5 whys.)

> En designprosess kan ha disse fasene: utforske, utforme, utvikle og evaluere.

> I utforskingsfasen finner vi mange forskjellige løsninger for produktet. I denne fasen er det lurt å snakke med ekte potensielle brukere for å finne ut hvilke mål, behov og ønsker de har for det vi skal lage.

> I utformings- og utviklingsfasen begynner vi å skissere mulige løsninger. Vi kan lage en prototype, som er en enkel testversjon som potensielle brukere kan gi tilbakemeldinger på. Lavnivåskisser og -prototyper er enkle skisser, gjerne på papir. Brukere er mer tilbøyelige til å gi ærlige tilbakemeldinger når det er tydelig at det de tester, ikke er et ferdig produkt.

> Høynivåskisser og -prototyper skal ligne så mye som mulig på et ferdig produkt. Slike skisser brukes primært for å formidle konseptet eller løsningen til utviklerne som skal skrive programkoden.

> I evalueringsfasen gjennomføres det brukertester der potensielle brukere prøver ut produktet og gir tilbakemeldinger.

> Preeces seks mål for brukskvalitet er anvendbarhet, effektivitet, sikkerhet, nytte, lett å lære og enkelt å huske når man først har lært det. Vi bruker målene når vi diskuterer hvordan et produkt kan forbedres.

> Nielsens ti heuristikker (se side 151–155) kan hjelpe oss med å evaluere et produkt.

156 Kapittel 3

Oppgaver

3.1 Hva er brukervennlighet?

3.01

a) Gjør rede for begrepene brukervennlighet, brukskvalitet og brukeropplevelse

b) Hva gjør et produkt brukervennlig?

3.02

a) Gi noen eksempler på IT-produkter (nettsider, apper og digitale tjenester) du bruker ofte på skolen eller i fritiden.

b) Gir disse produktene deg en god brukeropplevelse?

c) Vurder om produktene i oppgave a oppfyller kriteriene for brukervennlighet på side 136–137.

3.2 Hvem lager gode brukeropplevelser?

3.03

a) Hva gjør en interaksjonsdesigner?

b) Søk etter stillingsannonser for interaksjonsdesignere på Internett. Hvilke egenskaper og kvalifikasjoner ser bedriftene etter hos en interaksjonsdesigner?

c) Hvor i Norge kan du studere interaksjonsdesign?

3.04

Interaksjonsdesign kombinerer fagområder som grafisk design, informasjonsarkitektur og tjenestedesign. Hva går disse fagområdene ut på?

3.3 Hvordan lage en god brukeropplevelse?

3.05

Hva er fem-spørsmål-øvelsen, og hva kan den brukes til?

3.06

Hvorfor er det viktig å involvere potensielle brukere når vi skal lage et produkt? Hva kan en interaksjonsdesigner gjøre for å involvere brukerne i designprosessen?

3.07

Hva er en prototype? Og hva er forskjellen mellom lavnivå- og høynivåprototyper?

157Brukervennlighet

3.08

a) Søk på Internett og finn noen eksempler på trender innenfor webdesign. Hvilke farger, skrifttyper, former og layouter er det populært å bruke på nettsider og i apper nå? Og hva har det vært populært å bruke tidligere?

b) Lag en enkel statisk nettside der du viser skrifttyper, farger og former som er populære nå.

3.09

Universell utforming av nettsider, apper og andre IT-produkter handler om at flest mulig skal kunne ta i bruk produktet, uavhengig av funksjonsevne. Når vi lager IT-produkter, må vi blant annet følge retningslinjene i WCAG-standarden. WCAG står for web content accessibility guidelines.

a) Gå til Digitaliseringsdirektoratets veileder for universell utforming som du finner på nettadressen www.uutilsynet.no. Sett deg inn i de fire prinsippene som retningslinjene for tilgjengelig webinnhold bygger på, og gi eksempler på noen retningslinjer for hvert prinsipp.

b) Gå til et nettsted du bruker ofte. Finn noen eksempler på utforming som er i tråd med WCAG. Finner du også noen eksempler på utforming som bryter med WCAG?

3.4 Mål for brukskvalitet

3.10

Gjør rede for Preeces seks mål for brukskvalitet.

3.11

I eksemplet på side 149 trekker vi frem interaksjonsmønsteret som går ut på at brukeren skal dra for å oppdatere. Gi noen eksempler på andre interaksjonsmønster du bruker på mobiltelefonen. Gi også noen eksempler på interaksjonsmønster du bruker på nettsider og i programmer på pc-en.

3.12

Hva er VR-briller? Hvordan brukes de, og hva kan de brukes til?

3.5 Ekspertevaluering

3.13

Gjør rede for Nielsens ti heuristikker og finn noen eksempler som demonstrerer hver heuristikk.

3.14

Søk på Internett og finn noen eksempler på gode og dårlige designvalg innenfor webdesign. Nyttige søkeord kan være «user experience», «usability», «design mistakes» og «web design».

158 Kapittel 3

3.15

a) Gå inn på to nettbutikker fra mobilen og sammenlign dem. Lag en presentasjon med skjermbilder fra nettsidene. Her er forslag til noen spørsmål du kan ta stilling til:

• Hva slags innhold vises på forsiden?

• Hvordan er varene i butikken kategorisert?

• Hvordan vises varene frem når du har klikket deg inn på en vare?

• Hvordan legger du til varer i handlekurven? Og hvordan kan du fjerne varer fra handlekurven?

• Er det enkelt å fylle ut skjemaet når du skal bestille varer? Du trenger ikke gå så langt som å gjennomføre kjøpet.

b) Tenk deg at du skal lage din egen nettbutikk. Er det noe du ville ha gjort på samme måte som i de to nettbutikkene du sammenlignet i oppgave a? Er det noe du ville ha gjort annerledes? Begrunn valgene ut fra Preeces seks mål for brukskvalitet og Nielsens ti heuristikker.

c) Tegn noen enkle skisser som viser hvordan nettbutikken skulle sett ut. Du kan velge å ta utgangspunkt i en mobilskjerm eller en pc-skjerm.

d) Lag statiske nettsider basert på skissene fra oppgave c. Lag komponenter og CSS-stiler for noe av innholdet på nettsidene.

3.16

a) Ta utgangspunkt i en mobilapp, en nettside eller et annet IT-produkt du bruker ofte. Hva er de mest sentrale funksjonene?

b) Ta skjermbilder og lag detaljerte beskrivelser av hvordan funksjonene virker. Hvilke steg må du som bruker utføre? Synes du at de som står bak produktet, har tatt gode og/eller dårlige valg når de har utformet funksjonene? Kommenter og foreslå eventuelt forbedringer.

3.17

a) Finn frem noen programmer du har laget tidligere. Gi noen eksempler på endringer du kunne ha gjort for å forbedre brukervennligheten til programmene. Prøv også å utbedre programmene.

b) Gi noen eksempler på endringer du kunne ha gjort for å forverre brukervennligheten til noen av programmene. Lag en forverret utgave og spør andre om hvilken versjon de mener er mest brukervennlig.

Referanser:

Nielsen, J. (2020, 15. november). 10 Usability Heuristics for User Interface Design. Nielsen Norman Group. https://www.nngroup.com/articles/ten-usability-heuristics/ Nordbø, T. (2017). Introduksjon til interaksjonsdesign. Universitetsforslaget.

Norman, D.A. (2013). The design of everyday things. Basic Books.

Sharp, H., Preece, J. og Rogers, Y. (2019). Interaction Design: Beyond Human-Computer Interaction (5. utg.). John Wiley & Sons Inc.

159Oppgaver

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.