JWT 2016 luento 5 ti 22.3.2016 klo 14-16 Aulikki Hyrskykari PinniB 1096 1
Viime luennolla o JavaScriptin perusteista Tänään o JavaScriptin perusteista muutama poiminta o DOM puun käsittely haun tallentaminen o Yksittäisen elementin haku (Node) getelementbyid, queryselector o Useamman elementin haku (NodeList) getelementsbyclassname, getelementsbytagname, queryselectorall o Solmujen haku puussa liikkumalla parentnode, previoussibling, nextsibling, firstchild, lastchild o Testisolmun sisällön muuttaminen nodevalue o Elementtisolmun tekstisisältö textcontent o HTML-koodia elementin sisällöksi innerhtml o Elementtisolmun lisäys ja poisto createelement(), createtextnode() ja appendchild(), removechild() o Attribuuttien käsittely 2
Dynaamisesti tyypitetty kieli o Muuttujat ovat joko globaaleja tai lokaaleja (funktion sisäisiä) o Muuttujan tyyppi määräytyy dynaamisesti siihen sijoitetun arvon perusteella o Muuttujan voi ottaa käyttöön esittelemättä sitä ensin silloin sen esittely tehdään automaattisesti ja siitä tehdään automaattisesti globaali muuttuja 3
Muuttujien viittausalue o Viittausalue sidottu funktioihin funktiossa esitellyt muuttujat aina paikallisia omassa funktiossaan funktioiden ulkopuolella esitellyt globaaleja muuttujia var a = 5; function TekeeJotain () { var b = 12; // paikallinen muuttuja, olemassa vain funktion sisällä c = 10; // globaali muuttuja, olemassa myös funktion ulkopuolella... } potentiaalinen ongelmakohta: kannattaa esittellä muuttujat aina 4
Muuttujien viittausalue, esim. 1 external = 5; function ekafunktio() { var external = 6; window.alert("eka funktio: " + external); } function tokafunktio() { external = 7; window.alert("toka funktio: " + external); } alert(external); ekafunktio(); alert(external); tokafunktio(); alert(external); Mitä funktiokutsut tulostavat? 5
Muuttujien viittausalue, esim. 2 var summa = 21; function testaa(arvo) { if (arvo) { var summa = 42; } alert(summa); } testaa(true); testaa(false); Mitä funktion kutsut tulostavat? Miksi? 6
DOM Document Object Model (1) Oliomalli HTML-sivun elementeistä (DOM-puu) (2) Ohjelmointirajapinta HTMLdokumenttien rakenteen ja sisällön muokkaukseen 7
DOM Document Object Model o W3C DOM-standardi ei siis ole osa HTML:ää eikä JavaScriptiä kehitys tapahtunut tasoittain DOM Taso 1 (1998) sisältää mm. metodit elementtien luomiseen ja noutamiseen, esim. document.getelementsbytagname( p ) document.getelementsbytagname(*) palauttaa listan sivun kaikista elementeistä DOM Taso 2 (2000) sisältää metodit dokumenttien tyylin muokkaukseen tuki erilaisten tapahtumien (mm. hiiri ja näppäimistö) käsittelylle DOM Taso 3 (2004) laajennuksia tasoon 2 mm. dokumenttien ja elementtien käsittelyssä 8
Esimerkkisivu... <body> </body> </html> <div id="page"> <h1 id="header">kauppalista</h1> <h2>kauppalista</h2> <ul> <li id="one" class="hot"><em>ruodottomia</em> kuhafileitä</li> <li id="two" class="hot">pinaattia</li> <li id="three" class="hot">sitruunalohkoja</li> <li id="four">tilliä</li> </ul> </div> <script src="js/list.js"></script> /* css */....hot { background-color: #f08080; }.cool { background-color: #80eeee; }.normal { background-color: #ffee77; }.complete { background-color: #bbc5c5;... 9
Sivun DOM-puu o Jokaista puun solmua käsitellään JavaScript ohjelmassa oliona, jolla on metodeja ja oliomuuttujia o Jokaista sivun elementtiä, attribuuttia, ja tekstipalaa edustaa solmu DOM-puussa elementtisolmut kuvaavat puun (ja sivun) rakenteen elementtisolmu document on puun juuri (ylimpänä puussa) kaikki haut dokumenttipuuhun tapahtuvat document-solmun kautta attribuuttisolmu ei ole elementtisolmun lapsi on osa elementtisolmua tekstisolmulla ei voi olla lapsia aina puun lehtisolmu 10
document html body div attribute <body> <div id="page"> <h1 id="header">kauppalista</h1> <h2>kauppalista</h2> <ul> <li id="one" class="hot"> <em>ruodottomia</em> kuhafileitä </li> <li id="two" class="hot">pinaattia</li> <li id="three" class="hot">sitruunalohkoja</li> <li id="four">tilliä</li> </ul> </div> <script src="js/list.js"></script> </body> h1 attribute h2 ul script attribute text text li attribute li attribute li attribute li attribute em text text text text text 11
DOM puun käsittely (1) Noudetaan puusta elementti, jota halutaan käsitellä (2) Käytetään/käsitellään sen tekstisisältöä, lapsielementtejä, attribuutteja 12
DOM-puu haun tallentaminen o Kun puusta noudettua elementtiä tarvitaan useammin kuin kerran, se kannattaa tallentaa muuttujaan esim. li var itemnode = getelementbyid('one'); kun elementtiä vastaava solmu puusta on noudettu, sen avulla pääsee käsiksi solmun äitiin, sisaruksiin tai lapsiin o Elementin tallennus muuttujaan tarkoittaa itse asiassa että muuttujaan tallennetaan viittaus ko. solmuun DOM-puussa tehokkaampaa, kun ei jouduta tekemään solmun etsintää uudelleen body div h1 h2 ul script li li li 13
Yksittäisen elementin haku DOM-puusta o Kolme yleistä tapaa hakea elementtipuusta yksi solmu (Node, element-olio) getelementbyid('tunnus') - elementin id-tunnus queryselector('valitsin') - css-valitsin käyttäen hyväksi solmujen sukulaisuussuhteita // haetaan elementti ja tallennetaan se muuttujaan var el = document.getelementbyid("two"); // muutetaan elementin class-attribuutin arvo el.classname = "cool"; // haetaan elementti css-valitsimen avulla var el = document.queryselector('li:lastchild') el.classname = 'cool'; 14
Useamman elementin haku DOM-puusta o Kolme yleistä tapaa useampia solmuja (solmulistan) getelementsbyclassname('luokka') käytetään luokkatunnusta getelementsbytagname('elementti') elementin perusteella queryselectorall('valitsin') kaikki css-valitsimeen sopivat solmut vaikka palauttaisivat vain yhden solmun, palautettava olio on solmulista (=HTMLCollection) HTMLCollection-olioon voidaan viitata kuin Array-olioon sen pituus oliomuuttujassa length elementteihin viittaaminen kuten taulukossa 15
Esimerkkejä o getelementsbyclassname // haetaan kaikki luokkaan hot kuuluvat var elements = document.getelementsbyclassname('hot'); // muutetaan kolmas niistä (jos se on olemassa) if (elements.length > 2) { var el = elements[2]; el.classname = 'cool'; } o getelementsbytagname // haetaan kaikki li-elementtisolmut var els = document.getelementsbytagname('li'); // jos niitä löytyi, muutetaan ensimmäistä if (elements.length > 0) { var el = elements[0]; el.classname = 'cool'; } 16
Esimerkkejä o queryselector, queryselectorall // queryselector palauttaa ensimmäisen löydetyn var el = document.queryselector('li.hot'); el.classname = 'cool'; // queryselectorall palauttaa NodeList-olion, muutos // loydetyistä luokkaan cool kuuluvista toiseen var els = document.queryselectorall('li.hot'); els[1].classname = 'cool'; o NodeLista-olion läpikäynti // haetaan kaikki hot-luokkaan kuuluvat // li-elementtisolmut var hotitems = document.queryselectorall('li.hot'); // muutetaan kaikkien luokka for (var i = 0; i < hotitems.length; i++) { hotitems[i].classname = 'cool'; } 17
Solmujen haku puussa liikkumalla o sukulaissuhteiden avulla parentnode previoussibling, nextsibling firstchild, lastchild // noudetaan aloituskohta ja sen sisarukset var solmu = document.getelementbyid('two'); var edellinen = solmu.previoussibling; var seuraava = solmu.nextsibling; // muutetaan sisarusten class-attribuutit edellinen.classname = 'complete'; seuraava.classname = 'cool'; 18
DOM ja HTML-dokumentin white spaces o HTML dokumentissa peräkkäiset white space -merkit luhistetaan yhdeksi välilyönniksi o DOM-puussa selaimet käsittelevät tyhjätilamerkkejä eri tavoin sukulaissuhteita käytettäessä tähän joutuu kiinnittämään huomiota osa selaimista lisää HTML-dokumentin tyhjätilamerkeistä (välilyönnit, rivinvaihdot) DOM puuhun tekstisolmun solmun elementtityypin voi kysyä: oliomuuttuja nodename NodeName- muuttujan arvot samoja kuin tag-nimet, mutta isoin kirjaimin ( P, UL, DIV, jne.) var solmu = document.getelementbyid('two'); var edellinen = solmu.previoussibling; var seuraava = solmu.nextsibling; // Etsi li-sisarukset (ohita tyhjätilamerkit) while ((edellinen!= null) && (edellinen.nodename!= 'LI')){ edellinen = edellinen.previoussibling; } while ((seuraava!= null) && (seuraava.nodename!= LI')){ seuraava = seuraava.nextsibling; } // jos li-sisarukset löytyivat, muuta niiden luokka if (edellinen!= null) { edellinen.classname = 'complete'; } if (seuraava!= null) { seuraava.classname = 'cool'; } 19
DOM ja HTML-dokumentin white spaces o HTML dokumentissa peräkkäiset white space -merkit luhistetaan HTML dokumentissa yhdeksi välilyönniksi o DOMissa selaimet käsittelevät tyhjätilamerkkejä eri tavoin sukulaissuhteita käytettäessä tähän joutuu kiinnittämään huomiota osa selaimista lisää HTML-dokumentin tyhjätilamerkeistä (välilyönnit, rivinvaihdot) DOM puuhun tekstisolmun solmun elementtityypin voi kysyä (oliomuuttuja nodename) 20
Tekstisolmun sisällön muuttaminen o Tekstisolmun sisältämään tekstiin pääsee käsiksi oliomuuttujalla nodevalue // noudetaan ensin solmu jolla on tekstisisältöä // tekstisolmu on sen solmun lapsi var solmu = document.getelementbyid('two'); var txt = solmu.firstchild.nodevalue; solmu.firstchild.nodevalue = txt + ' 150 gr'; 21
Listan ylimmän rivin teksti? o Kokoilemalla itse solmun eka ensimmäisen lapsenlapsen tekstisisältö + toisen lapsen tekstisisältö ei kovin yleispätevä keino o Oliomuuttuja textcontent sisältää alipuun tekstisisällön (ilman html-merkintöjä) 22
HTML-koodia elementin sisällöksi o innerhtml-ominaisuuden avulla voi elementtiin viedä HTML-koodia sitä voi käyttää mille tahansa elementille potentiaalinen turvallisuusriski (!) sen avulla ei pitäisi tuoda käyttäjältä sisältöä var eka = document.getelementbyid('one'); // hae elementti var msg1 = eka.firstchild.firstchild.nodevalue + eka.firstchild.nextsibling.nodevalue; var msg2 = eka.textcontent; // hae sen textcontent // Kirjoita nämä kappaleiksi listan alle var msg = '<p>elementin \'eka\' tekstit itse keräiltynä: ' + msg1 + '</p>'; msg += '<p>elementin \'eka\' textcontent: ' + msg2 + '</p>'; var el = document.getelementbyid('tulostusalue'); // viedään html-koodipalan kappaleet tulostusalue-elementin sisällöksi el.innerhtml = msg; 23
Solmun tekstisisältö o Sijoittaminen oliomuuttujaan textcontent ylikirjoittaa koko elementin sisällön // noudetaan ensin solmu, ja sitten solmun, sekä // sen alipuun tekstit yhteen koottuna var solmu = document.getelementbyid('one'); var txt = solmu.textcontent; solmu.textcontent = txt + ' 150 gr'; 24
Elementtisolmun lisäys o createelement(), createtextnode() ja appendchild() luodaan ensin uusi elementtisolmu (ja mahdollisesti uusi tekstisolmu, joka viedään lapseksi elementtisolmulle) ja liitetään solmu DOM-puuhun jonkun solmun lapseksi // luodaan uusi elementtisolmu ja tallennetaan se muuttujaan var el = document.createelement('li'); // Luodaan uusi tekstisolmu ja tallennetaan muuttujaan var txt = document.createtextnode('smetanaa'); // Liitetaan tekstisolmu uuden elementin lapseksi el.appendchild(txt); // haetaan äiti, jolle uusi elementti halutaan viedä var aiti = document.getelementsbytagname('ul')[0]; // lisataan uusi elementti puuhun aiti.appendchild(el); 25
Elementtisolmun poisto o removechild() kun elementtisolmu poistetaan DOM-puusta, häviävät myös sen lapset // haetaan poistettava elementtisolmu var el = document.getelementsbytagname('li')[3]; // hae sen aiti var aiti = el.parentnode; // poista elementti aiti.removechild(el); 26
Attribuuttien käsittely o Kun elementtisolmu on noudettu, voi sen attribuutteja käsitellä oliomuuttujien: classname ja id kautta (kuten edellisissä esimerkeissä tehtiin) kysyä attribuutin olemassaoloa metodilla: hasattribute(), ja sen arvoa metodilla getattribute() var el1 =document.getelementbyid('one'); // Noudetaan elementti if (el1.hasattribute('class')) { // jos sillä on luokka var attr = el1.getattribute('class'); // attribuutti, tallenna // attribuutin arvo // lisaa tulostualueelle kappale, jossa kerrotaan luokan nimi var uusiel = document.getelementbyid('tulostusalue'); uusiel.innerhtml = '<p>the first item has a class name: ' + attr + '</p>'; } 27
Attribuutin muuttaminen ja poistaminen o Elementtisolmun attribuutin voi lisätä tai sen arvon muuttaa metodilla setattribute() ja poistaa metodilla removeattribute() yritys poistaa olematonta attribuuttia ei johda virheeseen, mutta silti on hyvä käytäntö tarkistaa onko se olemassa ennen kuin yrittää poistaa sitä // annetaan listan viimeisellekin li-solmuelementille class-attribuutti hot var el = document.queryselector('li:last-child'); el.setattribute('class', 'hot'); // ja poistetaan luokka-attribuutti kokonaan listan ensimmäiseltä el = document.getelementsbytagname('li')[0]; if (el.hasattribute('class')) { el.removeattribute('class'); } // näinkin mahdollista tehdä suoraan document.getelementsbytagname('li')[1].setattribute('class','complete'); 28