Document Object Model (DOM) ja tapahtumankäsittely - Viikkotehtävä 2
Tässä tehtävässä opitaan HTML5-dokumentin rakenteen muokkausta DOM-rajapinnan avulla ja tapahtumankäsittelyä.
Käy ensin läpi nämä luentomateriaalit:
- Document Object Model (DOM)
- WWW-lomakkeet
- Lomakkeet
- DOM ja tapahtumat - esimerkkejä
- Document Object Model (DOM) ja tapahtumankäsittely - pääteohjaus
- Fetch ja asynkroniset funktiot
Yhteiset vaatimukset
Kaikille tasoille yhteiset vaatimukset ovat:
- Käytetään vain Javascript-ohjelmointikieltä.
- Javascript-ohjelmassa on käytettävä Strict modea
- Ohjelma pitää toteuttaa pohjaksi annettuun XHTML5-dokumenttiin. Pohjadokumenttia saa vapaasti muokata, mutta valmiiksi pohjaan linkitettyjä skriptejä ei saa poistaa tai muuttaa.
- Kaikki funktiot, jotka sallivat lisätä suoraan käsin kirjoitettua html-koodia sivun sisältöön ovat
kiellettyjä. Vastauksen tasosta riippumatta tuloksena on 0 pistettä, jos tätä kieltoa rikotaan. Kiellettyjä ovat
ainakin seuraavat funktiot ja propertyt:
- innerHTML - saa lukea (get), mutta ei saa asettaa (set), mutta vain tallennuksen yhteydessä
- outerHTML - saa lukea (get), mutta ei saa asettaa (set), mutta vain tallennuksen yhteydessä
- adjacentHTML
- setHTML
- innerText
- write
- writeln
- alert
- Ulkoisten kirjastojen käyttäminen on kielletty. Poikkeuksen tekevät valmiiseen pohjaan jo linkitetyt validointikirjastot.
- Ulkoasun muokkaukseen saa käyttää DOM-operaatioita. Saa käyttää myös omaan CSS-tiedostoon luotuja tyylejä. Xhtml-tiedostossa ei saa esiintyä CSS-koodia.
- XHTML5-tiedostossa ei saa esiintyä javascript-koodia. Kielto koskee myös javascript-koodilla dynaamisesti HTML-koodiin lisättyä javascript-koodia.
- XHTML-tiedoston rakenteen täytyy olla validia
XHTML5/HTML5:sta eli XML-yhteensopivasti kirjoitettu HTML5:sta. Sivun täytyy pysyä
validina myös javascriptilla tehtyjen dynaamisten muutosten jälkeen.
Valmiiseen pohjaan on lisätty puoliautomaattinen W3C:n validaattori, jonka validoinnin voi suorittaa näppäinyhdistelmällä CTRL+ALT+V. Mahdolliset virheet näkyvät konsolissa.
Valmiissa pohjassa on myös automaattinen htmlinspector-tarkistus, joka suoritetaan automaattisesti aina, kun sivun rakenne dynaamisesti muuttuu. Mahdolliset virheilmoitukset näkyvät konsolissa.
- Valmiin ohjelman pitää toimia Firefox-selaimella (v116.0 tai uudempi) ja Googlen Chromella (v116.0 tai uudempi). Muista selaimista ei tarvitse toistaiseksi välittää.
- Koodin oleelliset osat on oltava kommentoitu.
- Kaikkien tiedostojen merkistönä on käytettävä UTF-8-merkistöä.
- Button lähettää aina oletuksena lomakkeen sisällön www-palvelimelle eli
käytännössä selain yrittää siirtyä uudelle sivulle.
Tämä täytyy estää preventDefault()-kutsulla, jotta ohjelma toimisi järkevästi.
Sivu ei saa latautua uudelleen ohjelmaa käytettäessä
- Älä käytä lomakkeissa reset-painiketta. HTMLFormElement.reset-metodia taasen pitää käyttää.
- Mahdollisten id-attribuutin arvojen pitää olla uniikkeja eivätkä ne saa alkaa numerolla tai sisältää välilyöntejä. Kts. MDN:id
- Tehtävissä vaadittuja järjestämisiä varten ei saa kirjoittaa omaa järjestysfunktiota. On käytettävä javascriptin tarjoamaa valmista sort-funktiota ja kirjoitettava tarpeen mukaan vain omia vertailufunktioita.
- Valmiissa pohjassa oleva JSHint ei saa antaa koodista mitään varoituksia tai virheilmoituksia. Valmiiseen pohjaan on linkitetty automaattinen JSHint-tarkistus. Mahdolliset virheilmoitukset näkyvät konsolissa.
- Tapahtumankäsittelijöitä saa lisätä vain addEventListener-funktiolla. Kaikki muut tavat ovat ehdottomasti kiellettyjä.
- Javascript-objekteihin saa
(ja kannattaa) keksiä omia attribuutteja. kts. Attributes and properties.
let input = document.createElement("input"); // seuraava on suositeltavaa ja tarpeellista input.omajuttu = "tallennan tänne jotain omaa tietoa"; input.oma = objekti;
- Sovelluksen tila tallentuu palvelimelle. Tarvittaessa tilan voi resetoida käymällä osoitteessa: https://appro.mit.jyu.fi/cgi-bin/tiea2120/vt2.cgi/clear. Tila resetoituu myös poistamalla kyseisen sivun evästeet tai selaimen istunnon vanhennettua ( 60 min ).
- Sivun lomakkeissa saa käyttää input-elementeissä vain seuraavia tyyppejä: text, radio, checkbox ja submit. Syöttökentissä ei saa käyttää html-koodissa määriteltäviä rajoitteita kuten required, pattern, min, max, maxlength tai minlength. Näiden käyttämiseen tutustutaan viikkotehtävässä kolme. Kaikkien tehtävässä mainittujen rajoitteiden tarkistukset on ohjelmoitava itse javascriptilla.
- Vinkkejä
- Jos haluat tyhjentää elementin sisällön tee:
elementti.textContent = "";
- Elementin voi poistaa remove()-metodilla:
elementti.remove();
- Sivulla näkyvien DOM-objektien järjestäminen ei ole järkevää, koska se on toivottoman raskasta ja hidasta. Järjestä tarvittaessa sisäinen tietorakenne, jonka perusteella vasta lopuksi päivität sivunäkymän (DOM-puun).
- Jos järjestämisessä on useita järjestysehtoja, et tarvitse järjestämistä useaan kertaan, vaan kirjoitat vertailufunktion, joka osaa kaikki tarvittavat ehdot
- Selaimet muistavat hanakasti lomakkeisiin syötettyjä tietoja. Sivun kaiken sisällön saa nollattua ja ladattua uudelleen SHIFT+CTRL+R-näppäinyhdistelmällä.
- Jos haluat tyhjentää elementin sisällön tee:
Taso 1
Luo itsellesi gitlabiin oma haara valmiista pohjasta. Katso pohja.xhtml-tiedostosta ja vt2.js-tiedostosta vinkit sekä valmiit apufunktiot (vt2-apufunktiot.js).
Data on tällä kerralla XML-muodossa. Joudut DOM-operaatioiden avulla muuntamaan xmldatan ainakin osittain helpommin javascriptilla käsiteltävään muotoon. Voit tutkia xmldataa osoitteessa: https://appro.mit.jyu.fi/cgi-bin/tiea2120/vt2.cgi/.
Xmldatan rakenne ei ole aivan sama kuin aikaisemmin! Joukkueen sarja tai leimaukset eivät ole nyt viitteitä vaan niissä on vastaavan sarjan tai rastin tunniste, jonka perusteella täytyy etsiä oikea sarjaobjekti tai rastiobjekti. Leimaukset eivät myöskään ole suoraan joukkueen yhteydessä. Vinkki: Luo oma objekti, johon kopioit viitteet kaikkiin sarjoihin. Käytä objektissa avaimena sarjan id:tä. Tämän objektin avulla on helppo löytää aina kutakin id:tä vastaava sarja ilman silmukoita. Vastaavan voi tehdä myös muille elementeille, joita tarvitset usein.
Muokkaa pohja.xhtml- ja vt2.js-tiedostoja ja kirjoita Javascript-ohjelma, joka tekee seuraavat asiat.
- Listaa www-sivulla taulukkomuodossa xmldatasta löytyvät joukkueet ja joukkueiden sarjat
ensisijaisesti sarjan nimen mukaan aakkostettuna ja toissijaisesti joukkueen nimen mukaan
aakkostettuna.
Isoilla ja pienillä kirjaimilla tai nimien alussa ja lopussa olevilla
ylimääräisillä välilyönneillä ei ole merkitystä joukkueita
järjestettäessä.
Taulukon on vastattava seuraavaa rakennetta:
<table> <caption>Tulokset</caption> <tr> <th>Sarja</th> <th>Joukkue</th> </tr> <tr> <td>2h</td> <td>Joukkue 2</td> </tr> <tr> <td>2h</td> <td>Joukkue 5</td> </tr> <tr> <td>4h</td> <td>Joukkue 1</td> </tr> <tr> <td>4h</td> <td>Joukkue 8</td> </tr> <tr> <td>8h</td> <td>Joukkue 3</td> </tr> <tr> <td>8h</td> <td>Joukkue 4</td> </tr> </table>
-
Sijoita sivun loppuun lista kaikkien rastien koodeista nousevassa aakkosjärjestyksessä (caseinsensitive) seuraavassa muodossa:
<ul> <li>31</li> <li>32</li> <li>3A</li> <li>foo</li> ...
- 31
- 32
- 3A
- foo
- ...
- Luo lomake, jolla voi lisätä XML-rakenteeseen uuden rastin.
Lisäämistä varten on pohjassa valmis funktio.
Lomakkeen ulkoasun on oltava sama kuin seuraavassa kuvassa:
- Lisättävän rastin on oltava XML-rakenteeltaan vastaava
DOM-elementti, kuin jo xmldatassa olemassa olevat rastit. Luo rasti xmldata.createElement-metodilla ja aseta rastin
muut tiedot muilla DOM-rajapinnan metodeilla.
Koodi voi olla mitä tahansa, mutta kuitenkin vähintään yhden merkin. Koodi ei voi olla pelkkää whitespacea. lat ja lon saavat olla vain liukulukuja. Käytä tarkistamiseen Number()-funktiota. Kelvollinen luku olisi esim. 10, 10.0, 10.1233, mutta 10foobar ei saa kelvata eikä myöskään tyhjä merkkijono.<rasti tunniste="..." koodi="..." lat="..." lon="..."/>
- Koodin täytyy olla uniikki eli kahdella rastilla ei saa olla samaa koodia
- Jos kaikkia tietoja (koodi, lat ja lon) ei ole täytetty, niin lisäystä ei tehdä.
- Rastille täytyy keksiä myös uniikki numeerinen tunniste seuraavalla tavalla: Käy läpi kaikki rastit, etsi suurin tunniste ja lisää tähän yksi (1).
- Muista luoda uusi rasti xmldata.createElement-metodilla. Älä vahingossa käytä document.createElement. Rasti on luotava oikeaan dokumenttiin.
- Rastilisäyslomake täytyy tyhjentää lisäämisen jälkeen
- Lomakekenttien label-elementtejä on osattava käyttää oikealla tavalla
- Lisäämisen jälkeen täytyy sivun lopussa oleva rastilistaus päivittää. Lisätyn rastin täytyy löytyä listauksesta oikeasta kohdasta. Vinkki: poista koko vanha rastilistaus ja luo uusi listaus tilalle aina uuden rastin lisäämisen jälkeen.
- Lisättävän rastin on oltava XML-rakenteeltaan vastaava
DOM-elementti, kuin jo xmldatassa olemassa olevat rastit. Luo rasti xmldata.createElement-metodilla ja aseta rastin
muut tiedot muilla DOM-rajapinnan metodeilla.
Taso 3
Laajenna Taso 1 -ohjelmaa seuraavilla ominaisuuksilla ja muutoksilla:
- Varmista, että käsittelet HTML-dokumentissa ykköstason rastilisäyslomaketta ja sen kenttiä suoraan document.forms-rajapinnan kautta. Kts. Lomakkeiden DOM-rajapinta. Koodistasi on siis käytävä ilmi, että osaat kunnolla käyttää kyseistä rajapintaa. Älä siis käytä HTML-dokumentissa lomakekenttien (input-elementit) etsimiseen ja käsittelyyn getElementsByTagName, querySelector, querySelectorAll tai getElementById, ellei tähän ole erityisen hyvää syytä. Perustele mahdollinen syy koodin kommenteisssa. Käytä:
- Laajenna tuloslistausta joukkueen jäsenten nimillä. Ulkoasun on vastattava mallikuvaa.
-
Lisää sivulle lomake, jolla voi lisätä uuden joukkueen tai muokata
jo olemassa olevan joukkueen tietoja. Lomakkeen ulkoasun on vastattava mallikuvaa.
- Joukkueelta kysytään nimi, sarja ja lista jäsenistä.
- Jäseniä voi syöttää n kappaletta.
- Jäseniä on aina syötettävä vähintään kaksi kappaletta eli alussa on oltava kentät kahden jäsenen nimille. Uusia syöttökenttiä luodaan tarpeen mukaan. Käytä input-tapahtumaa. Muiden tapahtumien avulla kikkailtu toteutus ei kelpaa.
- Syöttökenttiä pitää muokatessa olla aina oikea määrä eli yksi tyhjä. Mahdolliset ylimääräiset tyhjät kentät pitää poistaa automaattisesti. Kts. malli.
- Jäseniä voi poistaa klikkaamalla jäsenen nimen vieressä olevaa ruksia (x-kirjain). Pakollisia kahta ensimmäistä jäsentä ei voi poistaa.
- Joukkueessa ei saa olla kahta samannimistä jäsentä
- Joukkueen sarja kysytään radiopainikkeita käyttäen.
- Tarjolla olevien sarjojen täytyy olla samat joita XML-rakenteesta löytyy
- Sarjat täytyy esittää lomakkeella aakkosjärjestyksessä
- Sarjat muuttuvat satunnaisesti eli tämä osa lomakkeesta on luotava dynaamisesti aina xmldatan sisällön perusteella mukaan
- Ensimmäinen sarja täytyy olla lomakkeella oletuksena valittuna
- radiopainikkeen valuena on käytettävä sarjan id:tä
- Jos kaikkia pyydettyjä tietoja (joukkueen nimi, sarja ja väh. kaksi jäsentä ) ei ole syötetty, niin lisäystä ei tehdä.
- Tyhjiä tai pelkkää whitespace sisältäviä jäsenkenttiä ei huomioida
- Joukkueelle on lisättävä myös muut XML-rakenteessa esiintyvät tiedot:
- leimaustapa, joka on kaikilla lisätyillä joukkueilla GPS. Varmista, että käytät oikeaa tallennustapaa eli leimaustapojen indeksejä
<leimaustavat> <leimaustapa>1</leimaustapa> <leimaustavat>
- aika, joka on kaikilla "00:00:00"
- matka, joka on kaikilla 0
- pisteet, joka on kaikilla 0
- Uniikki jid, joka toimii kunkin joukkueen tunnisteena
- leimaustapa, joka on kaikilla lisätyillä joukkueilla GPS. Varmista, että käytät oikeaa tallennustapaa eli leimaustapojen indeksejä
- Uusi joukkue lisätään valmiilla asynkronisella funktiolla, joka ottaa parametrinaan oikeaa muotoa olevan joukkue-elementin. Tarkista muoto xmldatasta. Parantele lisäysfunktiota tarpeen mukaan. Joukkueen lisäämisessä ei poikkeuksellisesti ole palvelimella tarkistuksia, joten ole erityisen tarkkana, että lisäät oikeanlaista sisältöä. Tarvittaessa resetoi xml-data.
- Onnistuneen lisäämisen tai muokkaamisen jälkeen lomakkeen kenttien sisältö tyhjennetään.
- Näkyvissä saa olla joko vain Lisää joukkue -painike tai Tallenna muutokset -painike. Ei molempia. Toteuta käyttäen kahta eri painiketta. Älä muuta painikkeen tekstiä tilanteen mukaan vaan piilota aina se painike, jota ei käytetä.
- Uuden joukkueen on ilmestyttävä myös sivulla näkyvään joukkuelistaukseen oikealle paikalle. Päivitä listaus joukkueen onnistuneen lisäämisen jälkeen.
- Joukkueiden tietojen muokkaaminen
- Tuloslistauksessa näkyvistä joukkueiden nimistä tehdään linkkejä (käytä a-elementtiä), jotka vievät joukkuelomakkeeseen (esim. #lomake).
- Lomakkeeseen tulevat muokattavaksi klikatun joukkueen tiedot. Kts. mallikuva. Muita kuin mallikuvassa olevia tietoja ei tarvitse kyetä muokkaamaan. Oikea sarja täytyy olla valittuna.
- Muutokset tallennetaan Tallenna muutokset -painikkeella.
- Muokkaamisen jälkeen tuloslistaukseen päivitetään joukkueen tiedot. Tarvittaessa listaus on järjestettävä uudelleen.
- Jäseniä voi poistaa tyhjäämällä jäsenkentän tai klikkaamalla ruksia jäsenkentän vieressä.
- Tyhjennä lomake muokkauksen tallentamisen jälkeen. Sivu ei saa latautua uudelleen tallentamisen yhteydessä
- Joukkueen tietojen päivittämistä sivulle on tehtävä tarvittaessa joukkueen tunnisteen (jid) perusteella. Pidä muistissa viite muokattavana olevaan joukkueobjektiin. Voit keksiä uuden attribuutin esim. lomakeobjektiin. Muokkaamisen on toimittava järkevästi vaikka lisäisit useita samannimisiä joukkueita.
Taso 5
Toteuta taso 3:n mukainen Javascript-ohjelma seuraavilla laajennuksilla:
- Lisää leimaustavat aakkosjärjestyksessä näkyviin kunkin joukkueen kohdalle joukkuelistaukseen:
Dynamic Duo ( GPS, Lomake, NFC )
- Lisää joukkuelomakkeeseen myös leimaustavan kysyminen / muokkaaminen.
- Lomakkeella käytettävissä olevat leimaustavat täytyy etsiä xmldatasta
- Leimaustapoja pitää kyetä valitsemaan yksi tai useampi
- Leimaustapoja on valittava vähintään yksi
- Käytä valintaruutuja (checkbox)
- Leimaustavat on esitettävä lomakkeella aakkosjärjestyksessä
- Lisää joukkuelomakkeelle myös joukkueen rastileimausten muokkaus, lisääminen ja poistaminen. Esitä lomakkeella kaikki muokattavaksi valitun joukkueen rastileimaukset tavalla, jossa niitä voi muokata, poistaa tai lisätä uusia leimauksia. Voit toteutustavan keksiä muuten itse, mutta leimattava rasti täytyy valita alasvetovalikosta (select- ja option-elementit) ja xmldatasta löytyvästä rastivalikoimasta. Rastit on esitettävä alasvetovalikossa rastikoodin mukaan aakkosjärjestyksessä. Varmista, että tietojen päivittyminen toimii asynkronisilla funktiokutsuilla järkevässä järjestyksessä ja tiedot pysyvät oikeina sekä palvelimella että selaimessa.
Käyttäjien kommentit