Javascript og CSS
HTML5/CSS3 introduserer noen mekanismer som gjør det enklere å manipulere stilsett og stiler.
Javascript gir oss mange muligheter for å søke etter elementer i et document- eller element-objekt
De tre gamle metodene getElemenstByTagName(t), getElementByID(id) og getElementsByClassName(cls) er velkjente og operer på henholdvis elementnavn, attributte id og attributten class. Merk spesielt at den siste er fleksibel på den måten at sjekker om stringen cls er representert som en blankseparert string i class-attributten. Alle tre er metoder både i document og element.
I tillegg til disse har vi to metoder querySelectorAll(selector) og querySelector(selector). Disse forutsetter at det er satt opp en kopling mellom HTML (struktur) og CSS (utseende) og parameteren er en CSS3-selector, formulert på same måte som vi gjør det i et stilsett. Begge er metoder både i document og element. Forskjellen er at den første returnerer alle elementene den finner, mens den andre returnerer det første. Det vil si at det gir mening å skrive f.eks.:
document.querySelectorAll('div'); document.querySelectorAll('.hilited'); // annen kolonne i tabellen med id prisliste document.querySelectorAll('#prisliste tr>td:nth-of-type(2)'); // match på en av kommaseparert liste av class document.querySelectorAll('.fornavn','.etternavn');
getElemenstByTagName(t) og getElementsByClassName(cls) returnerer en collection i Javascript, mens querySelectorAll() returnerer en staticNodeList. Fordelen med den siste er at lista overlever dersom vi endrer egenskaper ved et medlem på en slik måte at det ikke lenger oppfyller kriteriene for medlemskap, f.eks. dersom vi endrer et klasse navn. Vi kan f.eks skrive:
var selected=document.querySelectorAll('.hilited'); [].forEach.call(selected, function(elt) { elt.className='killed'; });
Navn på CSS-egenskaper
Når vi skal manipulere CSS-egenskaper fra javascript er det viktig å huske at CSS-egenskaper systematisk bruker - som ordskiller (font-size, background-color, page-break-before, border-top-width, etc). Dette går dårlig som identifikator i Javascript. Når en egensskap skal navngis i Javascript skrives den vanligvis slik at andre ord begynner på stor bokstav (fontSize, backgroundColor, pageBreakBefore, borderTopWidth, etc), ofte kalt camelCase.
Endre style direkte
Dersom elementer har attributten style, kan vi skrive Javascriptkode som endrer denne.
HTML-koden er slik:
<div id="target3" style="color:blue; font-size:30px" class="a" onmouseover="changeStyle(event,'red','40px')" onmouseout="changeStyle(event,'blue','30px')"> Dra musa over her så blir det rødt </div>
Javascriptfunksjonen er slik:
function changeStyle(event,clr,sze) { var elt= event.target; elt.style.color=clr; elt.style.fontSize=sze; }
Merk at det er et problem når vi skal endre stilegenskaper av typen: border-left, background-color, osv. Altså stilegenskaper med "-". Javascript kan ikke annet enn å parse dette som et minustegn. For å bøte på dette opererer javascript med alternative navn, som borderLeft, backgroundColor osv. Lignende gjelder for stilangivelser der vi må bruke ":". En komplett liste av slike javascriptnavn finnes på [2] og Javascriptnavnene og CSS-egenskaper er angitt hos W3C [3] .
HTML-koden er slik:
<div id="target4" style="color:blue; font-size:30px" class="a" onmouseover="changeBStyle(event,'red','40px')" onmouseout="changeBStyle(event,'white','30px')"> Dra musa over her så blir bakgrunnen rød </div>
Javascriptfunksjonen er slik:
function changeBStyle(event,clr,sze) { var elt= event.target; elt.style.backgroundColor=clr; elt.style.fontSize=sze; }
Endre css class
I stedet for å arbeid direkte på stilegenskaper kan vi sette stilklasse.
HTML-koden er slik:
<div id="target2" class="a" onmouseover="setClass(event,'b')" onmouseout="setClass(event,'a')"> Dra musa over så blir det rødt </div>
Javascriptfunksjonen er slik:
function setClass(event,cls) { var elt= event.target; elt.className=cls; }
De aktuelle stilklasssene er slik:
.a{color:blue; font-size:30px}
.a3{color:blue; font-size:30px}
.b{color:red; font-size:40px}
Endre stilregel
HTML-koden er slik:
<div id="target3" class="a3" onmouseover="setClassRule('.a3','color','red')" onmouseout="setClassRule('.a3','color','blue')"> Dra musa over så blir det rødt </div>
Javascriptfunksjonen er slik:
function setClassRule(rule,name,val) { // we assume the actual stylesheet has index 2 var myrules=document.styleSheets[2].cssRules; for(i=0; i < myrules.length; i++) if(myrules[i].selectorText==rule) for(p in myrules[i].style) if(myrules[i].style[p] == name) myrules[i].style.setProperty(name,val,null); }
og stilsettet er slik.
.a{color:blue; font-size:30px}
.a3{color:blue; font-size:30px}
.b{color:red; font-size:40px}
Vise egnskapene til en regel
Dersom vi vil undersøke hva slags egenskaper et stil-element har kan vi inspisere det:
Inspisere en regel http://www.it.hiof.no/~borres/dw/scriptstyles/index4.html
Endre stilsett
Det er mulig å endre hvilket stilsett en HTML-side benytter fra Javascript. Nedenfor er et eksempel der en fransk artikkel om Picassos surrealistiske periode kan vises med engelsk eller tysk oversettelse. Oversettelsen er gjort med Babel Fish og er vel heller tvilsom, men det er ikke det som er hovedpoenget her.
Inspiser kildekoden for å se hvordan siden er bygd opp.
Stilsettene er referert i HTML-fila slik:
<link rel="stylesheet" href="picstilFrench.css"> <link rel="stylesheet" href="picstilEnglish.css"> <link rel="stylesheet" href="picstilGerman.css">
De tre stilsettene er slik:
- picstilFrench.css
.rightimage{float:right; margin: 0 0 10px 10px;padding:2px;} .english,.german,.spanish,.italian{display:none} .french{display:visible;}
- picstilEnglish.css
.rightimage{float:right; margin: 0 0 10px 10px;padding:2px;} .french,.german,.spanish,.italian{display:none} .english{display:visible;}
- picstilGerman.css
.rightimage{float:right; margin: 0 0 10px 10px; padding:2px;} .german{display:visible;} .french,.english,.spanish,.italian{display:none}
- picstilGerman.css
.rightimage{float:right; margin: 0 0 10px 10px;padding:2px;} .german{display:visible;} .french,.english,.german,.spanish,.italian{display:none}
- picstilSpanish.css
.rightimage{float:right; margin: 0 0 10px 10px;padding:2px;} .german{display:visible;} .french,.english,.german,.spanish,.italian{display:none}
Vi ser at det eneste som er forskjellig er hvorvidt det er engelsk, tysk eller fransk versjonen skal vises.
Javascriptet som bytter stilsett er slik:
function chooseStyle(theChoice){ if(document.styleSheets) for(i=0;i<document.styleSheets.length;i++) if(i==theChoice) document.styleSheets[i].disabled=false; else document.styleSheets[i].disabled=true; }
Javascriptet kalles slik:
<a href="Javascript:chooseStyle(0)">Francais</a> | <a href="Javascript:chooseStyle(1)">English</a> | <a href="Javascript:chooseStyle(2)">Deutsch</a> | <a href="Javascript:chooseStyle(3)">Espagnol</a> | <a href="Javascript:chooseStyle(4)">Italiano</a>
Vi kan selvsagt kalle funksjonen på andre måter, f.eks. som respons på et museklikk:
<div onClick="chooseStyle(2)"> klikk her for å bytte stilsett til tysk </div>
Tilordning av dynamikk
I litt mer kompliserte konstruksjoner kan det være en god ide å tilordne Javascriptfunksjonalitet dynamisk. På samme måte som vi kan og bør skille struktur fra utseende, kan og bør vi skille ut de dynamiske egenskapene. Det betyr at vi lar siden selv tilordne Javascriptfunksjonalitet når den lastes.
Vi merker de aktuelle elementene på en eller annen måte, f.eks. med class-attributt. Når siden lastes finner vi de merkede elementene og tilordner dynamikk.
HTML-siden er slik
<html> <head> <title>dynademo</title> <script type="text/javascript" src="dynajava.js"> </script> <style> .a{color:blue; font-size:40px} .b{color:red; font-size:40px} .x{color:blue; font-size:40px} </style> </head> <body onload="setHandlers()"> <h1>Stilforandring</h1> <div class="x">marit</div> <div class="a">per</div> <div class="x">kari</div> <div class="a">jens</div> </body> <div><a href="javascript:history.back(-1)">Tilbake</a></div> </html>
De aktuelle scriptfunksjonenen er slik
function hilite(e) { e.target.className='b'; } function unhilite(e) { e.target.className='a'; } function setHandlers() { var lst=document.getElementsByClassName('x'); for(ix=0; ix < lst.length;ix++) { lst[ix].onmousemove=hilite; lst[ix].onmouseout=unhilite; } }