Dynamiske websider med JavaScript og CSS3 Skrevet av Atle Nes Avdeling for informatikk og e-læring Høgskolen i Sør-Trøndelag Denne leksjonen handler om å bruke JavaScript og ny funksjonalitet i CSS3 til å lage dynamiske og tilpasningsdyktige websider. Vi tar i denne leksjonen også utgangspunkt i at du har grunnleggende kjennskap til HTML sin DOM (Document Object Model), programmering av dynamiske websider med JavaScript, design med CSS (Cascading Style Sheets) og forstår samspillet mellom disse teknologiene. HTML5 og JavaScript JavaScript, eller ECMAScript som det formelt kalles, gjør at vi kan kjøre små biter programkode på websidene for å gjøre de mer levende. I den nye HTML5-standarden er JavaScript blitt definert som standard scriptspråk, dvs. det scriptspråket vi skal bruke for å få laget dynamiske websider på klientsiden. Når vi sier på klientsiden mener vi at websiden lastes ned til nettleseren (klienten) før JavaScript-koden blir utført. Det finnes også scriptspråk som utføres på tjeneren (PHP, ASP, JSP etc.), men de blir ikke omtalt i denne leksjonen. Det at JavaScript er blitt standard scriptspråk i HTML5 betyr i alle fall at vi ikke lenger behøver å ha med attributtet type i syntaksen for å definere hvilket språk som er benyttet. Nettleseren skal nå forstå dette automatisk. Selv om det ikke har vært standardisert har nok endel nettlesere hatt denne funksjonaliteten lenge. Tidligere skrev vi altså <script type="text/javascript">...</script> Dette kan nå forkortes til <script>...</script> CSS3 (Cascading Style Sheets versjon 3) CSS brukes som kjent til å definere layout og utseendet til elementene på websiden. CSS3 er tredje versjon og er av W3C delt opp i mange ulike dokumenter som kalles moduler. Hver modul legger til helt nye funksjoner eller bygger på funksjonalitet fra CSS2 (og sørger for at CSS3 er bakoverkopatibel med denne). Det er lansert over 50 ulike moduler, men pga. modulariseringen er både stabilitet og status på disse svært forskjellig. Tre av modulene, om Selectors, Namespaces og Color, fikk imidlertid status som W3C anbefaling i 2011. 1
JavaScript Selectors API Når skal få JavaScript til å manipulere et element i DOM-treet kan man bruke attrubuttene id, name og class for å finne fram til riktig element(er) på websiden. Da har du kanskje brukt noen innebygde funksjoner som heter getelementbyid() eller getelementsbytagname(), men du har muligens savnet en getelementsbyclassname()? getelementsbyclassname() Det nye JavaScript-API-et løser dette ved å innføre nettopp getelementsbyclassname() slik at du nå også kan skrive: var innlegg = document.getelementsbyclassname('mine_innlegg'); Dette vil legge en referanse til alle elementer med klasseattributtet (class="mine_innlegg") til i variabelen innlegg. Den videre JavaScript-koden vil kunne manipulere elementene på websiden som hører til disse innleggene. Du kan selvfølgelig også inkludere flere klasser i en og samme funksjon ved å skille klassenavnene med mellomrom: var innlegg = document.getelementsbyclassname('klasse1 klasse2'); Dette vil legge referanser til både elementer med klasse1 og klasse2 til variabelen innlegg. Eller du kan utføre nøsting av ulike funksjoner: var forste_innlegg = getelementbyid('hoved').getelementsbyclassname('mine_innlegg'); Dette vil lage en referanse til alle elementer med class=mine_innlegg i likhet med øverste eksempel, men til forskjell bare innenfor elementet på websiden som har id=hoved (dvs. ikke hele websiden). queryselectorall() og queryselector() Annen ny funksjonalitet i JavaScript-API-et gjør at vi nå også enkelt har mulighet til å referere til elementer som stemmer overens med en bestemt syntaks i CSS. Dersom vi vil lage en referanse til alle avsnitt på websiden med klassen warning og error kan vi bruke funksjonen queryselectorall() til å skrive det kommaseparert på følgende måte: var alerts = document.queryselectorall("p.warning, p.error"); Et annen mer avansert eksempel kan være dersom vi ønsker å manipulere en punktliste (uordnet liste). La oss tenke oss at vi skal gjøre en operasjon på annethvert element i listen. Da kan vi med bruk av queryselectorall() skrive: var elements = document.queryselectorall("ul li:nth-child(odd)"); 2
Legg merke til at vi har skrevet CSS-syntaks for å referere til oddetallselementene (første, tredje, femte osv.) i punktlisten. Om man bytter ut odd med even vil det naturligvis bli partallselementene som blir referert til i stedet for oddetallselementene. Eller dersom det holder å referere til første enkelttreff i dokumentet kan vi bruke queryselector() i stedet for queryselectorall(). Dersom man vil manipulere første element i dokumentet med id=minid kan man skrive: var el = document.queryselector("#minid"); Vi kan ta et mer avansert eksempel. Tenk deg at du ønsker å manipulere første celle i tabellen som har name=test. Følgende syntaks vil gjøre nettopp dette. var first_td = document.queryselector("table.test > tr > td"); Legg også merke til bruken av hakeparanteser (>) for å traversere DOM-treet ned til riktig element. Hovedforskjellen på queryselector() og queryselectorall() er altså om du skal referere til et eller flere elementer. CSS3 Selectors En selector i CSS fungerer på lignende måte som for JavaScript. Den definerer kriterier for å velge ut et eller flere elementer på websiden som en eller flere CSS-regler skal gjelde for. CSS1 Første versjon av CSS hadde bare noen få selectors. Dette ga blant annet mulighet for å velge elementer (E), underelementer av elementer (E F), elementer som tilhører en bestemt klasse (E.klassenavn), elementer med en bestemt id (E.idnavn), hyperlenker med ulik status (E:link og E:visited), elementer som blir manipulert av brukeren (E:active, E:hover og E:focus) og første linje eller bokstav i elementet (E::first-line og E::first-letter) Om vi for eksempel ønsker at teksten i alle div elementer med klassen «advarsel» skal være rød kan vi definere dette som en CSS-regel på følgende måte: CSS2 div.advarsel { color: red; CSS2 introduserte mange nye selectors. Vi fikk mulighet til å velge alle elementer (*), elementer basert på attributtverdi (E[foo], E[foo="bar"], E[foo~="bar"] og E[foo ="bar"]), første underelement (E:first-child), elementer i et bestemt språk (for eksempel fransk - E.lang(fr)), innhold før og etter et element (E::before og E::after), underelement direkte under et element (E > F) og elementet direkte etter et element (E + F). Du husker kanskje at vi har brukt en av disse i avsnittet om JavaScript, nemlig muligheten for å velge et underelement direkte under et annet element. Om vi for eksempel ønsker å fargelegge bakgrunnen i den første cella i alle tabeller blå kan vi skrive en CSS-regel på følgende måte: table.test > tr > td { background-color: #0000ff; 3
CSS3 CSS3 introduserer også mange nye selectors. Dette gir tre nye muligheter for å velge elementer basert på attributtverdi i tillegg til (E[foo], E[foo="bar"], E[foo~="bar"] og E[foo ="bar"] fra CSS2) E[foo^="bar"] E[foo$="bar"] E[foo*="bar"] Velger alle elementer hvor attributtet foo har attributtverdi som starter med tekststrengen «bar». Velger alle elementer hvor attributtet foo har attributtverdi som avsluttes med tekststrengen «bar». Velger alle elementer hvor attributtet foo har attributtverdi som inneholder tekststrengen «bar». CSS3 gir også mange nye muligheter for å velger elementer basert på strukturelle egenskaper (i tillegg til E:first-child fra CSS2) E:root E:nth-child(n) E:nth-last-child(n) E:nth-of-type(n) E:nth-last-of-type(n) E:last-child E:first-of-type E:last-of-type E:only-child E:only-of-type E:empty Velger rotelementet til dokumentet. Velger det n te underelementet direkte under et element. Velger det n te siste underelementet direkte under et element. Velger det n te elementet av en bestemt type. Velger det n te siste elementet av en bestemt type. Velger det siste underelementet direkte under et element. Velger det første elementet av en bestemt type. Velger det siste elementet av en bestemt type. Velger det eneste underelementet direkte under et element. Velger det eneste elementet av en bestemt type. Velger elementet som ikke har noen underelementer. De siste nye variantene av selectors er E:target Elementet som er målet for URI en. E:enabled og E:disabled UI-element som kan være slått på eller slått av. E:checked UI-element som kan være valgt (checkbox eller radiobutton). E:not(s) Velger elementet som ikke samsvarer med selector s. E ~ F Velger elementet etter et element (ikke nødvendigvis like etter). 4
Eksempel på bruk av nth-child På tide med et lite eksempel. Vi kan lage oss en liten tabell med oversikt over leksjonene i faget HTML5. Tabellen har to kolonner og 9 rader. Å fargelegge annenhver rad i en større tabell kan dramatisk heve lesbarheten til tabellen. Dette kalles sebrafargelegging og har tidligere blitt løst med class="alternate" eller tilsvarende. Med den nye nthchild-selectoren kan tabellen bli helt fri for bruk av klasser. Det holder faktisk å legge til følgende CSS-kode: tr:nth-child(2n+1) { background-color: lightgrey; 2n+1 vil gi bety rad 1 (=2*0+1), rad 3 (=2*1+1), rad 5 (=2*2+1), rad 7 (=2*3+1) etc. Om du vil fargelegge motsatt kan du skrive 2n i stedet. Om du vil slippe unna matematikken går det også an å skrive de mer folkelige ordene odd eller even i stedet for 2n+1 og 2n. tr:nth-child(odd) { background-color: lightgrey; Dersom du vil ha annen fargelegging enn sebrastriper må du bruke matematikken. Legg også merke til at Internet Explorer versjon 7 og 8 ikke støtter CSS3 nth-child. En vanlig løsning på dette er å bruke jquery-biblioteket sin nth-child som fungerer også på IE-platformen. 5
CSS3 Farger Modulen om farger var den første som ble en CSS3 anbefaling av W3C - 7. juni 2011. For å se hva som er nytt om farger tar vi først en titt på hvordan verden så ut før CSS3. CSS2.1 lot oss definere farger på seks ulike måter: 17 uilke fargenavn aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, orange, purple, red, silver, teal, white og yellow. p { color: aqua; Fargekode bestående av 6 heksadesimale tegn To tegn for rødt, to for grønt og to for blått i intervallet 00 til FF. p { color: #AE03FF; p { color: #663399; Fargekode bestående av 3 heksadesimale tegn Et tegn for rødt, et for grønt og et for blått i intervallet 0 til F. Dette er en forenkling av fargekoden ovenfor som kan brukes dersom man har de to tegnene er like som i siste eksempel ovenfor. p { color: #639; RGB-kode med 3 numeriske verdier En verdi for rødt, en for grønt og en for blått i intervallet 0 til 255. p { color: rgb(109, 22, 255); RGB-kode med 3 prosentverdier Prosentverdier mellom 0% og 100% i stedet for numeriske verdier. p { color: rgb(0%, 10%, 100%); Systemfarger Farger i henhold til operativsystemet. p { color: ButtonFace; OBS! Denne siste kategorien bør du ikke lenger bruke siden den er uønsket i CSS3. 6
CSS3 lar oss definere farger på hele åtte ulike måter. Fargenavn Antallet er økt fra 17 til 147! Du kan finne en oversikt over alle fargene på http://www.w3schools.com/cssref/css_colornames.asp. CSS3 løser også problemet med gray/grey ved at begge skrivemåtene er tillatt. p { color: peru; Opacity Mulighet for å definere transparens med verdier fra fullt transparent 0 (eller 0.0) til fullt ugjennomsiktig 1 (eller 1.0). Legg merke til at regelen gjelder for elementet og alle underelementer! p { opacity: 0.3; RGBA-notasjon med numeriske eller prosentverdier Samme som CSS2.1, men med transparens som egen parameter. Man bør inkludere begge formuleringene for å støtte også gamle nettlesere. p { color: rgb(100,66,255); color: rgba(100,66,255,0.5); p { color: rgb(10%,6%,20%); color: rgba(10%,6%,20%,1); HSL eller HSLA-notasjon Dette er en ny fargemodell som blir brukt av designere. For nettleserne hard et ingen betydning om du definerer fargen med RGB eller med HSL. Hue har numerisk verdi mellom 0 og 359, saturation og lightness har prosentverdi mellom 0% og 100%. Også her er det lurt å inkludere formulering for å støtte gamle nettlesere. p { color: rgb(85,0,128); color: hsl(280,100%,50%); p { color: rgb(85,0,128); color: hsla(280,100%,50%,0.5); 7
Media Queries I dag finner vi nettlesere i mobiltelefoner, nettbrett, fjernsynsapparater, spillkonsoller og sikkert mange andre forskjellige enheter. Det antas at surfing på andre enheter enn den personlige datamaskinen vil overta i løpet av noen få år. I dag utvikles nettsteder stort sett for bruk med mus og tastatur, men etterhvert vil det kanskje være mer aktuelt med touch-grensesnitt, støtte for håndholdte spillkontrollere etc. Oppsummert stilles vi ovenfor et problem der vi har mange ulike enheter med ulike egenskaper (for eksempel skjermstørrelse) og ulike grensesnitt for inndata. Mange selskaper i dag velger å utvikle et eget iphone-nettsted. Nettstedet tilpasses enheten perfekt med tanke på iphone sine egenskaper til skjermstørrelse, men hva om man besøker nettstedet med en annen mobiltelefon med annen skjermstørrelse? Hva om det dukker opp en ny populær enhet? Skal vi utvikle et nettsted for iphone, en for ipad, en for Android, en for Windows Phone, en for Symbian, og en for personlige datamaskiner etc. På et tidspunkt kan man spørre seg om ikke dette blir for alt for mye arbeid. Ville det ikke heller være lurere å lage et nettsted og la designet endre seg basert på enhetens egenskaper? CSS2.1 ga oss noen spinkle muligheter til å velge mellom ulike stilark ved å spesifisere medietype. Hvis du har kodet stilark for utskrift kjenner du nok til denne syntaksen fra head i HTML: <link rel="stylesheet" type="text/css" href="skjerm.css" media="screen" /> <link rel="stylesheet" type="text/css" href="utskrift.css" media="print" /> Selv om standarden definerer mange ulike medietyper har nettlesere og enheter aldri omfavnet denne delen av spesifikasjonen. Det gjør at vi stort sett bare finner igjen denne syntaksen når det er snakk om utskrift. I CSS3 har vi fått noe som heter Media Queries som tar dette et steg videre. Dette lar oss lage stilark ikke for en bestemt type enhet slik vi gjorde med media-attributtet, men for en enhet som har visse egenskaper. Vi kan skrive: <link rel="stylesheet" type="text/css" media="screen and (max-device-width: 480px)" href="mobil.css" /> Vi ser at dette inneholder to deler; først en mediatype som før og deretter en spesifikasjon av egenskap (mediafeature). Den horisontale bredden til enheten blir sjekket (max-device-width) og dersom den er mindre eller lik 480 piksler vil enheten benytte stilarket mobil.css. Utviklere har eksperimentert med websider som har sjekket skjermoppløsning tidligere ved å bruke JavaScript. Media Queries tilbyr imidlertid mer enn bare skjermoppløsning. Det er til og med mulig å teste flere egenskaper på samme linje: <link rel="stylesheet" type="text/css" media="screen and (max-device-width: 480px) and (resolution: 163dpi)" href="mobil.css" /> 8
Vi er faktisk heller ikke lenger bare begrenset til bare å definere dette som links. Dette kan gjøres direkte i CSS-filen ved å bruke @media-regelen @media screen and (max-device-width: 480px) {.column { float: none; eller ved bruk av @import-direktivet @import url("mobil.css") screen and (max-device-width: 480px); Uansett alternativ vil resultatet bli det samme. Hvis test av egenskapen går gjennom vil den relevante CSS-koden bli utført på HTML-koden. I stedet for å tilpasse seg hver enkelt enhet som finnes lager man CSS som tilpasser seg egenskapene til enheten. Modulen om Media Queries er ikke ansett som ferdig av W3C, men fungerer på de fleste moderne nettlesere unntatt Internet Explorer. Det finnes et JavaScript bibliotek som du finner på http://code.google.com/p/css3-mediaqueries-js/ som du kan bruke for å få støtte også på IEplattformen. Web Fonts @font-face ble lansert i CSS2 og har vært implementert på Internet Explorer siden versjon 5 (utrolig!). Implementasjonen i IE baserte seg på det proprietære formatet Embedded Open Type (.eot) og ingen andre nettlesere valgte å bruke dette formatet. Med lanseringen av Safari 3.1 kunne webutviklere begynne å bruke alle de lisensierte TrueType fontene (.ttf) og OpenType fontene (.otf) på sidene sine. For å bruke egne fonter på websiden må de deklareres med en @font-face-regel: @font-face { font-family: DeliciousRoman; src: url(http://www.font-face.com/fonts/delicious/delicious-roman.otf); font-weight: 400; Og vi kan bruke denne fonten i et avsnitt på siden: p { font-family: DeliciousRoman, Helvetica, Arial, sans-serif; Den største grunnen til at webfonter ikke har tatt webben med storm er lisensspørsmål. Eierne av disse skrifttypene tillater rett og slett ikke slik bruk. Vi kan si at dette på sett og vis litt gammeldags tankegang. På sikt kan man kanskje tenke seg et felles lager der skrifttypene ligger gratis tilgjengelig på samme måte som Google sitt AJAX-bibliotek - http://code.google.com/apis/ajaxlibs/. 9
Mulighet for flere bakgrunner CSS3 tillater webutviklere å ha flere bakgrunner samtidig ved å definere de som en kommaseparert liste. La oss se på et enkelt eksempel med to bakgrunner: #eksempel { width: 500px; height: 250px; background-image: url(sheep.png), url(betweengrassandsky.png); background-position: center bottom, left top; background-repeat: no-repeat; Vi har definert høyde og bredde (height og width), to bilder for bakgrunn (background-image), plassering av bakgrunnsbildene (background-position) og om de skal gjentas eller ikke (backgroundrepeat). Dette vil stilsette og transformere følgende HTML-kode: <div id="eksempel">this box has background images, the first a sheep (aligned to the bottom and center) and the second is a grass and sky background (aligned to the top-left corner).</div> Til en ganske stilig boks på websiden: 10
Andre JavaScript-funksjoner JavaScript har også fått ny funksjonalitet knyttet til blant annet: Lokal lagring (web storage) En utvidelse av dagens cookies (informasjonskapsler). Cookies kan bare brukes til å lagre små tekststrenger, mens lokal lagring kan brukes til å lagre flere MB med data. Canvas Det introduseres et eget API for å tegne på et område på websiden enten i 2D eller 3D (WebGL). Device access Mulighet for å bruke JavaScript til å kommunisere med GPS, akselerometer og annen maskinvare på enheten. Webskjema Dette er temaer som vi tar opp i andre leksjoner senere i kurset. Andre CSS3-funksjoner Det finnes flere andre CSS3-moduler som tilbyr annen funksjonalitet enn den som er beskrevet her. En full oversikt over de viktigste modulene og deres status i forhold til å oppnå W3C anbefaling finner du på http://www.css3.info/modules/. CSS3 er i likhet med HTML5 ikke ferdigutviklet og det gjelder derfor å teste funksjonaliteten du ønsker å bruke opp mot de plattformer, enheter og nettlesere du vil at websiden skal fungere på. 11