Javascript ja DOM

Harjoitellaan Javascriptin ja DOM-rajapinnan perusteita.

Mallivastaus (malli.zip)

Alkuvalmistelut

Hello World

  1. Tallenna käyttöösi valmis dokumenttipohja johonkin väliaikaishakemistoon.
  2. Pura paketti W:\TIEA2120-hakemiston alihakemistoon ohjaus2.
  3. Luo haluamallasi editorilla nanonano.js-tiedosto samaan kansioon tallentamasi dokumenttipohjan kanssa.
  4. Avaa editoriin ja Firefox-selaimeen Nanonanon kotisivu index.html.
  5. Linkitä nanonano.js HTML-dokumentin head-osaan script-elementillä.
    <script src="nanonano.js"></script>
  6. Kirjoita nanonano.js-tiedostoon ensin yksinkertaisin mahdollinen Javascript-ohjelma:
    "use strict";
    alert("Hello world");
    
  7. Lataa sivu uudelleen selaimessa. Jos kaikki meni ok niin näytölle pitäisi ilmestyä dialogi jossa lukee Hello world.
  8. Dialogi ilmestyy jo ennen sivun sisältöä joten korjataan ohjelmaa sen verran, että sivu ilmestyy ensin ja vasta sitten dialogi. Siirrä alert-funktiokutsu window-luokan onload-tapahtumankäsittelijäfunktioon.
    "use strict"; // estää pahimpia virheitä
    
    // liitetään oma funktio window.onload-tapahtumaan, joka tapahtuu sitten kun koko html-dokumentti ja siihen liittyvät
    // kuvat ja muut tiedostot on ladattu
    window.onload = function() {
      alert("Hello world");
    };
    
  9. Kokeile ladata sivu uudelleen (reload). Nyt dialogi ilmestyy vasta dokumentin latauduttua.
  10. Kommentoi (// tai /* */) alert-komento pois ennen seuraavia tehtäviä.

Elementtien hakeminen ja muuttaminen

Haetaan dokumentissa olevia elementtejä ja muutellaan niiden sisältöä.

Otsikoiden numerointi

  1. Lisää uusi funktio numeroi ja kutsu tätä window.onload-tapahtuman käsittelijäfunktiossa.
  2. Hae numeroi-funktiossa kaikki h2-elementit sopivan nimiseen muuttujaan. Tämä onnistuu document.getElementsByTagName-metodilla. getElementsByTagName-funktio palauttaa aina NodeList-tyyppisen listan riippumatta siitä montako alkiota löytyi. NodeList toimii kuten taulukko. document.getElementsByTagName etsii aina koko DOM-puusta. Elementti.getElementsByTagName etsii aina kyseisen elementin alla olevasta dokumenttihaarasta.
  3. Käy for-silmukassa läpi listassa olevat h2-elementit. Listan alkioiden määrän saa length-metodilla.
  4. Haetaan h2-elementtien tekstit
    • Yksittäisen h2-elementin NodeListista saat item-metodilla tai []-operaattorilla.
    • Kunkin elementin sisällä oleva teksti muodostaa vielä oman TextNode-tyypin olionsa.
    • Tämän saat h2-elementin firstChild-attribuutista.
    • Varsinaisen tekstin (String-tyyppiä) saa nodeValue-attribuutista.
    • Kokeile miten h2-elementin textContent-ominaisuus toimii. Sillä saat suoraan jonkun elementin koko tekstisisällön eikä tarvitse välittää erillisistä TextNodeista
  5. Aluksi tekstin voit tulostaa konsoliin ja testata tuleeko sinne tekstiä. Arvoja voit myös tutkia debuggerilla.
  6. nodeValue- tai textContent-attribuuttiin voi myös asettaa arvoja. Lisää sivulle näkyviin kunkin nykyisen otsikon eteen vielä for-silmukassa käytetyn indeksin arvo. Kokeile. Numerointi ei vielä mene oikein, joten lisää kierrosnumeroon vielä yksi.

Menu

Avautuva menu

Tehdään yksinkertainen menu, jossa alakohtia voidaan piilottaa.

  1. Luo dokumentin alkuun HTML:ää kirjoittamalla kaksitasoinen sisäkkäinen lista, jossa on pääkohdat Artikkelit, Harkat ja Linkit ja näiden alle pari listakohtaa, joiden sisällä on linkit. Kts. edellä oleva kuva. Lisää näiden listakohtien eteen img-elementillä minus.jpg-kuva merkitsemään avattua menukohtaa.
  2. Merkitse ulompi lista sopivalla id-attribuutilla.
  3. Muotoile CSS:llä listan ulkoasu ja liu'uta (float) se sivun oikeaan laitaan.
  4. Luo nanonano.js-tiedostoon uusi funktio muuta_nakyvyys ja aseta funktion ensimmäisen parametrin nimeksi event.
  5. Hae window.onload-tapahtumankäsittelijässä edellä määrittelemälläsi id:llä varustettu ul-elementti johonkin muuttujaan document.getElementById-funktiolla. Tämä funktio palauttaa aina yhden elementin.
  6. Pyydä kaikkia tämän ul-elementin alla olevia img-elementtejä getElementsByTagName-metodilla.
  7. Käy for-silmukalla img-elementtilista läpi ja lisää kunkin elementin click-tapahtuman käsittelijäksi funktio muuta_nakyvyys.
    elementti.addEventListener("click", muuta_nakyvyys);
  8. Selvitä muuta_nakyvyys-funktion alussa mikä elementti on aiheuttanut tapahtuman. Tämä selviää muuta_nakyvyys-funktiolle parametrina tulevan event-olion target-attribuutista. Voit esim. kokeilla mitä tekee console.log(event.target.nodeName) tai katsoa debuggerilla mitä event-parametri pitää sisällään.
  9. Muuta kuvan (event.target) src-attribuutin arvoksi plus.jpg. Kts. setAttribute. Kokeile selaimella.
  10. Lisää logiikkaa ja aseta src-attribuutiksi plus.jpg jos ennen oli minus.jpg, muutoin toisinpäin. Muuta myös alt-attribuutin tekstiksi Auki/Kiinni tilan mukaan. Testaa toimintaa.
  11. Tutki Inspectorilla millainen puu sisäkkäisestä listasta muodostuu.

    HTML inspector firebugissa

  12. Selvitä, miten pääset käsiksi tapahtuman aiheuttanutta img-elementtiä seuraavaan (sibling) ul-elementtiin. Tapoja on monia, voit joutua käyttämään esim. joitain seuraavista attribuuteista/metodeista: parentNode, childNodes, nextSibling, nodeName ja getElementsByTagName (kts. elementtien hakeminen).
  13. Piilota sisempi ul-elementti samalla kun asetat src-attribuutin arvoksi plus.jpg, muutoin näytä elementti.
    • Elementin näkyvyyttä voi muuttaa esimerkiksi className-attribuuttia muokkaamalla.
    • Lisää CSS-tiedostoon luokka, jossa on ominaisuus display: none;.
    • Elementin saa näkyväksi poistamalla class-attribuutin. Tämä onnistuu removeAttribute-metodilla.

Elementtien lisäys

Lisätään elementtejä sivulle dynaamisesti DOM-rajapinnan avulla.

Linkit tekstiksi linkkilistaan

Linkit tekstiksi a-elementin jälkeen

  1. Luo uusi funktio linkit ja kutsu sitä window.onload-käsittelijäfunktiossa.
  2. Merkitse id-ominaisuudella dokumentin lopussa oleva ul-elementti.
  3. Hae linkit-funktiossa id:llä varustettu ul johonkin muuttujaan.
  4. Pyydä kaikkia tämän elementin alla olevia a-elementtejä getElementsByTagName-metodilla.
  5. Tee for-silmukka ja hae kunkin a-elementin http-osoite href-ominaisuudesta ja tulosta se konsoliin. Tämä onnistuu getAttribute-metodilla.
  6. Luo osoitteesta uusi tekstisolmu createTextNode-metodilla.
  7. Lisää se kyseisen a-elementin sisältävän li-elementin loppuun. Tarvitset parentNode-attribuuttia ja appendChild-metodia.
  8. Kokeile toimiiko skripti. Ulkoasua voi parantaa lisäämällä tekstin alkuun vielä yhden välilyönnin. Koodin uudelleenkäytettävyyttä voi vielä parantaa siten, että funktion parametriksi laitetaan id, tämä id haetaan dokumentista ja tämän jälkeläisinä olevat linkit "tekstitetään".

Yhteenlaskupeli

Rivejä joissa kaksinumeroisia lukuja ja tekstikenttä niiden summaa varten

Tehdään Nanonanon sivuille päässälaskun harjoitteluun pieni yhteenlaskutehtäviä generoiva peli.

  1. Lisää h2-otsikko ja sen alle div-lohko, jonka on id-ominaisuuden arvo on laskut. Lisää myös painike Tarkista, jolla on myös oma id-ominaisuuden arvonsa.
  2. Tee funktio luo_lasku, joka ottaa parametrinä rivin numeron ja palauttaa p-elementin, joka sisältää arvotun laskutehtävän tekstinä ja tekstilaatikon vastaukselle. Tuotettu elementti on muotoa:
    <p><span id="ekaluku_riviX">LUKU1</span> + <span id="tokaluku_riviX">LUKU2</span>
     = <input id="summa_riviX" type="text" size="3" /></p>
    • Elementin runko-osan saa luotua helposti DOMTool-työkalulla. Kopioi elementit HTML-osaan ja napauta Create DOM Statements. Kopioi DOM-koodi js-tiedostoosi. Palautettava elementti löytyy Nodes to Append -osasta.
    • Muuta id-attribuuttien asettamista siten, että X:n tilalle tulee parametrina annettu numero.
    • Arvo tekstien LUKU1 ja LUKU2 tilalle jotkin luvut väliltä 0-99. Tämä onnistuu Math.random-metodilla.
  3. Tee funktio luo_laskut, joka luo kymmenen laskua for-silmukassa ja lisää ne laskut-div-lohkon sisälle. Kutsu luo_lasku-funktiota silmukan kierrosluvun arvolla. Lisää luo_laskut-funktiokutsu window.onload-tapahtuman käsittelijään.
  4. Tee CSS-tiedostoon uusi luokka .virhe, joka muuttaa elementin taustanvärin punaiseksi ja tekstinvärin mustaksi.
  5. Tee funktio tarkista_laskut. Lisää tämä funktio window.onload-tapahtuman käsittelijässä tarkista-napin click-tapahtuman käsittelijäksi.
  6. Käy tarkistuksessa kaikki rivit läpi for-silmukassa ja tarkista ovatko kaikki laskut oikein.
    • Summaa luvut yhteen ja vertaile onko luku sama kuin tekstilaatikossa.
      • Luvut sisältävät elementit saat document.getElementById-metodilla. Lisää id-arvojen runkojen ekaluku_rivi, tokaluku_rivi ja summa_rivi perään silmukan kierroksen numero.
      • Tekstin saa textContent- tai nodeValue-attribuutilla. Tekstikenttään (input-elementti) syötetyn arvon saa value-ominaisuudesta. Huom. ei html-koodin attribuutista vaan DOM-objektin value-ominaisuudesta.
      • Summausta varten luvut on muutettava integer-tyyppisiksi parseInt-funktiolla
    • Jos laskettu luku ei ole oikein, niin laita tekstilaatikon class-attribuuttiin arvo virhe.
    • Jos rivi on kunnossa, niin poista class-attribuutti
    • Jos kaikki rivit ovat ok, niin ilmoita painikkeen alapuolella sopivalla tekstillä pelin läpipääsystä.
  7. Testaa "pelin" toimintaa.

Tapahtumat

Lisätään Javascriptillä elementteihin tapahtumia.

Tapahtumankäsittelijän lisääminen

  1. Luo johonkin kohtaan dokumenttia painike button-elementillä. Anna painikkeelle jokin id-arvo ja näkyvä teksti Hello world.
  2. Luo uusi funktio varoitus ja siirrä alert-kutsu sinne.
  3. Lisää onload-tapahtuman käsittelijään koodi, joka hakee napin väliaikaismuuttujaan. Tämä onnistuu document-olion getElementById-metodilla.
  4. Aseta painikkeelle click-tapahtuman käsittelijäksi funktio varoitus addEventListener-metodilla.
  5. Testaa napin toimintaa. Javascript-virheet näkee helposti konsolista:

    Firebug-laajennuksen virheikkuna

  6. Muuta ohjelman toimintaa siten, että Hello world ilmestyy vain tuplaklikkauksesta (kts. HTML:n tapahtumat).

Jos aikaa jäi, niin kokeile vielä toteuttaa uuden pelin arpominen ja vastaamisen kuluneen ajan laskeminen pelin uudelleenaloituksesta hyväksyttyyn tarkistukseen.

Mallivastaus (malli.zip)

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/tiea2120/ohjaus/ohjaus2/
© Tommi Lahtonen (tommi.j.lahtonen@jyu.fi) <http://hazor.iki.fi/>
2017-09-20 09:26:15
Informaatioteknologia - Jyväskylän yliopiston informaatioteknologian tiedekunta