Ajax (Asynchronous JavaScript and XML)
- Mitä Ajaxilla voi tehdä
- Ajax-sovelluksen toiminta
- Miten Ajax-ohjelmia tehdään
- XMLHTTPRequest-objekti
- jQuery ja Ajax-operaatiot
- Ajax-esimerkkejä
- Ajax-sovelluksien virheitä ja ongelmia
- Lisätietoa
- Ajax-malli (lähdekoodi (python), javascript-lähdekoodi näkyy suoraan html-tiedostossa)
- Esimerkki (lähdekoodi1, lähdekoodi 2)
- Ajax on lyhenne sanoista Asynchronous Javascript and XML
- Ajax on vain yleisnimitys monen vanhan tekniikan yhteiskäytölle:
- Javascript (Ecmascript)
- XML
- XHTML
- CSS
- XMLHTTPRequest
- DOM
Mitä Ajaxilla voi tehdä
- Ajaxin avulla muutetaan perinteinen WWW-sovelluksen toimintatapa muistuttamaan paremmin tavallisia tietokoneohjelmia.
- Ajax-sovellus muokkaa käyttäjän näkemää WWW-sivua dynaamisesti ilman, että käyttäjän tarvisi navigoida sivulta toiselle.
- Voi teettää www-palvelimella asioita, joita pelkällä Javascriptillä on hankalaa tehdä. Esim. voi kutsua mitä tahansa PHP/Perl/Python tms. skriptiä.
- Voi tarkistaa lomakkeen syötteet heti eikä vasta kun käyttäjä on täyttänyt koko lomakkeen.
- Lomakkeen sisältöä voidaan muuttaa dynaamisesti käyttäjän syötteiden perusteella.
Tunnettuja Ajax-sovelluksia
Ajax-sovelluksen toiminta
Ajax-sovelluksen ja myös aivan tavallisen www-sivun toiminta noudattaa seuraavaa kaavaa:
- Selain pyytää WWW-palvelimelta WWW-sivua:
GET /~tjlahton/sivusto/ HTTP/1.1 Host: users.jyu.fi
Host-otsake määrää mihin palveluun liittyvää sivua pyydetään. Samalla palvelimella voi olla useita eri sivustoja ja eri osoitteita. - WWW-palvelin kertoo millaista tietoa se palauttaa vastauksena:
HTTP/1.1 200 OK ... lukuisia muita HTTP-otsakkeita ... content-type: text/html
- WWW-palvelin lähettää varsinaisen sivun sisällön. Sisältö voi olla staattinen tiedosto tai jonkin sovelluksen (CGI, Flask, jne.) tuottama sisältö. Selain ei tiedä mitään siitä miten sisältö on tuotettu
- Selain tulkitsee sivun HTML-koodin ja pyytää palvelimelta sivuun liittyvät kuvat ja muut tiedostot kuten javascript-tiedostot ja css-tiedostot
- GET /~tjlahton/sivusto/tyylit.css HTTP/1.1
- GET /~tjlahton/sivusto/js/sovellus.js HTTP/1.1
- GET /~tjlahton/sivusto/kuvat/kuva.png HTTP/1.1
- Pyynnöt voivat kohdistua eri palvelimiin
- Selain vastaa pyyntöihin. Ei voida tietää missä järjestyksessä mikäkin sivuun liittyvä tiedosto latautuu. Useita voidaan käsitellä samaan aikaan. Lataukset tapahtuvat asynkronisesti.
- content-type-otsake muuttuu palautettavan sisällön mukaan. content-type-otsakkeessa ilmoitettu mediatyyppi määrittelee
mitä siirrettävä data on ja miten sitä pitää käsitellä. WWW-palvelin hoitaa tämän tavallisten tiedostojen kohdalla mutta jos
kyseessä on oma sovellus niin silloin pitää itse osata ilmoittaa oikea mediatyyppi.
- text/html tavallinen html-dokumentti
- text/plain tekstitiedosto
- text/xml xml-tiedostot
- image/png png-kuva
- text/javascript javascript-tiedostot
- text/css css-tiedostot
- application/json json
- application/xhtml+xml xhtml
- application/octet-stream binääritiedostot joille ei ole omaa tyyppiä. Käytännössä kaikki tiedostot jotka halutaan vain tallennettavan.
- WWW-selain suorittaa sivun sisältöön kirjoitetut tai linkitetyt javascript-sovellukset siinä järjestyksessä kuin ne sivun sisältä löytyvät
- Sivun DOM-puuta manipuloivat javascript-sovellukset voidaan suorittaa vasta kun sivun html-sisältö on kokonaan ladattu: $(document).ready()
- Sivun kuvien ym. osien latautumista joudutaan odottamaan vielä pitempään. Kaiken latauduttua suoritetaan window.onload-tapahtumaan määritelty ohjelma
- Sivuun linkitetty javascript-sovellus voi nyt tehdä lisäpyyntöjä (XHR) WWW-palvelimelle ja ladata esim. lisäsisältöä.
Nämä ovat ns. ajax- eli XHR-pyyntöjä eikä selaimen käyttäjä havaitse näitä kuin erikseen Firebugin tms. työkalun avulla.
- Oletuksena javascript-sovellus voi pyytää lisädataa vain samalta palvelimelta kuin mistä itse sovellus on ladattu
- Ajax-pyyntöjä voi ajatella ohjelmoijan kannalta asynkronisina funktiokutsuina jotka tehdäään verkon ylitse WWW-palvelimella toimivalle sovellukselle
- Asynkroninen pyyntö eli ajax-pyyntö ei pysäytä ohjelman toimintaa pyynnön toteutuksen ajaksi vaan vastaus pyyntöön tulee joskus määrittelemättömän ajan kuluttua. Vastauksen saapuminen riippuu verkon nopeudesta ja siitä miten suurta tietomäärää liikutetaan ja miten kauan www-palvelimella kestää käsitellä pyyntö. Tämä vastaukseen liittyvä viive täytyy osata huomioida sovelluksen toteutuksessa. Pyyntö voi myös epäonnistua, koska verkko ei toimi tai jotain muuta menee pieleen.
- Ajax-pyynnössä voi olla mukana parametreja jotka vaikuttavat siihen mitä vastauksena saadaan. Vrt. funktiokutsu ja kutsun parametrit. Kts. RESt
- Riippuen selaimen käyttäjän toiminnasta voi javascript-sovellus ladata lisää dataa. Esim. karttasovellus lataisi lisää karttaa sen mukaan miten käyttäjä liikuttelee karttaa. Sivun käyttäjä voi tehdä valintoja joiden perusteella ladataan uutta tietoa ja päivitetään lennosta sivun sisältöä. Esim. käyttäjä syöttää postinumeron niin haetaan ajax-kutsulla tätä vastaava postitoimipaikan nimi.
- Sivulla olevat lomakkeet voidaan käsitellä puhtaasti javascriptin avulla ja niiden tiedot voidaan lähettää taustalla www-palvelimelle ja saatu vaste päivittää sivulle ilman, että sivu latautuu selaimessa uudelleen. Vrt. normaali tilanne jossa submit-painikkeen jälkeen lähetetään lomakkeen tiedot www-palvelimelle ja saadaan vastauksena kokonaan uusi sivu.
Miten Ajax-ohjelmia tehdään
- Kirjoitetaan normaali Javascript-sovellus, joka tarvittaessa kutsuu WWW-palvelinta XMLHTTPRequestin avulla.
- XMLHTTPRequest-kutsun toteutuksessa ja toiminnassa voi olla selainkohtaisia eroja. On syytä käytttää kirjastoa, joka piilottaa erot ja myös yksinkertaistaa kutsujen tekemistä. Esim. jQuery.
- XMLHTTPRequest-kutsut voidaan osoittaa vain samalle www-palvelimelle, mistä Javascript-ohjelma haettiin.
- Ohjelman suoritus ei pysähdy XMLHTTPRequest-kutsun suorittamisen ajaksi vaan kutsu suoritetaan asynkronisesti ohjelman taustalla
- XMLHTTPRequest-kutsun vastauksen saavuttua suoritetaan haluttu Javascript-funktio.
XMLHTTPRequest-objekti
XMLHTTPRequest-objektin ominaisuudet kuvataan esim. W3C:n The XMLHttpRequest Object - draft-dokumentissa.
Tärkeimmät metodit:
abort() | Keskeytä menossa oleva pyyntö |
setRequestHeader("nimi", "arvo") | Asettaa pyynnön otsikkotietoja |
getResponseHeader("nimi") | Palauttaa yhden halutun http-otsakkeen arvon |
getAllResponseHeaders() | Palauttaa kaikki pyynnölle palautetut http-otsakkeet |
open("method", "URL"[, async[, "tunnus"[, "salasana"]]]) | Asettaa metodin (POST|GET|HEAD etc.), osoitteen ja mahdollisen käyttäjätunnuksen, salasanan ja tehdäänkö pyyntö asynkronisesti vai ei |
send(data) | Lähettää pyynnön ja mahdollisen datan |
onreadystatechange | Tapahtumankäsittelijä |
readyState | Objektin tila
|
responseText | Palautettu data merkkijonona |
responseXML | Palautettu data DOM-yhteensopivana XML-dokumenttina |
status | HTTP-statuskoodi (kts. luento 5) |
statusText | HTTP-statuskoodin mukana tullut mahdollinen teksti esim. virheilmoitus |
Huomioitavaa
Muutama asia on huomioitava ennenkuin XMLHttpRequest toimii oikein:
GET
GET-metodia käytettäessä parametrit laitetaan open
-metodin url
-parametriin.
Käytä escape
-funktiota tai muuta vastaavaa funktiota ääkkösten yms. korjaamiseksi.
Jos mitään tietoa ei lähetetä ja käytössä on GET-metodi, niin kutsu send(null)
.
POST
POST-metodia käytettäessä send
-metodille annettava data on oltava querystring-muodossa:
nimi=arvo&toinen=arvo&kolomas=jotain
Käytettäessä POST-metodia täytyy mediatyyppi määrätä seuraavalla tavalla:
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
Jos mitään tietoa ei lähetetä ja käytössä on POST-metodi, niin kutsu send("")
.
Vasteen käsittely
Tapahtumankäsittelijässä on tarkistettava readyState
-ominaisuudesta mikä on pyynnön vaihe ja status
-attribuutista mikä on vasteen statuskoodi.
Kun nämä ovat ok, niin data saadaan responseText
tai responseXML
-attribuuteista.
responseXML
Jos vaste halutaan XML:nä, on huomioitava seuraavat asiat:
- palvelimen on palautettava vaste
text/xml
-otsikkotiedoilla muutoin responseXML:ssä ei ole mitään. - Normaali xml-deklaraatio vaaditaan, muista kertoa oikea merkistö (encoding).
- Juurielementtiin on määritettävä nimiavaruus
xmlns="http://www.w3.org/1999/xhtml"
jos XML:n osa halutaan upottaa DOM:n avulla XHTML-dokumenttiin. - Varsinainen juurielementti saadaan
requestolio.responseXML.documentElement
. Tämä pitää liittää dokumenttiin document.importNode-funktiolla ennen upottamista.
XMLHttpRequestien debuggaus
Pyynnöt ja vasteet saa näkyviin esim. Firebugin Network-välilehdeltä.
jQuery ja Ajax-operaatiot
XMLHTTPRequestin käyttäminen kannattaa tehdä jQueryn tarjoaman Ajax-rajapinnan kautta, koska rajapinta on helpompi ja yksinkertaisempi käyttää.
/* yksinkertaisin versio, joka korvaa #lataa-id:llä varustetun elementin sisalto.html-dokumentilla. Huomaa, että sisalto.html ei tarvitse olla staattinen sivu vaan se voi olla mikä tahansa sovellus, joka vain palauttaa html-dokumentin */ $('#lataa').load('sisalto.html'); $.ajax({ async: true, url: "testi.py", data: sisalto, dataType: "xml", error: virhe, processData: true, type: "POST", success: function(data, textStatus, request){ alert("ok" + request.responseText); }} ); function virhe(data, textStatus, request) { /* täällä käsitellään virhetilanne */ }
Ajax-esimerkkejä
Ajax-sovelluksien virheitä ja ongelmia
- Selaimen back-painike ei toimi enää odotetulla tavalla
- Selainhistorian takaisinsaamiseksi on olemassa kikkoja.
- Esim. käytetään eri tiloille erilaista URL:in #ankkuria.
- Kirjanmerkkien tekeminen on ongelmallista
- Toimintojen vasteaika voi olla windows-sovelluksiin tottuneelle liian pitkä.
- Käyttäjälle pitää visuaalisesti vihjata, että nyt täytyy odottaa.
- Esteettömyys - sovelluksen pitää toimia myös ilman javascriptiä
- Ajax-sovellus on myös hankalasti hakurobottien indeksoitavissa.
- Making Ajax Work with Screen Readers
- Accessible Web 2.0 Applications with WAI-ARIA
- Linkit muuttavat sovelluksen tilaa
- Käyttäjä odottaa linkin vievän vain paikasta toiseen.
- Liian paljon Javascript-koodia aiheuttaa selaimen hidastumista.
- Kehitetään uusia käyttöliittymäkikkoja, jotka eivät ole käytettäviä.
- Tietoturva
- Huomaa, että XMLHttpRequest voi kutsua vain sitä palvelinta, josta Javascript-tiedosto on ladattu.
- Ei esim. SQL:ää, salasanoja yms. Javascript-tiedostoihin!
Lisätietoa
Linkkejä javascript-kirjastoihin ja Ajax-artikkeleihin.
- Ajax with jQuery (Flask)
- Mastering Ajax, Part 1: Introduction to Ajax
- Mastering Ajax, Part2
- Dynamic HTML and XML: The XMLHttpRequest Object
- Ajax Matters
- Ajax: A New Approach to Web Applications Artikkeli josta Ajax-hype alkoi
- Ajax (programming)
- Ajaxian
- Ajax Patterns
- SAJAX
- Ajax Mistakes
- XMLHTTPRequest & Ajax Working examples
- Very Dynamic Web Interfaces
- AJAX and Accessibility
- Why Ajax Sucks (Most of the Time)
- Basic AJAX examples
- Ajax Tutoria: Ajax What Is It Good For?
- Introducing JSON
- A Simpler Ajax Path
- Getting Started with Ajax
- Rasmus' 30 second AJAX Tutorial
- Rich Ajax slide shows with DHTML and XML
- AJAX Applications vs Server Load?
- AJAX/DHTML Tutorial: Should I Render My UI On The Server or the Client
- 10 Places You Must Use Ajax
- XMLHTTP
- The XMLHttpRequest Object - W3C Working Draft 05 April 2006
- The SVG Terminal
- Suckerfish HoverLightbox
- Document Object Model (DOM) Level 3 Load and Save Specification
Käyttäjien kommentit