JWT 2017 luento 10 to 20.4.2016 klo 12-14 Aulikki Hyrskykari PinniB 1096 1
Viime luennolla o Funktiot JavaScriptissä, callback, IIFE, sulkeumat ja Module pattern Tänään o AJAX (Asynchronous JavaScript and XML) o JSON (JavaScript Object Notation) o APIt rajapinnoista yleisesti o Google Maps JavaScript API key peruskartan tuominen sivulle markkereiden lisääminen laaja kokoelma muita toimintoja 2
AJAX ja JSON o Ennen web-sovellusohjelmat (palvelimella) keskustelivat selaimen kanssa staattisten sivujen välityksellä, vanha malli: HTTP request CSS HTML HTTP response Client Server Database 3
Asynkroninen toiminta o Ongelma sivunpäivityspyyntö palvelimelle tuo koko sivun sivulle tarvittava uusi tieto mahdollisesti vain pieni osa sivulla selain jähmettyy odottaessaan että uuden sivun tiedot saadaan muodostetuksi ja tuoduksi selaimeen odotanko lieden vieressä, että vesi kattilassa alkaa kiehua? EN. Haluan tehdä jotain muuta sillä aikaa o Ratkaisu haluan olla asynkroninen! 4
AJAX (Asynchronous JavaScript and XML) o Ajax on joukko tekniikoita: HTML, DOM, JSON/XML, XMLHttpRequest, callback mahdollistaa vuorovaikutteisemmat web-sovellukset selainohjelma voi noutaa pieniä tietomääriä palvelimelta vain sivun osaan lataamatta koko verkkosivua uudelleen vastauksen odottelu ei lopeta sivun muuta toimintaa asiakaskone selain (client) Palvelin (server) 5
Tiedon välittäminen AJAXia käyttäen o Lähetetään pyyntö tiedon noutamiseksi palvelimelta o Tiedon saavuttua puretaan tieto niin että sitä voidaan käyttää o Päivitetään haluttujen elementtien sisällöt käyttäen hyväksi tarvittavia osia saadusta tiedosta DOM-puuta o Noudettava tieto voi olla esimerkiksi käyttäjän tiedonhakupyyntö välittömästi tarvittavaan tietoon esim. hae seuraavat juna-aikataulut ennakointi käyttäjän mahdollisesti tulevaan tiedonhakupyyntöön esim. Google maps ennakoi kartan vierityspyyntöön noutamalla seuraavat alueet jo valmiiksi etukäteen 6
Tiedonvälityksessä käytetyt formaatit o Missä muodossa tieto kulkee palvelimen ja selainkoneen välillä? itse asiassa välitettävä tieto tietysti aina merkkejä, mutta merkkijonojen syntaksi voi olla: HTML-muodossa + helppo näyttää sivulla, ei tarvetta sen kummempaan lisäkäsittelyyn - HTML-koodi tulee tuottaa jo palvelimella valmiiksi - huono siirrettävyys: soveltuu vain selainympäristössä käytettäväksi - tieto välitettävä samalta palvelimelta XML-muodossa + joustava formaatti, hyvä siirrettävyys - runsassanainen formaatti, saattaa vaatia paljon lisäkäsittelyä - tieto välitettävä samalta palvelimelta JSON-muodossa + kompakti formaatti, tietoa voi hakea muiltakin palvelimilta (JSONP) + helppo muunnos JavaScript-olioksi - tarkka formaatti, puuttuva pilkku tai lainausmerkki rikkoo koko tiedon 7
JSON (JavaScript Object Notation) o Tätä käytetään nykyisin valtaosin (siirto merkkijonona) lähes sama formaatti jota käytimme aiemmin literaaliolioiden luomiseksi literaaliolio var kirjaolio = {aihe: "JavaScript", julkaistu: 2011}; // olio sama JSON-muotoisena merkkijonona (huomaa lainausmerkkien käyttö!) var kirjajsstr = "{'aihe': 'JavaScript', 'tekija': 2011}"; // merkkijono o JavaScriptissä valmiit metodit esitysmuotojen välisiin muuntoihin var kirjaolio = JSON.parse(kirjaJSstr); // konvertoidaan JSON-merkkijonosta oliomuuttuja var kirjajsstr = JSON.stringify(kirjaOlio); // konvertoidaan oliosta JSON-merkkijono 8
Datan noutaminen palvelimelta 1. Luodaan tiedon siirrosta huolehtiva olio olio XMLHttpRequest on selaimissa valmiiksi toteutettu olio var xhr = new XMLHttpRequest(); 2. Sidotaan oliolle pyyntöön vastaamista kuunteleva käsittelijäfunktio (kuuntelija) vastauksen käsittelijä sidotaan käyttäen olion onreadystatechange -metodia xhr.onreadystatechange = tiedonkasittelija; 3. Avataan yhteys palvelimelle ja lähetetään pyyntö xhr.open('get', 'polku-tietoon-palvelimella', true); xhr.send(); GET määrittää siirtoyhteyden tyypin (toinen mahdollinen on POST) toinen parametri osoite johon pyyntö kohdistuu (tiedosto palvelimella) boolean-arvo määrittää käsitelläänkö pyyntö asynkronisesti 9
Vastauksen käsittely o XMLHttpRequest-olion oliomuuttuja readystate kertoo missä vaiheessa tiedon haku on, kun tiedon haku on suoritettu sen arvo == 4 xhr.readystate == 0 //uninitialised xhr.readystate == 1 //loading xhr.readystate == 2 //loaded xhr.readystate == 3 //interactive xhr.readystate == 4 //complete oliomuuttujan status kertoo, onnistuiko haku xhr.status ==200 vastauksena kyselyyn saatu tieto (merkkijono) oliomuuttujassa responsetext xhr.reponsetext olioon liitetty onreadystatechange-kuuntelija tarkastaa sekä readystate, että status tilan, ja päättää sen perusteella mitä olion palauttamalla tiedolle tehdään 10
Koodi yhteen koottuna var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { // anonyymi xhr-palautteen // jos tiedon siirto on tehty loppuun if (xhr.readystate == 4) { // jos tiedon siirto onnistui if (xhr.status == 200) { // tähän noudetut tiedot kasittelevä funktio tai sen kutsu } else { // käsitellään virhetilanne, virhekoodi oliomuuttujassa xhr.statustext } } } xhr.open("get", "palvelimelta-noudettavan-tiedoston-url", true); xhr.send(); 11
Esimerkki: Juna-aikataulujen noutaminen palvelimelta o Halutaan hakea aikataulutietoja sivulle päivittämättä koko sivua muu sivu säilyy, noudetaan vain tiedot taulukkoon sivu voisi olla monimutkainen ja noudettu tieto esim. vain yksi junamatka jokin ohjelma tai tietokantakysely muodostaisi json-tiedon palvelimella tällä kurssilla ei palvelinpuolen ohjelmointia, joten json-tieto tallennettu tiedostoksi 12
o Funktio haeuusitieto(), jota kutsutaan, kun sivulla painettaan jotain painikkeista aamu, aamupäivä, iltapäivä, ilta function haeuusitieto(mika) { // haetaan pyydetyt tiedot - normaalisti tiedot tuottaisi jokin ohjelma, tietokantakysely, // tms. mutta nyt esimerkin vuoksi palvelimelle on tallennettu neljä json-tekstitiedostoa: // "data/aikataulu1.json", "data/aikataulu2.json", "data/aikataulu3.json", "data/aikataulu4.json" // ============================================================================================== var url = "data/aikataulu" + mika + ".json"; // luodaan XMLHttpRequest-olio xhr = new XMLHttpRequest(); // ja sidotaan siihen kasittelijaksi funktio, joka käsitteleen haetun tiedon xhr.onreadystatechange = function () { // jos tiedon siirto xhr-olioon suoritettu if (xhr.readystate == 4) { // jos tiedon siirto tapahtui onnistuneesti if (xhr.status == 200) { vietiedottaulukkoon(xhr.responsetext); // noudettu tieto xhr-olion responsetext-oliomuuttujassa } else { kirjoitaviesti("tiedon noutaminen ei onnistu (error code: "+ xhr.statustext + ")"); } } } } xhr.open("get", url, true); // avataan yhteys palvelimelle ja lähetetään xhr.send(); // sinne yllä muodostettu HTTPRequest -olio 13
Esimerkki noudetusta json-tiedostosta o Esimerkki yhdestä (tässä tapauksessa sivulle valmiiksi tallennetusta) JSON-merkkijonosta "data/aikataulu1.json" { "aikataulu": { "paiva": "perjantai", "pvm": "22 hutikuuta 2016", "mista": { "paikka": "Tampere", "koodi": "TRE" }, "minne": { "paikka": "Helsinki", "koodi": "HKI" }, "juna": [ { "lahtee": "04:30", "saapuu": "6.47", "kesto": "2:17", "vaihtoja": "1" },... { "lahtee": "08.07", "saapuu": "09:52", "kesto": "1:45", "vaihtoja": "0" }, { "lahtee": "08.34", "saapuu": "10:47", "kesto": "2:13", "vaihtoja": "1" } ] } } 14
Muunnokset JSON-merkkijono JavaScript-olio o JSON-olio, jolla metodi: JSON.parse(mjono) muuttaa JSON-tekstin JavaScript-olioksi (muunnos toisin päin olisi JSON.stringify(olio)) function tuotiedottaulukkoon() { // xhr-olion responsetext-kentassa palvelimelta noudettu JSON-muotoinen merkkijono noudettutieto = JSON.parse(xhr.responseText); } // nyt JSON-muotoisena tekstinä saadusta tiedosta on muodostettu // JavaScript-olio noudettutieto, jota ohjelmassa voi käyttää kuten mitä tahansa oliota // oliosta löytyy esimerkiksi taulukko: aikataulu.juna // jokaisessa taulukon alkiossa aikataulu.juna[i] on yhden junavuoruon aikataulut... 54 15
API Application Programming Interface o UI vs. API user interface rajapinta käyttäjän ja ohjelman välissä application programming interface rajapinta ohjelmien kesken o Selaimet, skriptikirjastot, palvelut, jne. avaavat toiminnollisuuttaan muiden käytettäväksi rajapintojen kautta, esim. selaimissa DOM on rajapinta jonka kautta skriptit pääsevät muokkaamaan sivun elementtejä HTML5:ssä joukko JavaScript API -rajapintoja, joiden kautta pääsee käsiksi muihinkin selaimen ominaisuuksiin, esim. Drag and Drop, Web Storage, Canvas, Geolocation, ja paljon muita jquery on JavaScript-ohjelma, jolla on API tarjoaa tehokkaampia tapoja sivun elementtien käsittelyyn Facebook, Google, Twitter, jne tarjoavat rajapintoja joiden kautta voi käyttää niihin tallennettua tietoa 16
Google Maps JavaScript API https://developers.google.com/maps/documentation/javascript/ o API Key rajapinnan käyttäminen saattaa edellyttää API key:n luomisen palvelun keino tunnistaa kutsuvaa ohjelmaa Google Maps sallii kevyehkön käytön ilman avaintakin ilman avainta max 2500 kutsua päivässä, kaikki toiminnot eivät saatavilla kannattaako hankkia jos ei aio kaupallistaa sovellusta? etuja: sen avulla saat tietää kuinka paljon sivustoltasi lähetetään API-kutsuja Google ilmoittaa sinulle jos käyttämiisi rajapintoihin tulee muutoksia avaimeen liittyviä ominaisuuksia hallitaan Google-sovelluskehittäjien API-konsolin kautta https://console.developers.google.com/apis/ tätä harjoitustyötä varten et välttämättä tarvitse avainta 17
Rajapinnan kuvaus o Reference-välilehti https://developers.google.com/maps/documentation/javascript/reference#release-version o Kartan lisääminen sivulle luodaan kartta-olio käyttäen rajapinnan Map-konstruktoria kaksi parametria elementtisolmu sivulla, johon kartta tuodaan tyypillisesti div-elementti karttamääreet, joiden avulla määritetään miten kartta piirretään koordinaatit (longitude-latitude), zoomaustaso, karttatyyppi annetaan käyttäen olion literaalinotaatiota 18
Peruskartta o Sivulla esiteltynä elementti, johon kartta tuodaan elementillä tulee olla leveys ja korkeus o Karttamääreet konstruktorin toinen parametri MapOptions-olio olio parametrina konstruktorille, annettava seuraavat ominaisuudet (pakolliset) center: koordinaatti (lat, long), johon kartta keskitetään, esim: center: {lat: 61.4929, lng: 23.778} zoomauskerroin, kerroin 0 antaa koko maapallon, kerroin 20 tarkimman zoomauksen (tällä hetkellä), esim. zoom: 10 muita parametrin ominaisuuksia esimerkiksi maptypeid (ROADMAP, SATELLITE, HYBRID, TERRAIN) löydät ne API-kuvauksesta https://developers.google.com/maps/documentation/javascript/reference#mapoptions 19
Tarvittava koodi <body> <! tähän elementiin tuodaan kartta, sen koko määritellään css:n kautta --> <div id = "kartta"></div> <!-- tuodaan Google maps rajapinta javascript-ohjelmien käyttöön --> <script src= "http://maps.google.com/maps/api/js"></script> <script src = "js/google-map.js"></script> </body> function initmap() { var map = new google.maps.map(document.getelementbyid('kartta'), { center: {lat: 61.5, lng: 23.8}, zoom: 8 }); }... jostain initmap() funktiota tulee kustua - - vaikka näin: (function init(){ initmap() }()) 55 20
Markkereiden lisääminen https://developers.google.com/maps/documentation/javascript/reference#marker o Marker()-konstruktori luo markkerin, ominaisuudet määrää parametrina annettu MarkerOptions -olio function initmap() { var map = new google.maps.map(document.getelementbyid('kartta'), { center: { lat: 61.4929, lng: 23.778}, zoom: 20 }); var nastanpaikka = {lat: 61.4933213, lng: 23.7773083}; } var omamarker = new google.maps.marker({ // parametrina annetaan olio, jossa määritellään position: nastanpaikka, // mihin kohtaan map: mymap, // mihin karttaan title: "JWT luento torstaina 20.4.2017" // mitä markkerissa lukee kun hiiri viedään sen }); // päälle 56 21
Laaja joukko toimintoja o Google Maps APIn dokumentaatio: Samples iso joukko esimerkkejä erilaisista rajapinnan kautta saatavissa olevista toiminnoista, esim. osoitteen saa muutettua koordinaateiksi ja päinvastoin (Geocoder) oman sijainnin näyttäminen (Geolocation) katunäkymän esittäminen (StreetViewPanorama) matkareittien etsintä ja näyttäminen kartalla (DirectionService, DirectioRenderer) erilaisia tapoja piirtää kartalle (esim. InfoWindows) jne. 22