DOM i Javascript
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 ser nå ut til at nettleserprodusentene har har tatt inn over seg at velformede dokumenter skal kunne handteres ved hjelp av et DOM-grensesnitt slik som DOM er beskrevet fra W3C. Det betyr et langt steg i retning av at dokumenter betraktes som DOM-trær og at treet kan leses og manipuleres med funksjoner som er beskrevet som del av DOM-anbefalingen. Vi er ikke helt framme ved en felles måte å gjøre ting på, men det er bedre enn det har vært. Et eksempel på et problem ar at Microsoft og Mozilla manipulerer style-attributter på forskjellig måte.
Merk Microsofts generelle XML-maskin, MSXML, som gjør det mulig å anvende DOM-funksjonalitet på andre dokumenter enn det som er lastet opp som "synlig" deler av en side. Blandt annet kan vi via Javascript anvende XSLT-transformasjoner på XML-data. MSXML beskrives i modulen MSXML.
Eksemplene i denne modulen er dersom ikke annet er angitt testet i de seneste versjonene av MSIE, Mozilla og Opera, alle på Windows.
.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:
Klikk her for å vise antall paragrafer.
<p style="cursor:pointer" onclick="countCode('p');">
Klikk her for å vise antall paragrafer.
</p>
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.
Klikk her for å vise mer.
<p id="makemore">
Dette er originalteksten.
</p>
<p style="cursor:pointer" onclick="makeMore('makemore');">
Klikk her for å vise mer.
</p>
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);
}
.
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.
Klikk her for å bytte linjene
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>
<p style="cursor:pointer" onclick="switchElements('linje1','linje2');">
Klikk her for å bytte linjene
</p>
Javascriptet er slik:
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 kanskje gjort det annerledes med litt mer sofistikert nodeadministrasjon).
Dette er ren DOM-kode ifølge boka. 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. Merk spesielt funksjonen getElementById som 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å den omstridte, ikke DOM, 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, men altså ikke ifølge W3C-standard. innerHTML bryr seg ikke om hva slags trestruktur vi flytter, den fokuserer bare på innholdet i elementet, betraktet som text. De fleste nettlesere har implementert innerHTML. Hvis du søker på nettet finner du mange kommentarer til denne "innerHTML-fiksen".
.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.
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.
<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.ia.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