DOM
Børre Stenseth
Moduler>JavaScript>DOM

DOM i Javascript

Hva
DOM-programmering i Javascript (Document Object Model)

Vi har opp gjennom HTMLs historie kunnet manipulere innholdt på en side i selve nettleseren ved hjelp av scriptspråk, vanligvis Javascript. Dette har vanligvis blitt omtalt som DHTML (dynamisk HTML). Dette har vært en ganske slitsom aktivitet fordi nettleserne har hatt forskjellige oppfatninger av hvordan en vevside er beskrevet, altså vilke deler siden består av og hvordan de kan leses og endres.

Det er fortsatt av og til en ganske krevende øvelse, men handlingsrommet med felles funksjonalitet blir stadig større. Min erfaring er at det nesten alltid er MSIE som skiller seg fra de andre i min referanseramme (Opera, FireFox, Chrome) og som fører til ekstraarbeid.

Eksemplene i denne modulen er ganske trivielle og har bare som hensikt å vise helt grunnleggende DOM-manipulering.

Tell paragrafer

La oss se på et enkelt eksempel: Vi ønsker å telle antall paragrafer, p-elementer, på denne siden og vise resultatet i en alertboks. Prøv dette:

<div>
<button onclick="countCode('p');">Tell paragrafer</button>
</div>

Javascriptkoden er svært enkelt og bruker bare en DOM-metode.

function countCode(tagname)
{
   paralist=document.getElementsByTagName(tagname);
   alert("antall "+tagname+": "+paralist.length);
 }

Produksjon av innhold

La oss produsere en elementstruktur fra et javascript. Vi vil legge til litt formatert text i paragrafen nedenfor.

Dette er originalteksten.

<p id="makemore">
   Dette er originalteksten.
</p>
<div>
 <button onclick="makeMore('makemore');">Vis mer</button>
</div>

Javascriptkoden er slik:

function makeMore(hostID)
{
   hostelement=document.getElementById(hostID);
   newelt=document.createElement('div');
   newtext=document.createTextNode('... og her er mer');
   newelt.style.color='red';
   newelt.appendChild(newtext);
   hostelement.appendChild(newelt);
}

Koden er ganske omstendelig og demonstrerer bruk av grunnleggende DOM-metoder.

Bytte innhold i elementer

Dette er en ganske generell problemstilling som kan tjene som illustrasjon av noe av den mest sentrale funskjonaliteten. Vi ønsker altså å bytte innholdet i to elementer som respons på en eller annen brukeraksjon. Du kan test ut eksempelet her.

Hallo
Hei

De involverte linjene i HTML-siden er slik:

<div id="linje1"><span style="color:red">Hallo</span></div>
<div id="linje2"><span style="color:green;font-size:20;">Hei</span></div>
<div id="temp" style="display:none">her</div>
<div>
 <button onclick="switchElements('linje1','linje2');">Bytt linjene</button>
</div>

Javascriptet er igjen veldig omstendelig:

function copyFragment(fromNode,toNode)
{
   while(toNode.hasChildNodes())
      toNode.removeChild(toNode.lastChild);
   
   nod=fromNode.firstChild;
   while(nod!=null)
   {
      nodcopy=nod.cloneNode(true);
      toNode.appendChild(nodcopy);
      nod=nod.nextSibling;
   }
}

function switchElements(elt1ID,elt2ID)
{
   	element1=document.getElementById(elt1ID);
   	element2=document.getElementById(elt2ID);
   	elementtemp=document.getElementById('temp');
   	copyFragment(element1,elementtemp);
   	copyFragment(element2,element1);
   	copyFragment(elementtemp,element2);
}

Vi har altså brukt et skjult hjelpeelement, div med id="temp", for å foreta den nødvendige mellomlagringen når vi bytter (Vi kunne selvsagt gjort det annerledes med litt mer sofistikert nodeadministrasjon).

Siden begge de involverte div'ene har en understruktur er det ikke godt nok å kopiere det tekstelementet som er barn av selve div-elementet, vi må kopiere et helt trefragment. Funksjonen getElementById plukker ut det første elementet i treet med den angitte id-attributten. Attributten id spiller altså en spesiell rolle og er koplet til en egen DOM-funksjon.

Det finnes en kortere versjon av scriptet som baserer seg på egenskapen innerHTML. Hvis vi bruker denne kan koden vår se slik ut:

function switchElements(elt1ID,elt2ID)
{
	element1=document.getElementById(elt1ID);
	element2=document.getElementById(elt2ID);
	temptext=element1.innerHTML;
	element1.innerHTML=element2.innerHTML;
	element2.innerHTML=temptext;
}

Unektelig noe enklere. innerHTML bryr seg ikke om hva slags trestruktur vi flytter, den fokuserer bare på innholdet i elementet, betraktet som text. Det er dessuten en viktig forutsetning for at dette skal fungere at det som plasseres som innerHTML parses i det øyeblikket det plasseres.

Bilder

Vi kan bruke den samme teknikken for bilder. Prøv å føre musa inn og ut av dette bildet og se hva som skjer.

image1

Den aktuelle koden er slik:

<div id="div1" style="cursor:pointer">
   <img src="Smileys17.gif" alt="image1"
   onmouseover="switchElements('div1','div2');"/>
</div>
<div id="div2" style="display:none">
   <img src="Smileys12.gif" alt="image2"
   onmouseout="switchElements('div1','div2');"/>
</div>

Alternativt kan vi gjøre slik hvis vi f.eks. ønsker å markere en popup. Prøv å klikk på bildet.

image1
<div id="div11" style="cursor:pointer">
   <img src="Smileys17.gif" alt="image1"
   onmouseover="switchElements('div11','div12');"/>
</div>
<div id="div12" style="display:none">
   <img src="Smileys12.gif" alt="image2"
   onmouseout="switchElements('div11','div12');"
   onclick="simplepopup('http://www.it.hiof.no/~borres/ml/domscript/p-smileys.html','Pop','*')"/>
</div>

Skjulte elementer

Vi ser at en teknikk som er bruk ovenfor er å legge ut deler av vevsiden med style="display:none", for så å flytte innholdet i et slikt skjult element til et element som ikke er skjult. Og/eller omvendt. Dette åpner i prinsipp for at vi kan ommøblere en vevside nesten som vi vil med en enkel "switchElements()" eller "copyElements()" funksjon.

To eksempler

Gallerihttp://www.it.hiof.no/~borres/dw/domscript/demo1.html
Oversettelsehttp://www.it.hiof.no/~borres/dw/picasso/picasso_hidden.html
Referanser
  1. JavaScript og DOMkrook.orgkrook.org/jsdom/14-03-2010
  1. DOM i MS Internet ExplorerMSDNmsdn.microsoft.com/en-us/library/ms763742%28v=VS.85%29.aspx14-03-2010
  1. DOM i MozillaMozillabooks.mozdev.org/html/mozilla-chp-5-sect-2.html14-03-2010
  1. DOM i OperaOperawww.opera.com/docs/specs/14-03-2010
Vedlikehold
Børre Stenseth, sist revidert mai 2011
(Velkommen) Moduler>JavaScript>DOM (MSXML)