JavaScript Real-Life Projekt

I dette projekt skulle min gruppe og jeg re-implementere et kommercielt website ved hjælp af HTML, CSS og JavaScript. Min gruppe bestod af Oliver, Tiffany, Dicte, Cecilie og mig, og sammen udvalgte vi sider fra H&M, som vi genskabte i HTML og CSS. Derudover skulle vi bruge JavaScript til at udvikle interaktive elementer efter eget valg, hvor hvert gruppemedlem skulle implementere nok JavaScript til at demonstrere hele pensum.

Som en del af projektet var der krav om, at vi afleverede en online interaktiv prototype, der samlede vores løsning i HTML, CSS og JavaScript. Vi skulle desuden uploade kildekoden til GitHub samt udarbejde en fælles video på 4-8 minutter, hvor vi gennemgik udvalgt JavaScript-kode, der demonstrerede hele pensum.

Proces

Planlægning

Som første skridt etablerede vi et delt GitHub-repository, der fungerede som versionsstyringsværktøj og sikrede, at alle gruppemedlemmer kunne arbejde parallelt uden at overskrive hinandens kode. I repositoryet oprettede vi en grundstruktur med to HTML-dokumenter, et fælles CSS-stylesheet samt separate JavaScript-filer til hvert gruppemedlems funktionalitet. Denne struktur understøttede princippet om separation of concerns, idet indhold (HTML), præsentation (CSS) og funktionalitet (JavaScript) blev holdt adskilt.

For at sikre konsistens i kodebasen fastlagde vi fælles kodestandarder, som alle skulle følge. Disse omfattede blandt andet, at al kode skulle skrives på engelsk, variabler skulle navngives i camelCase og funktioner skulle begynde med stort bogstav. Til strukturering af CSS anvendte vi BEM-metoden for at sikre genkendelighed og undgå konflikter i navngivning af klasser. Desuden skulle alle variabler starte med små bogstaver, og al kode skulle dokumenteres med kommentarer, hvor funktioner blev beskrevet med både forventet input og output.

Herefter fordelte vi de interaktive funktioner i JavaScript, så alle bidrog med en selvstændig modulær komponent: Oliver implementerede en indkøbskurv, Dicte udviklede et login-flow, Cecilie programmerede et dynamisk billedgalleri til produktsiden, Tiffany stod for produktvalget, og jeg havde ansvar for en interaktiv sidemenu på forsiden.


Udvikling af interaktiv sidemenu

Udviklingen af den interaktive sidemenu begyndte med en konkret gennemgang af H&M’s eksisterende hjemmeside. Formålet var at forstå, hvordan deres menu var opbygget, hvilke hovedkategorier og undermenuer der blev brugt, og hvordan billeder blev integreret i submenuen. Denne observation gjorde det muligt at definere, hvilke elementer jeg skulle genskabe, og hvordan de skulle struktureres i HTML, CSS og JavaScript, så løsningen både lignede originalen og fungerede dynamisk.

Dernæst lavede jeg et array af objekter i JavaScript, hvor hvert objekt repræsenterede et menupunkt (billede 1, l. 10-56). Hvert objekt indeholdt tre egenskaber: navn for hovedmenupunktet, submenu for listen af undermenuer og picture for billederne, der skulle vises i undermenuen. Denne tilgang gjorde det muligt at iterere over menuen og automatisk generere både hovedmenu og undermenuer i DOM’en, hvilket er en mere effektiv metode end at skrive alle elementer manuelt.

Med datastrukturen på plads begyndte jeg at oprette HTML-elementer dynamisk med JavaScript. Jeg startede med at finde <ul id=”menu”> i HTML’en og gemme den i en variabel. Derefter oprettede jeg en for-løkke, der gik igennem hvert element i menu-arrayet. For hvert menupunkt oprettede jeg et <li>-element og indsatte et <a>-tag med hovedmenuens navn (billede 2, l. 60-67).

Herefter byggede jeg selve submenuen. Jeg oprettede en <div>-container med klassen submenu, der skulle indeholde både tekst-undermenuen til venstre og billederne til højre (billede 2, l. 72-73). For tekst-undermenuen oprettede jeg en ny <ul>, hvor jeg igen brugte en for-løkke til at gå igennem undermenu-arrayet. For hvert undermenupunkt lavede jeg et <li> med en <a>-tag og tilføjede CSS-klasser til særlige elementer, såsom de første fire undermenuer, der skulle fremhæves, og “LAST CHANCE”, der skulle have en særlig styling (billede 2, l. 80-103). På denne måde kunne jeg style dem forskelligt i CSS og få dem til at ligne elementerne på H&M’s hjemmeside.

Parallelt med tekst-undermenuen blev billed-delen opbygget. Her oprettede jeg en separat <ul>, hvor hvert billede blev placeret i et <li> med et <img>-tag. Billederne fik src- og alt-attributter, så de både blev vist korrekt og var tilgængelige for skærmlæsere. Til sidst blev både tekst-undermenuen og billed-delen tilføjet til submenu-containeren, der igen blev tilføjet til hovedmenuens <li> (billede 3, l. 112-131). På denne måde blev hele menuen og dens submenuer genereret fuldstændigt dynamisk, hvilket gør det nemt at ændre eller tilføje nye kategorier uden at ændre HTML manuelt.


Efter strukturen var på plads, gik jeg videre til styling og interaktion. Jeg anvendte CSS til at skabe en todelt submenu med flexbox, hvor tekst og billeder stod side om side med passende afstand mellem kolonnerne. Ved hjælp af CSS-transitions fik jeg submenuen til at glide ind fra venstre, når brugeren fører musen over et hovedmenupunkt.

Dog glider submenuen ikke ind på helt samme måde som på H&M’s originale hjemmeside. På den oprindelige side glider alle submenuer ind fra venstre på en måde, så de altid fylder præcis 50 % af skærmen og bliver siddende fast ved den venstre kant, uanset hvilket hovedmenupunkt man holder musen over. I min version placerer submenuen sig i stedet direkte under den kategori, den hører til, hvilket betyder, at placeringen varierer afhængigt af menupunktet.

Jeg forsøgte at efterligne H&M’s løsning ved at bruge position: fixed i CSS, så submenuen kunne holde sin placering uafhængigt af resten af layoutet. Det gav dog et uforudset problem: når submenuen var længere end skærmhøjden, kunne man ikke scrolle ned for at se resten af indholdet, fordi den var låst fast til skærmen. For at løse det ændrede jeg i stedet til position: relative, hvilket sikrede, at brugeren kan scrolle gennem hele submenuen. Ulempen er, at overgangseffekten ikke er en tro kopi af H&M’s løsning, men til gengæld kan hele menuens indhold altid tilgås.

Til sidst gjorde jeg menuen responsiv ved at anvende en media query i CSS, der aktiveres ved en skærmbredde på maks. 960px (billede 9, l. 161). Når denne grænse nås, ændres menuens struktur: menulinjen vises ikke længere som en vandret liste, men bliver i stedet skjult bag en burger-knap. Samtidig ændres submenuerne, så de ikke længere optræder som en todelt flex-struktur med billeder, men kun viser tekstkolonnen i en lodret opstilling. Dette blev gjort ved at skjule billedlisten (display: none) og ændre submenuens flex-direction til column, så den fylder hele skærmbredden i mobilvisning.

JavaScript styrer selve interaktionen med burger-menuen. Når brugeren klikker på burger-knappen, ændres elementernes style.display: burger-knappen skjules (none), kryds-knappen vises (block), og menulinjen vises (flex). Når brugeren derefter klikker på kryds-knappen, vendes processen: burger-knappen vises igen, kryds-knappen skjules, og menulinjen skjules (none) (billede 4, l. 139-159).

For submenuerne i mobilvisning blev interaktionen også ændret fra hover til klik. Ved hjælp af JavaScript blev der tilføjet en funktion, så et klik på et hovedmenupunkt åbner dets tilhørende submenu. Før en submenu åbnes, lukkes alle andre, så kun én er synlig ad gangen (billede 5, l. 169-196) . Denne funktionalitet blev udviklet med hjælp fra AI. Jeg har derfor ikke selv udarbejdet koden fra bunden, men jeg har integreret den i mit script og testet den, så den fungerer sammen med burger-menuen og menuens øvrige struktur.

Herunder kan du se min HTML (billede 6) og CSS (billede 7-9).

Merge af kode i Github

En central del af processen bestod i at samle de individuelle komponenter, som hvert gruppemedlem havde udviklet, til én samlet løsning i vores fælles GitHub-repository. Denne fase viste sig at være udfordrende, da integrationen krævede, at vi håndterede konflikter mellem forskellige dele af koden og sikrede, at strukturen hang sammen på tværs af projektet.

Et konkret eksempel var integrationen af min menulinje. Da jeg første gang implementerede den i det fælles projekt, blev den placeret oven i Olivers del af headeren, der bestod af ikoner til søg, login, favoritter og kurv. Samtidig forsvandt H&M’s logo helt fra siden. Denne fejl viste, hvordan individuelle løsninger kan skabe uforudsete konflikter, når de bringes ind i et større system. Oliver fik dog justeret strukturen, så både min menulinje og hans ikon-del kunne eksistere side om side, uden at elementerne overskrev hinanden.

Foruden konflikten i desktop-visning oplevede jeg en tilsvarende udfordring i mobilvisning, hvor burger-menuen blev placeret oven i de ikoner, Oliver havde implementeret. Dette skyldtes, at menulinjen og ikon-delen manglede en fleksibel ramme til at styre deres indbyrdes forhold, når skærmbredden blev 960px eller mindre.

Jeg løste problemet ved at justere CSS-strukturen. Først gjorde jeg <nav> til en flex-container (display: flex), så elementerne i headeren automatisk kunne placere sig side om side i stedet for at overlappe. Dernæst tilføjede jeg en min-width på 60px til ikonerne, så de fik en fast grundbredde og ikke blev presset væk, når burger-knappen blev vist. Endelig justerede jeg bredden på H&M-logoet til 500px, så der kom en tydelig balance mellem logo, menu og ikoner.

Selvom disse ændringer forbedrede strukturen, lykkedes det mig ikke at få mobilvisningen til at fungere helt optimalt. Menulinjen placerede sig stadig i midten fremfor ude til højre, og når burger-menuen blev åbnet, blev ikonerne skubbet ud af skærmbilledet.  Jeg forsøgte at løse problemet ved at ændre i HTML-strukturen, men ændringerne påvirkede resten af layoutet på en måde, der ikke fungerede. Jeg forsøgte også at fastlåse burgermenuen i højre hjørne ved at bruge position: fixed, men det gik heller ikke. Jeg valgte derfor at acceptere fejlen fremfor at bruge mere tid på finjustering, da det vigtigste var, at burger-menuen fungerede.

Resultat

Herunder ses resultatet af projektet og vores afleverede materiale:

Reflektion

Projektet har givet mig god erfaring med at udvikle en hjemmeside – både selvstændigt og i samarbejde med andre. Jeg fik mulighed for at fordybe mig i JavaScript og udvikle en selvstændig komponent, der efterfølgende skulle integreres i det samlede system.  Processen tydeliggjorde, hvor komplekst det kan være at få individuelle løsninger til at spille sammen, og hvor vigtigt det er med klar struktur og planlægning.

En vigtig læring for mig har været, hvor vigtig struktur og kodestandarder er for et fælles kodeprojekt. De koderegler og fælles principper, vi fastlagde i begyndelsen, gjorde det lettere at overskue hinandens kode og finde fejl. Dog kunne de ikke forhindre, at vi stødte på konflikter undervejs. Specielt da jeg skulle implementere min menulinje i Olivers kode, hvor jeg oplevede, hvordan små forskelle i struktur og CSS kunne skabe større layoutproblemer. Udfordringen gav mig en bedre forståelse for versionsstyring og vigtigheden af at teste sin kode i en fælles ramme tidligt i processen. Jeg tror på mange måder, at mine problemer med menulinjen kunne være undgået med bedre planlægning: Hvis jeg tidligere havde overvejet, hvordan min kode skulle integreres med de andre komponenter, kunne jeg have opbygget den i mindre dele, så den var lettere at tilpasse og integrere. Derudover kunne vi have lavet simple prototyper af både desktop- og mobilversionen tidligt i processen, så potentielle konflikter med burger-menuen og ikonerne blev opdaget, inden de opstod i den færdige løsning. I praksis havde vi dog begrænset tid, da flere af mine gruppemedlemmer samtidig var tutorer for nye studerende og derfor måtte bruge en stor del af deres energi på den opgave. Derfor valgte vi at fokusere på kerneopgaven (at få erfaring med JavaScript) frem for en mere omfattende planlægningsfase.

Projektet har også givet mig en bedre forståelse af GitHub som samarbejdsværktøj. Jeg har lært, hvor vigtigt det er at committe løbende og at teste ændringer i en separat branch, før de merges ind i hovedprojektet. Arbejdet med GitHub viste mig også, hvor let konflikter kan opstå, men samtidig hvor effektivt de kan løses, når man har et system til at holde styr på versionshistorikken.

En anden vigtig erfaring har været at acceptere, at det perfekte ikke altid er muligt. Jeg måtte justere mine ambitioner for at få menulinjen til at fungere teknisk, og jeg erfarede, at det vigtigste i denne sammenhæng var en stabil og brugbar løsning fremfor en tro kopi af H&M’s originale design. Det har lært mig at prioritere funktionalitet og færdiggørelse over detaljeret finpudsning – især når man har en fast deadline og tiden er knap. 

Alt i alt føler jeg, at projektet har styrket mine kompetencer både teknisk og samarbejdsmæssigt. Jeg er blevet bedre til at strukturere min kode, mere opmærksom på de udfordringer, der opstår i integrationen mellem forskellige dele af et projekt, og mere tryg ved at arbejde med GitHub som fælles platform. Erfaringerne giver mig et stærkere fundament til at håndtere lignende projekter i fremtiden, hvor samarbejde, planlægning og fleksibilitet er lige så vigtigt som de tekniske færdigheder.