Kirjautuminen

Haku

Tehtävät

Oppaat: DOM: Document Object Model veppikoodaajan näkökulmasta

Kirjoittaja: Blaze. Vuosi: 2008.

Taustaa

Veppiselainten Javascript-tulkit mahdollistavat interaktiivisien veppisivujen luomisen. Perusjavascriptillä interaktiivisuus kuitenkin rajoittuu lähinnä lomake-elementtien ja kuvien manipuloimiseen. Tekniikan todellisen potentiaalin hyödyntäminen vaatii, että kaikkien veppisivun elementtien ominaisuuksia päästään muokkaamaan ja että niitä tarvittaessa voidaan luoda tai poistaa.
Tähän tarpeeseen vastaa DOM, Document Object Model.

Tämä opas on henkinen jatko-osa Javascript-perusoppaalle ja käsittelee DOMin käyttämistä Javascriptillä veppisivulla. Opas olettaa, että lukija osaa niin Javascriptin kuin HTML:nkin. XML:n ymmärtäminen on avuksi.

Niin mikä malli?

DOM kuvaa XML-dokumentin (XHTML on XML:ää, ja perinteinen HTML on tarpeeksi lähellä edellisiä, jotta sitä voidaan käsitellä samalla tavalla) elementtejä olioina, jotka muodostavat puurakenteen.

Esimerkiksi seuraava XHTML-dokumentti, jota käytetään mallina tämän oppaan ajan, voidaan esittää oheisenlaisena puuna. Jokainen puun solmu on olio, jolla on metodeja ja kenttiä, joiden avulla saadaan tietoa solmusta itsestään sekä sen sukulaisista.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fi">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<title>Mallisivu</title>
	</head>
	<body>
		<h1>Mallisivu</h1>
		<p id="mallikappale"><a href="http://fi.wikipedia.org/wiki/Lorem_ipsum">Lorem ipsum</a> dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua.</p>
		<ul id="ulompi">
			<li>eka</li>
			<li>
				<ul id="sisempi">
					<li>toka</li>
					<li>kolmas</li>
				</ul>
			</li>
		</ul>
	</body>
</html>

Spesifikaatioista

DOM kehitettiin jo 90-luvun puolivälissä: W3C DOM Level 1 -suositus julkaistiin jo vuonna 1998. Suosituksi tekniikan teki kuitenkin vasta vuosituhannen vaihteen IT-buumi. Tuon ajan valtaselaimilla, Internet Explorer 4.0:lla ja Netscape 4.0:lla, oli kuitenkin molemmilla DOMista oma, eroava, näkemyksensä. Tämän takia kaikki DOMiin liittyvä koodi piti pahimmillaan kirjoittaa kolmeen kertaan: IE:n DOMille, Netscapen DOMille sekä W3C:n standardi-DOMille. Nykyään standardi-DOM on onneksi varsin hyvin tuettu selainten keskuudessa ja pääosa koodista tarvitsee kirjoittaa vain kerran. Tämä opas käsittelee vain standardi-DOMia.

DOM Level 0 ei ole varsinainen standardi, vaan tällä nimellä kutsutaan niitä rakenteita, jotka olivat Javascriptissä olemassa ennen varsinaisen DOMin määrittelemistä. Tähän kuuluvat esimerkiksi document.forms ja document.images.

DOM-spesifikaatio on jaettu osiin, joita ovat mm. Core, HTML ja Style. Core-spesifikaatio määrittelee sellaisen objektimallin, jota voi käyttää minkä tahansa XML-dokumentin kanssa. HTML-spesifikaatio rakentuu tämän päälle ja määrittelee toimintoja, jotka ovat mahdollisia vain, kun pohjalla oleva dokumentti on (X)HTML:ää. Style-spesifikaatio määrittelee, miten tyylikielet, erityisesti CSS, kiinnittyvät DOMiin.

Suoritusajankohta

Selain suorittaa Javascriptin heti, kun se saa sen ladattua. Skriptit ovat yleensä dokumentin head-osiossa, joten on mahdollista, että skriptiä suoritettaessa viitataan elementtiin, jota ei ole vielä olemassa, koska sitä ei ole ehditty ladata.

Tämän ongelman voi kiertää käyttämällä jotain tapahtumaa (event), esimerkiksi onload, suorittamaan skriptin.

Puussa liikkuminen

Tarkastellaan ensin puurakenteen sukulaissuhteita. Kaikilla solmuilla on äitisolmu1, paitsi juurisolmulla, joka DOMissa on document-solmu. Useimmilla solmuilla on lapsisolmu tai useita lapsisolmuja. Useimmilla on myös sisaruksia, siis solmuja, joilla on sama äitisolmu.

P-elementin äiti on body, toisin sanoen p on body-elementin lapsi. P-elementillä on myös kaksi sisarusta, h1 ja ul, jotka molemmat ovat body-elementin lapsia. P-elementillä on kaksi lasta: a-elementti sekä tekstisolmu. A-elementin tekstisolmu ei ole p-elementin lapsi (mutta on sen jälkeläinen (descendant)).

Puun jokainen solmu on luokka, joka perii Node-luokan. Node-luokka sisältää kenttiä, jotka viittaavat solmun sukulaisiin.

parentNodeSisältää elementin äitisolmun. Esimerkissämme body.
childNodesSisältää nodeList-olion, joka puolestaan sisältää kaikki solmun lapsisolmut. Esimerkissämme a-elementin ja tekstisolmun.
nextSiblingSisältää seuraavan sisaruksen. Esimerkissämme ul. Mikäli solmu on äitinsä viimeinen (tai ainoa) lapsi, nextSibling on null.
previousSiblingSisältää edellisen sisaruksen. Esimerkissämme h1. Mikäli solmu on äitinsä ensimmäinen (tai ainoa) lapsi, previousSibling on null.
firstChildSisältää elementin järjestyksessään ensimmäisen lapsisolmun. Esimerkissämme a. Mikäli elementillä ei ole lapsia, firstChild on null.
lastChildSisältää elementin järjestyksessään viimeisen lapsisolmun. Esimerkissämme tekstisolmu. Mikäli elementillä ei ole lapsia, lastChild on null.

Elementtien valitseminen

Lähtemällä liikkeelle document-oliosta ja käymällä läpi kaikki sen lapset voisi puusta poimia minkä tahansa elementin tai mitkä tahansa elementit, mutta ei ole tarkoituksenmukaista keksiä pyörää joka kerta uudelleen ja niinpä DOM tarjoaa hommaan valmiita metodeita.

getElementById(elementId)Valitsee elementin sen id-attribuutin arvon perusteella, oli tuo elementti sitten missä kohtaa dokumenttia tahansa.
getElementsByTagName(tagname)Valitsee elementtejä niiden tyypin perusteella, esimerkiksi kaikki p-elementit.
getElementsByName(elementName)Valitsee elementtejä niiden name-attribuutin arvon perusteella.

getElementById-metodi löytyy vain document-oliolta. Kahta jälkimmäistä voi kutsua mille tahansa solmulle. Tällöin kriteereihin passaavia elementtejä etsitään vain tämän olion jälkeläisten joukosta.

Esimerkki

var listaSolmu = document.getElementById('sisempi');
var kohdat = listaSolmu.getElementsByTagName('li');

kohdat-muuttujassa on nyt nodeList-tyyppinen olio, joka sisältää kaksi li-elementtisolmua, "tokan" ja "kolmannen". "Eka" li-elementti ei tule mukaan, koska se ei ole "sisempi"-id:llä varustetun listan jälkeläinen.

Solmujen muuttaminen

DOM Level 2 määrittelee HTMLElement-luokalle style-kentän, jonka avulla pääsee käsiksi elementin CSS-tyyleihin. style-kenttä on assosiatiivinen taulukko, jossa on avaimina kaikki CSS-ominaisuudet ja arvoina niiden arvot.

Koska Javascriptissä ei voi käyttää viivaa asioiden nimissä, ja CSS-ominaisuuksissa viiva esiintyy usein, nimet muuntuvat hiukan: kaikki viivat poistetaan ja viivaa seurannut kirjain muutetaan isoksi. Esimerkiksi background-color muuntuu muotoon backgroundColor.

Elementtien attribuutteja voi manipuloida seuraavilla metodeilla.

getAttribute(name)Palauttaa nimetyn attribuutin arvon, tai tyhjän merkkijonon, jos elementillä ei ole kyseisen nimistä attribuuttia.
setAttribute(name, value)Asettaa nimetyn attribuutin arvoksi arvon value.
removeAttribute(name)Poistaa nimetyn attribuutin.

Lisäksi class-attribuuttiin pääsee käsiksi nopeasti className-kentän avulla.

Uusien solmujen luominen

DOM-puuta voi muokata luomalla sinne uusia solmuja tai poistamalla vanhoja.

createElement(tagname)Luo uuden elementin tyyppiä tagname. Huomionarvoista on, että luominen ei lisää elementtiä puuhun.
createTextNode(data)Luo uuden tekstisolmun, tekstinä parametrina annettu teksti.
appendChild(newChild)Lisää parametrina annetun elementin sen solmun, jolle metodia kutsuttiin, viimeiseksi lapseksi.
insertBefore(newChild, refChild)Lisää parametrina annetun elementin sen solmun, jolle metodia kutsuttiin, lapseksi juuri ennen parametrina annettua toista elementtiä.
removeChild(oldChild)Poistaa parametrina annetun elementin puusta.

Puun muutokset tulevat näkyviin heti koodin suorittamisen jälkeen.

Esimerkki

Esimerkissä luodaan uusi img-elementti, asetetaan se näyttämään Ohjelmointiputkan logo ja lisätään se tekstikappaleen loppuun.

var kuvaSolmu = document.createElement('img');
kuvaSolmu.setAttribute('src',
	'http://www.ohjelmointiputka.net/img/putka.jpg');
kuvaSolmu.setAttribute('alt', 'Ohjelmointiputka');
kuvaSolmu.style.display = 'block';
var kappaleSolmu = document.getElementById('mallikappale');
kappaleSolmu.appendChild(kuvaSolmu);

Skriptin suorittamisen jälkeen elementti on osa puuta, aivan kuin elementti olisi kirjoitettu suoraan HTML-merkkauksella.

nodeName, nodeValue

Jokaisella solmulla on kentät nodeName ja nodeValue. nodeName kertoo, minkätyyppisestä solmusta on kysymys. Elementtisolmuilla sen arvo on elementin nimi. Tekstisolmun nodeName on aina merkkijono "#text". Dokumentin juurisolmun nimi on "#document".

nodeValue on useimmilla solmutyypeillä null. Tekstisolmuilla sen sisältö on solmun sisältämä teksti. Tekstiä voi vaihtaa muuttamalla nodeValue-kentän arvoa.

Esimerkki

Vaihdetaan h1-otsikon tekstiksi "Testisivu".

var otsikkoSolmu = document.getElementsByTagName('h1')[0];
// varmistetaan, että käsitellään tekstisolmua
if(otsikkoSolmu.firstChild.nodeName == '#text') {
	otsikkoSolmu.firstChild.nodeValue = 'Testisivu';
}

Hyödyllisiä linkkejä

1Oikeammin: "vanhempi-solmu" (parent node). Mielestäni tuo kuitenkin kuulostaa niin pöljältä, että käytän termiä "äitisolmu".

Kommentit

MikaBug [24.01.2008 20:55:27]

Lainaa #

Hieno opas, ja todellakin JS-oppaiden jatkoksi! Paljon uutta ja tarpeellista tietoa tuli ainakin minulle. Kiitos!

Meitzi [29.01.2008 23:43:39]

Lainaa #

Vielä Ajax jatko?

php-Niko [05.03.2008 13:59:32]

Lainaa #

Hmm.. Hyvä opas, mutta...

En tiedä onko kyseessä virhe vai ei, koska en ole aivan nero JS:ssä ja tekijän ajatusten lukemisessa.

Ensinmäinen esimerkki:

...
<p id="mallikappale"><a href="http://fi.wikipedia.org/wiki/Lorem_ipsum">Lorem ipsum</a>bla bla bla...</p>
...

Tokavika esimerkki:

...
var kappaleSolmu = document.getElementById('testikappale');
...

mallikappale = testikappale ?

Tää on tälläistä pilkunviilausta. En vain tiedä liittyykö noi mitenkään toisiinsa.

E: Ok. Eli olin oikeassa, jee. ^^

Blaze [05.03.2008 14:04:53]

Lainaa #

Tarkotus oli, että kaikki esimerkit liittyy tuohon alussa esiteltyyn mallisivuun. Korjattu.

Pollapoju [19.07.2008 12:47:26]

Lainaa #

Erinomainen opas.

punppis [04.04.2009 22:41:01]

Lainaa #

Pari kysymystä. Onko jotenkin väärin jos vaihtaa kuvan alt-attribuuttia esim. näin:

var solmu = document.getElementById("kuva");
solmu.alt = "Kuvan alt-attribuutti vaihdettu";

Tai jos vaihtaa tekstisolmun arvoa näin:

document.getElementById("teksti").innerHTML = "Teksti vaihdettu.";

Petja [13.02.2012 19:25:39]

Lainaa #

En näe mitää väärää esimerkeissäsi, punppis. Tosin kannattaisi käyttää jQueryä, mutta se on sitten ihan toinen asia.

Kirjoita kommentti

Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.

Muista lukea keskustelun ohjeet.
Tietoa sivustosta