!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

Børre Stenseth
JavaScript >Javascript og CSS

Javascript og CSS

Hva
Hvordan vi kan programmere endring av stil i Javascript
MVC
Model View Controller. Wikipedia [1]

Utvikling av web-sider, eller om vi vil web-løsninger, er i økende grad avhengig av en klar oppfatning av forholdet mellom struktur, utseende og dynamikk. Disse tre aspektene er koplet til 3 teknologier: HTML, CSS og Javascript.

HTML5 viderefører et klart fokus på struktur, og de fleste stilbaserte attributter er borte. CSS utvikler seg stadig og har langt større fleksibilitet enn de fleste er klar over.

Forholdet mellom struktur (HTML) og Javascript er den største utfordringen for de fleste webutviklere. Det skyldes i hovedsak to forhold:

  • Objektorientert utvikling i JS er såpass forskjellig fra de språk de fleste programmere kjenner,som Java, C++, C#, at det oppfattes som krevende og litt diffust
  • Begivenhetsstyrt programmering blir litt annerledes på grunn av meldingstransport i sidestrukturen
  • De ulike nettleserne implementerer ikke DOM-modellen av en vevside på samme måte. (Det skulle være morsomt å vite hvor mye tid som er brukt på vedensbasis for å tilpasse seg IE)

Vi kan ommøblere en HTML-side stort sett slik vi ønsker ved hjelp av DOM-programmering i Javascript. Vi kan flytte elementer, endre innholdet osv. Blandt de ting vi kan gjøre er å endre utseendet på elementer ved å endre style-egenskaper. Dette kan vi gjøre på flere måter. Vi kan:

  • endre style-egenskaper direkte
  • endre tilordning av stilklasser (class)
  • lage en dynamisk tilordning av javascriptbegivenheter som gjør de siste
  • endre vilket stilsett vi ønsker å bruke

Vi skal se nærmere på disse mulighetene i denne modulen

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.

Dra musa over her så blir det rødt

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] .

Dra musa over her så blir bakgrunnen rød

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.

Dra musa over så blir det rødt

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

Dra musa over så blir det rødt

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:

_JS
function showCSSRule(rule)
    {
        var myrules=document.styleSheets[0].cssRules;
        for(i=0; i < myrules.length; i++)
            if(myrules[i].selectorText==rule)
            {
                T='';
                for(p in myrules[i].style)
                    if(myrules[i].style[p])
                        T+=p+' : '+myrules[i].style[p]+'\n';
                alert(T);
            }
    }

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.

Test siden med valgfri oversettelse http://www.it.hiof.no/~borres/dw/picasso/picasso_with_style.html

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.

Se et eksempel her http://www.it.hiof.no/~borres/dw/scriptstyles/dynademo.html

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;
    }
}
Referanser
  1. Model View Controller Wikipedia en.wikipedia.org/wiki/Model-view-controller 14-03-2010
  1. CSS Properties To JavaScript Reference Conversion codepunk codepunk.hardwar.org.uk/css2js.htm 14-07-2010
  1. Cascading Style Sheets W3C Schools www.w3schools.com/css/default.asp 14-03-2010

All relevant kode er sitert i teksten

Vedlikehold
B.Stenseth, revidert april 2008
( Velkommen ) JavaScript >Javascript og CSS ( Expand )