DOM

JAVASCRIPT JA DOM KOULUTUSTA VUONNA 2025!

Kurssit saatavilla kautta Suomen. Tule ja varaa oma koulutustapahtumasi
IT-koulutuksen asiantuntijasi, Koulutus- ja konsultointipalvelu KK Mediat

DOM Level 1 - solmut, ominaisuudet ja metodit

DOM Level 1-standardi korvasi aiemmat selainkohtaiset toteutukset (nk. DOM Level 0). Malli määritteli yhtenäisen oliohierarkian ja käsitteet, ja tarjosi yhtenäisen tavan käsitellä sekä HTML- että XML-dokumentteja ohjelmallisesti. Tämä standardointi vähensi merkittävästi selainten välisten yhteensopivuusongelmien määrää ja loi perustan modernille web-kehitykselle.

DOM Level 1:een sisältyvät seuraavat keskeiset ominaisuudet:

DOM Level 1 - solmutyypit (nodeType)

Koko DOM-puu koostuu Node-tyyppisistä olioista, ja niillä kaikilla on nodeType-ominaisuus. Seuraavassa taulukossa on listattu DOM Level 1 -määrittelyn keskeiset solmutyypit:

SolmutyyppiSeloste
DocumentOlio, joka esittää dokumentin.
DocumentFragmentOlio, joka esittää dokumentin osaa (voi olla myös koko dokumentti)
NodeViittaus elementtiin, ominaisuuteen tai merkkijonoon
ElementOlio, joka esittää yhden dokumentin elementeistä. Elementti voi sisältää toisen elementin, tekstiä, kommentin, olioviittauksen tai muotoilematonta tekstiä (eli CDATA)
AttributeNimi-arvo - pari, joka esittää elementin jonkin ominaisuuden
CommentsKommentti (selain ohittaa)
TextOlio, joka sisältää elementin tekstin (sisällön). Parsitaan ilman esitystä.
CdataMerkkijono, joka ei sisällä muotoilukoodia. Ei parsita.
EntityAlkio, joka korvataan merkkijonolla. Siis < merkki korvataan merkinnällä <
EntityReferenceKun alkiota edeltää &-merkki, korvaava merkkijono laitetaan sen paikalle.
DocumentTypeKokoelma dokumentin olioista.

NodeType ilmaistaan numeerisena arvona. Esimerkiksi Element on arvoltaan 1, tekstisolmu 3, ja koko dokumentti (Document) 9.

Esimerkiksi DOM:n näkökulmasta <p>Hello <strong>>World</strong></p>> on todellisuudessa:


<p>                (Element)
 ├── "Hello "            (Text)
 └── <strong>      (Element)
       └── "world"       (Text)

On hyödyllistä tiedostaa, että kaikki DOMin osat ovat nodeja – mutta kaikki nodet eivät ole elementtejä.. Esimerkiksi jos käytät childNodes-ominaisuutta DOM:n lukemiseen, saat kaikki nodet – mukaan lukien whitespace-tekstisisällöt, rivinvaihdot ja kommentit. Sen sijaan DOM:n lukeminen children-ominaisuudet tai querySelectorAll()-menetelmällä palauttaa vain elementit. Tällä on vaikutusta sekä siihen, mitä voit muokata DOMin kautta, että suorituskykyyn: mitä enemmän nodeja käsittelet, sitä raskaampi operaatio on.

DOM Level 1 - Ominaisuudet

DOM Level 1 - malli kattavan valikoiman ominaisuuksia dokumenttipuun hallintaan. Seuraavassa taulukossa on listattu nk. read-only tyyppiset ominaisuudet ja kokoelmat. Näiden avulla voit tarkastella dokumentin rakennetta ja sisältöä, mutta et voi suoraan muokata sitä.

OminaisuusSelitys
attributes[]Sisältää elementin kaikki ominaisuudet.
ChildNodes[]Kokoelma, joka sisältää solmun lapsielementit. (Huom. firstChild, lastChild)
FirstChildEnsimmäinen lapsielementti (sama kuin childNodes[0])
LastChildViimeinen lapsielementti (sama kuin childNodes[n], missä n on kokoelman viimeinen alkio)
NextSiblingPalauttaa solmun vanhemman seuraavan lapsen eli sisaren.
NodeNamePalauttaa elementin nimen.
NodeTypePalauttaa solmun tyypin kokonaislukuna (1 = elementti, 2 = ominaisuus, 3 = teksti).
ParentNodeViittaus solmun vanhempaan
PreviousSiblingPalauttaa solmun vanhemman edellisen lapsen.

Näiden lisäksi on kaksi ominaisuutta, joiden arvoa voi suoraan muuttaa (read-write):

OminaisuusSelitys
dataMerkkijono, jossa on solmun sisältämä teksti. Jos solmu ei sisällä tekstiä, arvo on "undefined".
nodeValueMerkkijono, joka sisältää solmun sisältämän tekstin. Jos solmu ei sisällä tekstiä, arvo on "null".

DOM Level 1 - Metodit

DOM Level 1 tarjoaa kattavan valikoiman metodeja dokumenttipuun hallintaan ja muokkaamiseen. Seuraavassa taulukossa on listattu tärkeimmät Document-olioon liittyvät metodit. Nämä metodit ovat olennaisia, kun halutaan dynaamisesti muokata verkkosivun rakennetta ja sisältöä JavaScriptillä.

OminaisuusSelitys
document.createElement(elementti)Luo uuden solmun.
document.createDocumentFragment()Luo uuden dokumentin osan.
document.createTextNode(data)Luo uuden tekstisolmun.
document.createAttribute(nimi)Luo elementille ominaisuuden.
document.getElementsByTagName(elementti)Palauttaa listan solmuista, jotka täsmäävät etsittävän elementin nimeen (NodeList).

HTMLDocument-oliolla on Document-olion yleisten metodien lisäksi seuraavat omat metodit:

OminaisuusSelitys
HTMLDocument.open()Avaa dokumentin sisällön kirjoittamista varten.
HTMLDocument.close()Sulkee dokumentin.
HTMLDocument.write(teksti)Kirjoittaa tekstiä avoimeen dokumenttiin.
HTMLDocument.writeln(teksti)Kirjoittaa tekstin ja rivinvaihdon avoimeen dokumenttiin.
HTMLDocument.getElementById(id)palauttaa elementin, jonka ID on annettu parametrina.

Node-olio tarjoaa useita hyödyllisiä metodeja:

OminaisuusSelitys
Node.insertBefore(lapsisolmu, viittaus)Lisää lapsisolmun ennen viittausta.
Node.removeNode (lapset)Poistaa dokumentin lapsisolmun. Jos parametri lapset annetaan, poistetaan kaikki solmun lapset. Muuten poistetaan vain itse solmu.
Node.appendChild(lapsisolmu)Lisää uuden solmun parametrina annetun solmun lapsisolmuksi.
Node.hasChildNodes()Palauttaa "true", jos solmulla on lapsia.
Node.cloneNode(lapsisolmut)Luo kopion parametrina annetusta solmusta lapsineen. Muuten kopioi vain juurisolmun.
Node.swapNode(solmu)Vaihtaa solmujen paikkaa.

Node-kokoelmat: NodeList ja HTMLCollection

Kun käsittelet DOM:ia, saat usein tulokseksi yksittäisen elementin sijaan kokoelman. DOM:ssa on useita erilaisia kokoelmia, mutta yleisimmät kokoelmatyypit ovat: :

On hyvä huomioita, että sekä NodeList ja HTMLCollection ovat objektikokoelmia. Vaikka ne muistuttuvat rakenteeltaan JavaScriptin taulukkoa, ne käyttäytyvät eri tavalla. Esimerkiksi for...of toimii molemmissa, mutta metodit kuten forEach() toimivat vain NodeListissä.

Tutustu myös näihin

Edellä olevat peruskäsitteet muodostavat pohjan taidoille, joita tarvitset aina kun haluat tehdä verkkosivusta interaktiivisen – olipa kyseessä iso kokonaisuus tai pieni yksityiskohta.

Suosittelemme tutustumaan myös seuraaviin käytännönläheisesti DOM-manipuloinnin osa-alueisiin:

DOM Level 1 - esimerkki 1

Seuraava esimerkki havainnollistaa, miten HTML-dokumentin rakennetta voidaan tarkastella DOM-mallin avulla. Tutustumme myös siihen, miten dokumentin elementteihin on mahdollista viitata ohjelmallisesti DOM-mallin kautta.


<html>
<head>
<title> Yksinkertainen dokumentti</title>
</head>

<body id="juuri">
<h1>Otsikkotaso 1</h1>
<table id="taulu">
<tbody>


<tr id="rivi1">
<td id="solu1">Jotain</td>
<td id="solu2">Jotain</td>
</tr>


<tr id="rivi2">
<td id="solu3">Jotain</td>
<td id="solu4">Jotain</td>
</tr>


</tbody>
</table>

<h1>Toinen ykkostason otsikko</h1>

</body>

Yllä olevan HTML-dokumentin puumainen rakenne on hyvin ilmeinen ja yksinkertainen. body-elementti toimii juurena ja sisältää kaksi lapsielementtiä: h1 ja table. Table-elementin sisällä on tbody, jolla on kaksi tr-elementtiä. Molemmilla taulukon rivi elementeillä on vielä kaksi omaa lasta eli solua (td- elementit).

Dokumenttipuu muodostuu solmuista, jotka vastaavat jokaista HTML-elementtiä sekä niiden sisältämää tekstiä. Jos elementille on annettu id-attribuutti, voidaan elementtiin viitata sen avulla. Esimerkissämme body-elementille on annettu yksilöllinen tunniste juuri, joten voimme käyttää sitä aloituspisteenä.


juuri = document.getElementById("juuri");

Mikäli haluamme viitata ensimmäiseen h1-elementtiin, voimme käyttää jompaakumpaa seuraavista viittauksista:


juuri.firstChild;
juuri.childNodes[0];

Table-elementtiin voimme viitata joko käyttämällä ominaisuutta childNodes tai nextSibling:


juuri.childNodes[1];
juuri.firstChild.nextSibling;

Viimeiseen elementtiin juuri ennen body elementtin sulkemista voimme viitata seuraavasti:


juuri.lastChild;
juuri.childNodes[2];

Vastaavilla tavoilla voimme viitata taulukon sisäisiin elementteihin. Koska table elementille on annettu id-attribuutti, voimme käyttää sitä juurielementtinä kun lähdemme matkaamaan dokumenttipuuta. Jos haluamme viitata taulukon ensimmäisestä rivistä takaisin body-elementtiin, voimme tehdä sen seuraavasti:


rivi1 = document.getElementById("rivi1");
rivi1.parentNode.parentNode;

Jos haluamme viitata taulukon ensimmäisen rivin toiseen soluun, se voidaan tehdä useilla eri tavoilla:


// jos aloitetaan body elementistä
juuri.childNodes[1].childNodes[0].childNodes[0].childNodes[1];
//tai
juuri.firstChild.nextSibling.firstChild.firstChild.lastChild;

//jos aloitetaan table elementistä
taulu = document.getElementById("taulu");
taulu.firstChild.lastChild.previousSibling.lastChild;
//tai
taulu.childNodes[0].childNodes[0].childNodes[1];

//jos aloitetaan tr elementistä
rivi1.lastChild;
//tai
rivi1.firstChild.nextSibling;
//tai
rivi1.previousSibling.lastChild;

Kuten aiemmat esimerkit osoittavat, elementteihin viittaamisessa on useita eri lähestymistapoja. Moni niistä johtaa kuitenkin pitkiin ja hankalasti ylläpidettäviin viittauksiin. Yleensä on helpointa käyttää lyhyitä viittauksia, esimerkiksi childNodes[]-kokoelmaa tai viittaamalla elementin vanhempaan parentElement-kutsun kautta.

DOM Level 1 - toinen esimerkki

Seuraavassa esimerkissä luodaan ja siirretään elementtejä dynaamisesti JavaScriptin avulla:


<script language="javascript">

function korvaa () {


	var elementti;
	elementti = document.lomake.elementinNimi.value;

	var sisalto;
	sisalto = document.lomake.elementinSisalto.value;

	var indeksi;
	indeksi = document.lomake.elementinIndeksi.value;

	var solmut = 0;
	solmut++;
	
	//luodaan uusi elementti ja sisalto
	var uusiElementti= document.createElement(elementti);
	var uusiElementtiSisalto = document.createTextNode(sisalto);

	// ja liitetaan ne toisiinsa
	uusiElementti.appendChild(uusiElementtiSisalto);

	//Haetaan olemassaolevat elementit
	var vanhaElementti = document.getElementsByTagName(elementti);
	//ja korvataan ensimmäinen uudella elementilla
	vanhaElementti[indeksi].replaceNode(uusiElementti);

	alert("Korvattava on "+ indeksi + ". <" + elementti + "> elementti! ");
}


function vaihda () {

	var elementti;
	elementti = document.lomake2.elementinNimi.value;

	var indeksi;
	indeksi = document.lomake2.indeksi.value;

	var uusiIndeksi;
	uusiIndeksi = document.lomake2.uusiIndeksi.value;

	//Haetaan olemassaolevat elementit
	var vanhaElementti = document.getElementsByTagName(elementti);

	//ja vaihdetaan keskenään
	//vanhaElementti[indeksi].swapNode(vanhaElementti(uusiIndeksi));

	alert("Vaihdetaan elementti "+ elementti + " indeksista " + indeksi + " indeksiin " + uusiIndeksi + " ");
	//alert("ok");
}

</script>

---

<form action="" method="POST" name="lomake" >
<p>Elementti
<input type="Text" name="elementinNimi" id="elementti"><br>
Arvo
<input type="Text" name="elementinSisalto" id="sisalto"><br>
Indeksi
<input type="Text" name="elementinIndeksi" id="indeksi"><br>

<input type="Submit" onClick="korvaa()">
</form>


<hr>

<form action="" method="POST" name="lomake2" >
<p>Elementti
<input type="Text" name="elementinNimi" id="elementti"><br>
Indeksi
<input type="Text" name="indeksi" id="indeksi"><br>
Uusi Indeksi
<input type="Text" name="uusiIndeksi" id="uusiIndeksi"><br>

<input type="Submit" onClick="vaihda()">
</form>