29.4.2014 Aulikki Hyrskykari o Edellinen luento Perustietotyypit Lauseet Oliot Built in oliot o Tällä kertaa: JavaScript Built in oliot ja for in lause HTML ja DOM Funktiot parametrit callback funktiot Tapahtumat ja tapahtumankäsittelijät HTML5 Canvas JavaScript kirjastoista
o Tiedonpaketoija oliot (data wrappers) perustietotyyppisen muuttujan voi määritellä "tiedonpaketoija olioksi jos tarpeen käsitellä muuttujaa oliona, esim. tarvitaan metodeja Object, Number, Boolean, String, Array ja Function o Apuväline oliot Math, Date ja RegExp tuovat mukanaan monia käyttökelpoisiin tietoihin ja toimintoihin o Virheoliot niiden avulla saadaan tietoa avuksi odottamattomista tilanteista selviytymiseen o Object kaikkien olioiden pohja olio o Number, Boolean, String, Array kuhunkin olioon liittyy joukko ominaisuuksia valmiiksi toteutettuja ja metodeja, jotka helpottava olioiden käsittelyä esim. http://www.w3schools.com/jsref/jsref_obj_string.asp
o Date olio ajan käsittelyyn o Math olion kautta saadaan käyttöön matemaattiset funktiot o RegExp oliot ovat säännöllisiä lausekkeita, joiden avulla on mahdollista tehdä hahmontunnistusta (pattern matching) merkkijonoille käsitellä merkkijonoja (etsiä ja korvata tunnistettuja osamerkkijonoja) o Esimerkiksi mjono = "33100 ; var okpostinro = new RegExp("^\d{5$ ); // tai var okpostinro = /^\d{5$/; if (document.lomake.postinro.value.search== 1) // ei ole käypä postinumero alert( Anna oikea postinumero ); o y.o. esimerkin säännössä käytetyt merkit sovitetaan merkkijonoon seuraavasti: ^ sopii merkkijonon alkuun \d sopii mihin tahansa numeromerkkiin {n sopii juuri n lukumäärään edeltävää merkkiä $ sopii merkkijonon loppuun o for...in silmukan avulla käydään läpi olion kaikki ominaisuudet (esimerkki http://www.sis.uta.fi/~jwt/14/esim/05-06-for-in-esimerkki.html) <!DOCTYPE html> <html> <head> <meta charset="utf 8"> <title>for..in esimerkki</title> </head> <body> <h1>opetellaan JavaScriptiä 6</h1> <p> Käydään läpi asiakastiedot ja muodostetaan niistä merkkijono. </p> <p> Tuloksena on: <span id= msg">ei tietoja.</span> </p> <script> var tieto; var str = ""; var asiakas={etunimi:"aarne", sukunimi:"asiakas",ika:30; for (tieto in asiakas) str+=asiakas[tieto]+" "; document.getelementbyid("msg").innerhtml = str; </body> </html> getelementbyid("tunnus") document olion metodi, noutaa elementin jonka id=="tunnus" innerhtml() DOM solmun ominaisuus, jäsentää merkkijonon ja korvaa solmun sisällön jäsennetyllä sisällöllä. JWT 2014@Aulikki Hyrskykari, SIS, Tampereen yliopisto
o DOM on standardoitu keino päästä käsittelemään ohjelmallisesti HTML dokumentin osiin ja ominaisuuksiin o Se välittää HTML elementit JavaScriptiin olioina olioita (ts. sivun elementtejä) voisiten käsitellä JavaScriptillä voidaan muokata HTML elementtien ominaisuuksia JavaScriptin kautta käyttöön olioille (ts. sivun elementeille) määriteltyjä tapahtumia ja metodeja o Toisin sanoen, DOM standardoi sen, miten HTML dokumentin (www sivun) elementtejä voi ohjelmallisesti muokata, luodajapoistaa <!DOCTYPE html> <html> <head> <title>simple HTML document</title> </head> <body> <h1> Esimerkkisivu </h1> <p id = esittely > Tämä dokumentti sisältää otsikon ja kaksi kappaletta. </p> <p> Tämä on <em>toinen</em> kappale ja tässä on sisältönä paitsi tekstiä ja kuva <a href="http://www.visittampere.fi/">tampereelta</a> <br /> <img src = "img/nasinneula.png" alt="näsinneula" /> </p> </body> </html> o Selain muodostaa sivusta DOM puun joka koostuu solmujen hierarkiasta
document html head body title h1 p p #text #text id #text #text em #text a br img #text href #text src alt o DOM puun solmu olioilla on kolme yhteistä ominaisuutta o nodetype, solmun tyyppi (kokonaisluku 1 12), esim. 1=elementtisolmu, 2=attribuuttisolmu, 3=tekstisolmu, 9=kommenttisolmu ja 10=dokumenttisolmu o nodename, solmun nimi merkkijonona DOM spesifikaatiossa kaikille elementeille annettu vakionimet kapitaalikirjaimin kirjoitettuna, esimerkiksi <p> elementille: nodename == "P" o nodevalue, solmun arvo, esim. tekstisolmujen (nodetype=3) arvo on teksti itse attribuuttisolmun (nodetype=2) arvo on attribuutin arvo elementtisolmun (nodetype=1) arvo on null o Kullakin solmutyypillä muitakin ominaisuuksia ja metodeja
o Elementtisolmun (nodetype=2) style ominaisuuden kautta pääsee käsiksi solmun css piirteisiin var kappale= document.getelementbyid("esittely"); kappale.style.color="red"; o Solmun style ominaisuuden (edelleen olio) ominaisuudet vastaavat CSS piirteitä, mutta nimeämiskäytäntö JavaScript tyyppisesti camelcase, esim. CSS DOM o border color bordercolor o background image backgroundimage o color color ks. esim. http://www.w3schools.com/jsref/dom_obj_style.asp esimerkki: http://www.sis.uta.fi/~jwt/14/esim/06-01-html-dom.html o Aiemmin oli esillä getelementbyid(tunnus), jolla noudettiin sivulta elementti, jolla oli määrätty tunnus o Toinen tapa on käyttää html elementtinimeä (nodename) getelementsbytagname ( nodename") o Funktio palauttaa listan solmu olioita palautetun listan oliotyyppi on HTMLCollection viittaus listan yksittäisiin solmuihin indeksoinnilla [0], [1], var kappaleet = document.getelementsbytagname("p"); kappaleet[0].textcontent = "Ensimmäisen kappaleen uusi teksti"; kappaleet[1].textcontent = "Muutetaan toinen kappale"; o Listan pituus (solmujen lukumäärä)? tallennettu solmulistan ominaisuuteen length solmulistan solmut ensimmäinen ja viimeinen alkio solmut[0] solmut[elem.length 1] http://www.sis.uta.fi/~jwt/14/esim/06-02-html-dom-getelementsbytagname.html
kappale.nextelementsibling.childnodes[1] o Kun on olemassa viittaus johonkin DOM puun elementeistä, pääsee sen kautta kiinni mihin tahansa sivun muista elementeistä. o Kaikilla solmuilla on seuraavat ominaisuudet: childnodes, lapsisolmujen lista firstchild, ensimmäinen solmu lapsisolmujen listassa =childnodes(element)[0] lastchild, viimeinen solmu lapsisolmujen listassa =childnodes(element)[listanpituus 1] nextsibling, seuraava sisarussolmu nextelementsibling, seuraava sisarus, jonka nodetype==1 previoussibling (previouselementsibling), edellinen sisarussolmu parentnode, solmun äiti var solmu = document.getelementbyid("esittely"); alert(solmu.nextelementsibling.firstchild.nodevalue); o Tuottaisi valintaikkunaan tekstin: "Tämä on" (ed. esimerkin Tampere sivulla) o Funktion kutsu funktioon voidaan viedä kutsukohdasta arvoja parametrien avulla parametrit annetaan sulkeissa, sulkeet kirjoitetaan, vaikka parametreja ei olisikaan <!DOCTYPE html> <html> <head> <meta charset="utf 8"> <title>asiakastietojen käsittely</title> <script type="text/javascript"> function Asiakas(p1, p2, p3) { this.etunimi = p1; this.sukunimi = p2; this.ika = p3; function muodostaasiakastiedot(tamaasiakas) { var tieto; var asiakastiedot = ""; for (tieto in tamaasiakas) asiakastiedot = asiakastiedot + tamaasiakas[tieto] + " "; return asiakastiedot; </head> <body> <h1>opetellaan JavaScriptiä 7 </h1> <p> Käydään läpi asiakkaan tiedot ja muodostetaan niistä merkkijono. </p> <p> Tuloksena on: <span id= msg">ei tietoja.</span> </p> <script type="text/javascript"> var asiakas1 = new Asiakas("Kalle", "Kuluttaja", 28); var str1 = muodostaasiakastiedot(asiakas1); document.getelementbyid("msg").innerhtml=str1; </body> </html>
o Funktiossa esitelty muuttuja on paikallinen funktiolle var a=1; var b=2; var c=3; function f1() { var a=11; b=22; function f2(){ var b=222; c=333; alert("f2 a,b,c: "+a+", "+b+", "+c); f2(); alert("f1 a,b,c: "+a+", "+b+", "+c); f1(); alert("globaali a,b,c: "+a+", "+b+", "+c); o Lohkossa esitellyt muuttujat näkyvät sisemmille hierarkiatasoille (funktioihin) o Jos muuttujaa ei ole esitelty lainkaan, siitä tulee automaattisesti globaali JWT 2014@Aulikki Hyrskykari, SIS, Tampereen yliopisto var luku, tulos; //globaaleja muuttujia function square(n) { var b = n * n; // b, n lokaaleja muuttujia return b; // palauta n * n; luku = 6; tulos = 2*square(luku); n funktion muodollinen parametri luku funktiolle välitetty, todellinen parametri Funktio palauttaa aina arvon Jos return lausetta ei ole käytetty, palautettu arvo on undefined
o Funktion palauttamaa arvoa voi käyttää lausekkeessa function iseven(n) { return (n%2 ==0); // palauttaa boolean arvon var arvo = 6; if (iseven(val)) { // tee jotain o Jos if lauseen ehtolausekkeen arvo on määrittelemätön, tulkki lähettää virheen (throws an error) o try catch lauseella voidaan ottaa virhe kiinni ja määritellä itse miten se käsitellään o Funktiolle välitettyjen parametrien lukumäärä ja tyyppi voi vaihdella eri kutsukerroilla o Paikallinen muuttuja (taulukko) "arguments automaattisesti käytettävissä kaikissa funktioissa o Parametreihin pääsee käsiksi sekä muodollisten parametrien, että arguments taulukon kautta add(1, 2, 3); // palauttaisi 6 add(1, 2, 3, 4, 5); // palauttaisi 19 o Miten näin toimiva funktio toteutettaisiin? function add () { var s = 0; for (var i = 0; i < arguments.length; i++) s += arguments[i]; return s; add(1, 2, 3, 4, 5); // palauttaisi 15 add(1, 2, "3", 4, 5); // entä tämä?
o Funktio voi palauttaa eri tyyppisiä arvoja eri kutsukerroilla function teejotain (p1) { if (typeof(p1) == "number") return 0; // palauttaa luvun else if (typeof(p1) == "string") return nolla"; // palauttaa merkkijonon teejotain(1); // palautuu 0 teejotain("abc"); // palautuu "nolla" teejotain(); // palautuu undefined o Voidaan luoda funktio ja antaa se arvoksi muuttujalle var tieto, vastaus; tieto = function (a,b) { return a + b; var tieto2 = tieto; vastaus = tieto2(10,2);
o Koska funktio on vain tietoa, se voidaan välittää toiselle funktiolle parametrina function summaa(a,b){ return a() + b(); function yy(){ return 1; function kaa(){ return 2; answer = summaa(yy, kaa); o Kun funktio fa välitetään toiselle funktiolle fb parametrina, ja fb suoritta funktion fa, kutsutaan fa:ta callback funktioksi o Sen avulla voi käyttää toisten kirjoittamia funktioita, jotka toteuttavat heidän määrittelemänsä toiminnan o Tätä käytetään tapahtumankäsittelijöiden toteutuksessa
o Edellä skriptipalat suoritettu dokumentin latautuessa selaimeen, ts. ne oli kirjoitettu sivulle ns. inline skripteinä o Tyypillisempi tapa tapahtumat ja tapahtumankäsittelijät (events, event handlers) toisin sanoen tietty tapahtuma saa aikaan siihen liitetyn skriptin suorituksen - esim. sivun latautuminen, hiiren napsaututus tai kaksoisnapsautus, lomakkeen lähettäminen, näppäimen painaminen jne. o Tapahtumankäsittelijä koodipala (yleensä funktio) jonka tapahtuma laukaisee o Tapahtumankäsittelijä voidaan määritellä HTML elementin attribuutiksi o Attribuutin nimi on tyyppillisesti muodoltaan "onxxx" jossa XXX on tapahtuman nimi esimerkiksi <img href="kuvan osoite" onclick="kasittelyfunktio(parametrit)">
event attribuutti attribuuttiin liitetyn funktion kutsun saa aikaan onchange tekstikentän, alueen tai pudotusvalikon sisällön muutos onclick napsautus elementin päällä ondblclick kaksoisnapsautus elementin päällä onmousedown hiiren painikkeen painallus elementin päällä onload sivun tai kuvan latauksen valmistuminen onsubmit lomakkeen lähetys onreset lomake palauttaminen alkuarvoonsa onunload dokumentin sulkeminen onresize elementin koon muutos täydellinen lista, ks esim. http://www.w3schools.com/tags/ref_eventattributes.asp <!DOCTYPE HTML> <html> <head> <meta charset="utf 8"> <title>mousedown/up esimerkki</title> </head> <body> <p id="p1" onmousedown="kasittelemdown()" onmouseup="kasittelemup()"> text belonging to paragraph </p> <script> function kasittelemdown(){ document.getelementbyid("p1").style.color="red"; function kasittelemup(){ document.getelementbyid("p1").style.color="green"; </body> </html> esimerkki: http://www.sis.uta.fi/~jwt/14/esim/06-04-mousedownupevent.html
o Tapahtuma luo aina event olion olio sisältää tapahtumaan liittyvää tietoa tällaisia ovat mm. seuraavat olion ominaisuudet clientx hiiren x koordinaatti (ikkunassa) clienty hiireny koordinaatti (ikkunassa) offset * hiiren x koordinaatti suhteessa tapahtuman laukaisseen elementin vasempaan reunaan offset * hiiren y koordinaatti suhteessa tapahtuman laukaisseen elementin yläreunaan button liittyykö tapahtumaan hiiren painikkeen (ja minkä niistä 1=vasen, 2=oikea, 3=keski) painallus keycode näppäimistön näppäimen koodi o täydellinen luettelo esim. täällä: https://developer.mozilla.org/en-us/docs/web/api/event#dom_event_subclasses * Puuttuvat Firefoxin event-olio mallista <!DOCTYPE HTML> <html> <head>... </head> <body> <p id= "status">status</p> <div id = "alue" onmousemove = "handlemousemove(event)" ></div> Event olio välitetään funktiolle <script> var statusrivi = document.getelementbyid("status ); function handlemousemove(e) { statusrivi.textcontent = "client(x,y): (" + e.clientx + ", " + e.clienty + ") " + "offset(x,y): ( + e.offsetx + ", " + e.offsety + ")"; </body> </html> esimerkki: http://www.sis.uta.fi/~jwt/14/esim/06-05-event-olion-valittama-tieto-coordxjay.html
<!DOCTYPE HTML> <html> <head>... </head> <body> <p id= status">viesti</p> <p onmousedown="whichbutton(event)"> Tapahtumaan liittyvään tietoa voidaan välittää event oliolla... </p> <script> var viestirivi = document.getelementbyid( status"); function whichbutton(e) { var msg = "button: "; switch (e.button) { case 0: msg += "left"; break; case 1: msg += "middle"; break; case 2: msg += "right"; break; viestirivi.textcontent = msg; Event olio välitetään funktiolle </body> </html> http://www.sis.uta.fi/~jwt/14/esim//06-05-b-event-olion-valittama-tieto-mousedown.html o DOM olioille voi asettaa kuuntelijafunktion (event listener) o Kuuntelijan asetus tapahtuu metodilla addeventlistener() o Metodille voi antaa kaksi parametria tapahtuman nimi (event name) ja kuuntelijafunktio, joka suoritetaan tapahtuman aktivoiduttua object.addeventlistener( tapahtumannimi", callbackfnimi); o Olio huolehtii tapahtuman havaitsemisesta tapahtumaa ei siis liitetä HTML dokumenttiin tapahtumien nimet esim. täältä https://developer.mozilla.org/en-us/docs/web/reference/events o Ohjelmoija (sinä) kirjoitat kuuntelijafunktion (callback) joka suoritetaan, kun tapahtuma aktivoituu o Jos kuuntelijan asetetaan window oliolle, tapahtuma ikkunassa saa aikaan kuuntelijafunktion kutsumisen
keydown ja keyup tapahtumia kuunnellaan koko ikkunassa tuottavat tekstiä sivulle <p> elementin sisällöksi... <body> <p id= status">status</p> script> window.addeventlistener("keydown", reportkeycode); window.addeventlistener("keyup", reportkeyup); function reportkeycode(e) { statusrivi.textcontent += e.keycode + " "; function reportkeyup() { statusrivi.textcontent += "UP "; </body> </html> http://www.sis.uta.fi/~jwt/14/esim/06-06-addeventlistenerforkeycodes.html keydown tapahtumaa kutsutaan niin kauan kun näppäin pohjassa kutsun taajutta ei pääse kontrolloimaan tehdään sama window ikkunan setinterval metodin avulla luodaan tyhjä olio keysdown - keydown listener luo oliolle ominaisuuden, jonka nimi on painetun näppäimen koodi ja keyup listener poistaa ominaisuuden setinterval metodin avulla kutsutaan funktiota update, joka keysdownolion avulla tietää mitä näppäintä on painettu <body> <p id= status">status</p> script> var keysdown = {; window.addeventlistener("keydown", keyflagon); window.addeventlistener("keyup", clearkeyflag); window.setinterval(update,10); </body> </html> function keyflagon(e) { keysdown[e.keycode] = true;; function clearkeyflag(e) { delete keysdown[e.keycode];; function update() { // tätä funktiota kutsutaan 10 ms välein, täällä voidaan toistuvasti // esim. trkastaa mitä näppäimistön näppäimiä on painettu // ja regoida siihen kulloinkin tarkoituksenmukaisella tavalla esimerkki: http://www.sis.uta.fi/~jwt/14/06-07-siirrakuvaanuolinappaimilla.html
key keycode home-näppäin 36 nuoli vasemmalle 37 nuoli ylös 38 nuoli oikealle 39 nuoli alas 40 insert-näppäin 45 delete-näppäin 46 o verkosta löytyy täydellisempiä listoja, esim http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes o document olion metodeja: createelement(elementname) createtextnode(text) appendchild(newchild) removechild(node) o Esimerkki: lisätään listaan uusi alkio: var list = document.getelementbyid("list1") var newitem = document.createelement("li") var newtext = document.createtextnode(text) list.appendchild(newitem) newitem.appendchild(newtext)
Canvas elementti on rajattu alue, taustakangas se voidaan asemoida sivulle haluttuun kohtaan siihen voi tuoda kuvan, tai siihen voi piirtää ohjelmallisesti elementille määritellään konteksti olio (graphics context) - konteksti säilyttää piirtämiseen liittyvät ominaisuudet (esim. kynän sijainti, koko, väri, jne.) <body> <canvas id="mycanvas" width="640" height="480"></canvas> <script> var cv = document.getelementbyid('mycanvas'); var context = cv.getcontext('2d');... o Kutsutaan getcontext() metodia parametrilla 2d o 3d parameteria ei ole, 3 ulotteisia kuvia piirretään webgl:ää käyttäen getcontext( WebGL ) o http://www.w3schools.com/tags/ref_canvas.asp <body> <canvas id="mycanvas" width="640" height="480"></canvas> <script> var cv = document.getelementbyid('mycanvas'); var context = cv.getcontext('2d'); context.linewidth = "3"; context.strokestyle = "green"; context.beginpath(); // aloitetaan uusi piirtoviiva context.moveto(100, 150); // viivan alkukohta context.lineto(450, 50); // viivan loppukohta context.stroke(); // piirretään viiva...
o Canvas elementille annetaan luotaessa koko <canvas id="mycanvas" width="640" height="480"></canvas> o Jos koko jätetään antamatta, oletus on 300 x 150 o Huom: CSS sääntöjen avulla voi muuttaa canvasin kokoa ikkunassa, mutta se ei muuta piirtoalueen dimensioita o Ontto suorakaide ctx.linewidth = 7; ctx.strokestyle = 'black'; ctx.rect(300,300, 30, 30); // x,y,leveys,korkeus ctx.stroke(); o Täytetty suorakaide ctx.fillstyle = "#CC0000"; ctx.fillrect(300,300,30,30); o Kaari (osa ympyrää) ctx.beginpath(); ctx.arc(200,300,40,0,2*math.pi); // x,y, radius, start angle, end angle ctx.fill(); ontto ympyrä: ctx.stroke() 360 o = 2 * PI radians
o Vaikka elementteihin pääsee DOM puun kautta käsiksi, se ei ole aivan ongelmatonta o DOM puuhun tallennetaan muutakin kuin vain esitellyt elementit sivun sisältöä (tekstit, kuvat, jne.) käsittellään eri selaimissa eri tavoin rakentaessaan DOM puuta selaimet tulkitsevat tyhjätilamerkit eri tavoin jotkut selaimet ohittavat ne, toiset tekevät niistä oman DOM solmunsa. o Selainten tulkinta DOM puun rakentamisesta toivottavasti tarkentuu ajan myötä toistaiseksi turvallisen JavaScript koodin kirjoittaminen vaatii aikaa tarkastaa miten pääselaimet joissain erikoistilanteissa rakentavat oman DOM puunsa o Viittaaminen sivun kohteisiin vaikuttaa monimutkaiselta kun otetaan huomioon, että CSS:ään on jo toteutettu selkeät ja yksikäsitteiset valitsimet. o Ratkaisuna näihin ongelmiin: o JavaScript kirjastot jos käytämme Javasciptiä jonkun yleisesti hyvälaatuiseksi todetun javascript kirjaston kautta, nämä perustason ongelmat on niissä valmiiksi ratkaistu o jquery dokumentit: http://jquery.com/ tutoriaali esim: http://www.w3schools.com/jquery/default.asp o Jotta jquery funktioita voi käyttää kirjasto tulee tuoda omaan ohjelmaan (kuten mikä tahansa muukin JavaScript funktiotiedosto) funktiokirjaston kopioida itselleen jqueryn kotisivuilta (http://jquery.com/) mutta kirjaston voi kuitenkin tuoda myös suoraan muutamasta paikasta: http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js http://ajax.microsoft.com/ajax/jquery/jquery 1.4.2.min.js siis esim: <script type="text/javascript src="http://ajax.microsoft.com/ajax/jquery/jquery 1.4.2.min.js">
o jquery on räätälöity helpottamaan HTML elementtien valintaa ja niiden käsittelyä syntaksi: $(selector).action() $ = lyhenne sanalle jquery kertoo, että skripti löytyy jquery kirjastosta (selector) kysely (tai etsi)" HTML elementti action() toiminta, joka näille elementeille suoritetaan o Esimerkki: elementin piilota tämä o Esimerkki: piilota / näytä elementti, jonka id = #panel, silloin kun napsautetaan elementtiä, jonka id = #flip <script> $(document).ready(function(){ $("p").click(function(){ $(this).hide(); ); ); <script> $(document).ready(function(){ $("#flip").click(function(){ $("#panel").slidetoggle("slow"); ); ); slide/toggle: http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_slide_toggle animate: http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_animation