JavaScript ja DOM

Käsitellään JavaScriptin ja DOM:n käyttöä WWW-sovelluksissa.

Luentotaltiointi

Ongelmia videon katselussa?

Työvälineet

Historiaa

Javascript on alunperin kehitetty Netscape-selaimeen 1990-luvulla. Microsoft kehitti oman versionsa nimeltään JScript vähän Netscapen jälkeen. Javascript-kieli on standardoitu ECMAScript-standardissa. ECMAScript-kieltä kehitetään edelleen. Tällä hetkellä on käytössä Javascript 1.8 (Firefox 2).

Eri Javascript-versioita:

Javascript-yhteensopivuus on aina ollut hieman ongelmallista mutta nykyään asia voidaan hoitaa käyttämällä valmiita kirjastoja.

JavaScript-tiedoston linkittäminen

script-elementillä head-osassa:

<script type="text/javascript" src="jokutiedosto.js"></script>

Syntaksi

Javascriptin syntaksista kannattaa lukea seuraavia lähteitä:

Ympäristö

JavaScriptiä suoritetaan määrätyssä ympäristössä, joka voi olla esimerkiksi selaimessa. JavaScript ei itsessään määrittele, miten tietoa voidaan syöttää tai tulostaa, vaan se tarjoaa ainoastaan tiedon käsittelymekanismit. Tiedon syöttö ja vasteiden anto tehdään käyttäen XHTML:ää ja DOM:ia.

Yleistä

Muuttujat

JavaScript on heikosti tyypitetty kieli. Muuttujien tyyppi määräytyy siis arvon perusteella. Muuttujat esitellään seuraavasti:

var x = 1.0;
var s = "Diiba daaba";
totuus = true; // globaali muuttuja, näkyy kaikissa funktioissa

Huomioi seuraavaa:

Operaattorit

Käytössä on normaalit aritmeettiset ja vertailuoperaattorit.

Merkkijonot

Merkkijonot ovat olioita, joilla mm. seuraavia metodeja:

Merkkijonoja voi operoida seuraavilla operaattoreilla:

+
Liittää merkkijonot yhteen
< > <= >= ==
Vertailee aakkosjärjestystä
s[n]
Antaa merkkijonon s n:nnen kirjaimen

Merkkijonojen tyyppien muunnoksiin on olemassa muutama globaali funktio:


var luku = parseInt("567");
var luku = parseInt("567", 10); // toinen argumentti kertoo kantaluvun. Tässä kymmenjärjestelmä
var luku = parseInt("0567"); // ei toimi kuten voisi kuvitella. etunolla tarkoittaa, että luku saatetaan käsitellä oktaalijärjestelmässä.
var luku = parseInt("0567", 10); // tämä toimii
var luku = parseInt("101", 2); // binääriluku

Taulukot

Taulukko luodaan Array-oliolla

var paikat = new Array();
paikat[0] = "Jämsä";
paikat[1] = "Äänekoski";

tai hakasulkeilla:

var paikat = ["Jämsä", "Äänekoski"];

Taulukkoon lisääminen onnistuu seuraavasti:

paikat[paikat.length] = "Jyväskylä";
paikat.push("Jyväskylä");

Assosiatiivisia "taulukoita" (nimi-arvo-pareja) voi tehdä seuraavasti:

var lampo = new Object;
lampo["jkl"] = -6;
var saatilat = {
  jämsä: "Aurinkoinen",
  äänekoski: "Pilvipoutaa"
};

for (var i in saatilat) {
	alert( i + " : " + saatilat[i] );
}

Assosiatiivinen "taulukko" on itseasiassa olio, jolla on attribuutteja. Tämä voi aiheuttaa jossain tilanteissa hämmennystä.

Funktiot

Funktion voi esitellä seuraavasti:

function summaa(x,y) {
  return (x + y);
}

summaa = function(x,y) {
  return (x + y);
}

Huomioitavaa:

Oliot

JavaScript (joka pohjautuu Ecmascript 3 -standardiin) on prototyyppi-pohjainen kieli ja siinä ei ole luokkia samassa mielessä kuin Java/C++/C#-kielissä vaan pelkästään olioita (objekteja). JavaScriptissä omia olioita voidaan luoda seuraavasti:

// konstruktori-funktio
function Koordinaatti(x,y) {
  this.x = x;
  this.y = y;
}

// Koordinaatin "public-metodi"
Koordinaatti.prototype.normi = function() {
  return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}

var piste = new Koordinaatti(1,2);
piste.normi();

Olioita laajennetaan toisten olioiden avulla käyttäen prototype-määritystä. Private-attribuutteja ja -metodeja on mahdollista luoda pienellä vaivalla.

Ohjausrakenteet

Javascriptissä on normaalit ohjausrakenteet:

Tarpeellisia funktioita

Aika

Päivämäärä

var aika = new Date();
alert(aika.getDate() + "." + aika.getMonth() + "." + aika.getYear());

Kulunut aika

var aika = new Date();
var hetkiA_msec = aika.getTime();
// tehdään jotain
var hetkiB_msec = aika.getTime();
var kulunutaika = new Date(hetkiB_msec - hetkiA_msec);
alert(kulunutaika.getSeconds());

Ajastetut funktiot

// suoritetaan oma_ajastettu_funktio joka sekunti
window.setInterval(oma_ajastettu_funktio,1000);

Math

Pyöristäminen

var liukuluku = 3.245200004;
var kaksidesimaalia = Math.round(liukuluku*100)/100

Satunnaisluvut

var sanoja = ["Diiba","Daaba","Tesmaus","Heppa","Muuli","Saippuakauppias","Jepjep"];
// pyöristys alaspäin( 0-0.999999999 * 7 )
var rand = Math.floor( Math.random() * sanoja.length );
console.log(sanoja[rand]);

eval

Funktiot: eval - Core JavaScript 1.5 Reference

Esimerkki:

// XHTML-dokumentissa
<p><span id="lasku">3 + 4</span> = <strong id="tulos"></strong></p>
// JavaScript-funktiossa
var yhteenlasku = document.getElementById("lasku").firstChild.nodeValue;
var tulos = eval(yhteenlasku);
document.getElementById("tulos").firstChild.nodeValue = tulos;

Toinen esimerkki:

// XHTML-dokumentissa
<p><input type="text" id="funktio" onchange="suorita" /></p>
// JavaScriptissä:
function ykkonen() {
  alert("Funktiossa ykkonen!");
}
function kakkonen() {
  alert("Funktiossa kakkonen!");
}
function suorita() {
  var funktion_nimi = document.getElementById("funktio").value;
  eval(funktion_nimi + "()");
}

eval on hidas verrattuna normaaleihin laskutoimituksiin ja funktiokutsuihin

isNaN

Tutkii onko muuttuja erikoisarvoa NaN (not a number). NaN-arvoa ei voi vertailla muulla kuin tällä funktiolla.

var numero = parseInt(document.getElementById("tekstikentta").value);
if (isNaN(numero))
  document.getElementById("tekstikentta").className = "red";

typeof

Operaattorit: typeof - Core JavaScript 1.5 Reference

Palauttaa stringinä muuttujan tyypin.

Tapahtumat

Javascript-funktioiden suoritus kytketään tiettyyn tapahtumaan, esimerkiksi kun sivu on ladattu tai käyttäjä tekee jotain. XHTML-elementeille voi antaa ominaisuuksia, jotka liittyvät tiettyyn tapahtumaan. Ominaisuuden arvoksi annetaan haluttu funktio. Esim.

<input onchange="laske_arvosana()" id="vt1" size="3" maxlength="3" value="0" />

Tapahtumia ei yleensä kannata määrätä kiinteästi elementteihin, sillä kaikissa selaimissa ei ole JavaScript-tukea. Tapahtuman voi määrätä myös erillisessä Javascript-tiedostossa seuraavasti:

elementti.tapahtumatyyppi = käsittelijäfunktio;

Selaimen tarjoamiin globaaleihin olioihin voi myös määrätä tapahtumia, esim.

window.onload = function() {
  // sivun latauksen jälkeen tapahtuvat toimenpiteet
}

Seuraavassa dokumentissa on lista erilaisista tapahtumista selitteineen:

Ylläolevissa esimerkeissä tapahtumankäsittelijäksi voi määrätä vain yhden funktion. DOM-standardi määrittää kuitenkin paremman tavan tapahtumien rekisteröinnille ja mahdollistaa useiden tapahtuman käsittelijöiden liittämisen tapahtumaan:

elementti.addEventListener(tapahtumantyyppi, käsittelijäfunktio, kaappaus);

Tarkempaa tietoa missä järjestyksessä tapahtumat käsitellään:

Esim. tapahtumankäsittelijän kytkeminen useaan elementtiin:

window.onload = function() {
  for(var i=1;i<=9;i++) {
    document.getElementById("vt" + i).addEventListener("change", laske_arvosana, false);
  }
}

Tästä on myös sekin etu, että rekistöidyssä funktiossa saa viitattua tapahtuman aiheuttaneeseen elementtiin this-muuttujan avulla (tai evt.target:lla) ja yhteen tapahtumaan voidaan liittää useita tapahtuman käsittelijöitä.

Oletustapahtuman voi peruuttaa kutsumalla e.preventDefault()-funktiota.

Tapahtuman välittymisen muille käsittelijöille voi estää kutsumalla e.stopPropagation()-funktiota

Tapahtumien rekisteröintiin on myös olemassa funktioita, jotka korjaavat selaimien väliset erot:

Selaimien välillä on muitakin yhteensopivuusongelmia, joten samalla vaivalla kannattaa ottaa käyttöön jokin kirjasto, joka hoitaa likaisen työn. Näitä kirjastoja tarkastellaan Ajax-luennon yhteydessä.

Document Object Model (DOM)

DOM on standardi, jonka avulla voidaan manipuloida dynaamisesti dokumenttipuuta.

JavaScriptin ja DOM-rajapinnan avulla voidaan muokata dokumenttipuuta.

Dokumentin rakennetta voi tutkia esim. Firebugin HTML-välilehdeltä.

Hyvä rakenne - otsikkotasot löytyvätHuono rakenne - ei otsikkotasoja ja liian syvä Xetor-ohjelman rakennenäkymä

Kukin elementti ja teksti muodostavat dokumenttipuuhun Node-tyypin olion. DOM:in tarjoamia attribuutteja ja metodeja voi tarkastella Firebugin DOM-välilehdeltä. Valitse aluksi esim. document ja sen alta documentElement, niin pääset tutkimaan html-elementtiä.

Käsitteitä

vanhempi-, äiti- tai isäelementti (engl. parent)
elementti, jonka sisällä ko. elementti välittömästi on.
lapsielementti (engl. child)
välittömästi ko. elementin sisällä oleva elementti
jälkeläinen (engl. descendant)
ko. elementin sisällä oleva elementti
esivanhempi, esiisä (engl. ancestor)
elementti, jonka jälkeläinen ko. elementti on
sisarelementti (engl. sibling)
elementit ovat sisaret, jos niillä on yhteinen vanhempielementti
edeltävä/seuraava sisarelementti (engl. preceding/following sibling)
edeltävä elementti on dokumenttipuussa ennen ko. elementtiä, seuraava on sen jälkeen

JavaScript kytkeytyy DOM:iin mm. seuraavien olioiden ja metodien kautta:

Elementtien saanti

Elementtien lisääminen ja poistaminen

Elementtien arvot

Huomattavaa

Lisätietoa

Esimerkkejä

Esimerkit luennolla 4.

Huomioitavaa

Javascriptin ja DOMin käytössä tulee huomioida seuraavat asiat:

luentomalli

malli.js

Käyttäjien kommentit

Kommentoi Lisää kommentti
Kurssimateriaalien käyttäminen kaupallisiin tarkoituksiin tai opetusmateriaalina ilman lupaa on ehdottomasti kielletty!
http://appro.mit.jyu.fi/web-sovellukset/luennot/luento3/
© Tommi Lahtonen (tommi.j.lahtonen@jyu.fi) <http://hazor.iki.fi/>
2016-01-25 10:42:21
Informaatioteknologia - Jyväskylän yliopiston informaatioteknologian tiedekunta