Ajax
Basisfunksjoner
Koden under er svært enkel og ikke spesielt funksjonell. Vi definerer en global variabel, myRequest, med de farer dette medfører dersom vi har flere asynkrone forespørsler på samme side. Den fungerer for enkle demo-situasjoner, men det er grunn til å vurdere å basere AJAX-løsninger på et litt mer robust grunnlag, se f.eks. modulen jQuery .
var myRequest; function startXMLHttpRequest(url) { myRequest=null; myRequest = new XMLHttpRequest(); if (myRequest) { myRequest.onreadystatechange = processRequest; myRequest.open("GET", url, true); myRequest.send(null); } else{ alert("Nettleseren henger ikke med"); } } function processRequest() { // if the request is complete and successfull if (myRequest.readyState == 4) { if ((myRequest.status == 200) || (myRequest.status == 304)) alert(myRequest.responseText); else alert("Problem med tilgang til data:\n" + myRequest.statusText); } }
Koden over definerer et "globalt" XMLHttpRequest-objekt og to metoder. Den første metoden, startXMLHttpRequest, adresserer en fil via en URL. Merk at denne metoden ikke tar hensyn til gamle, eldre enn versjon 7, versjoner av IE. Dersom vi skulle gjøre det, ville vi kanskje ende opp med noe slikt:
Når vi har fått opprettet objektet ser vi at vi angir hvilken funksjon som skal være eventhandler: "myRequest.onreadystatechange = processRequestChange;". Deretter åpner vi en GET-forespørsel og vi sender den uten tilleggsdata. De aktuelle metodene og egenskapene ved et XMLHttpRequest-objekt er listet nedenfor.
Den andre funksjonen, processRequestChange, er programmert slik at den bare bekymrer seg for tilstanden som tilsier at forespørselene er ferdig behandlet(4). Dersom status på dette tidspunktet er 200 så har alt gått bra og vi kan plukke opp resultatet som text og viser det fram i en alert-boks.
Du kan teste ved å klikke
Fragmentet som sender forespørselen:
<p> Du kan teste ved å klikke <button class="demobutton" onclick="javascript:startXMLHttpRequest('frej1.txt');return false;">her.</button> </p>
En viktig begrensning
JavaScript er underlagt begrensninger i hva vi kan få tak i via koden. Begrensningene administreres av nettleserne. Begrunnelsen er sikkerhet. Når vi lager AJAX-løsninger må de ressursene, filene, vi bruker ligge i samme domene som den HTML-siden som bruker dem. Denne sikkerhetsmekanismen er ganske involvert og det vil føre for langt å forfølge dette her. Kortformen for våre praktiske løsninger er at vi legger alt vi vil bruke på samme server og samme bruker.
I praksis er ikke dette noen alvorlig begrensning. Det normale er vel at vi bygger en løsning med tilgjengelige ressurser innenfor et domene. Det er ikke noe problem å bruke fremmede ressurser, men da gjør vi det via kode på tjeneren, f.eks. et pythonskript, som legges i det lovlige domenet. Webservices kan være eksempler på slike "fremmed" ressurser. Vi kan selvsagt også hente data fra databaser på andre tjenere, typisk en 3-lags løsning.
Noen løsninger
Tekst til DOM-node
Vi har altså, hvis øvelsen ovenfor gikk bra, greidd å få tak i en tekst fra en URL. Når vi nå har tak i den burde vi kunne legge den ut på siden i stedet for å vise den fram i en alert boks. Vi bruker altså DOM-programmering for å plassere den teksten vi henter.
Velge blandt flere
En vanlig situasjon er selvsagt at vi ønsker å tilfredsstille et valg som brukeren treffer. brukeren vil velge blandte flere alternativer. Eksempelet viser hvordan vi kan kople inn en select-boks.
Header informasjon
Vi kan sende en forespørsel som bare returnerer header-informasjon fra en fil. På denne måten kan vi finne ut når en ressurs sist ble oppdatert, mime-typen, servertypen etc. Vi bruker HEAD i stedet for GET eller POST. Vi henter ut getAllResponseHeaders() i stedet for responseText.
Tolke resultatet som XML
Vi kan tolke det svaret vi får på en forespørsel som en DOM-struktur. Det vil si at vi kan hente en XML-fil, analysere denne som et DOM-tre og bruke de delene vi vil til å møblere HTML-siden, som vi betrakter som et annet DOM-tre. Vi plukker da opp responseXML i stedet for responseText.
Bruk av pythonskript på tjeneren
I stedet for å laste ned en fil direkte, kan vi la kode på tjeneren returnere de dataene vi er ute etter, i den form vi vil ha dem. Vi må da tenke gjennom arbeidsdelingen mellom klient og tjener. Eksempelet demonstrerer hvordan vi kan hente 1 av Shakespears sonetter via et Pythonskript på tjeneren.
Skriptet som betjener siden:
Bruk av pythonskript på tjeneren, POST
Samme som ovenfor, men vi bruker POST istedet for GET. Pythonkoden er den samme som over.
Et enkelt "vevsted"
Et enkelt vevsted med 3 sider, eller egentlig en side der hovedinnholdet byttes ut.
GET eller POST
Vi kan hente data med GET eller med POST. POST har den egenskapen at den kan transportere større datamengder. Anta at vi har etablert et XMLHttpRequest-objekt og at vi har gjort klar parameterlista, params.
POST:
... myRequest.open("POST", url,true); myRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); myRequest.setRequestHeader("Content-length", params.length); myRequest.setRequestHeader("Connection", "close"); myRequest.send(params);
GET:
... myRequest.open("GET", url+'?'+params, true); myRequest.send(null);
Metoder og egenskaper
Et XMLHttpRequest-objekt har følgende metoder og egenskaper:
Metoder
- abort()
- Kansellerer pågående forespørsel
- getAllResponseHeaders()
- Returnerer et komplett sett av alle "http headers" som text
- getResponseHeader("headername")
- Returnerer verdien av en "http header"
- open("method","URL",async,"user","password")
- Spesifiserer metoden URL-adressen og tre valgfrie andre parametre i en forespørsel
method kan ha verdiene "GET", "POST", eller "PUT" ("GET" når vi vil hente data og "POST" når vi sender data. Når vi sender mer enn 512 byte må "POST" brukes).
URL parameteren kan være absolutt eller relativ.
async parameteren spesifiserer om forespørselen skal behandles asynkront eller ikke. Dersom den er true betyr det at skriptet kan fortsette uten å vente på svar. - send(content)
- Sender forespørsel. content legger data til en forespørsel som er åpnet med POST
- setRequestHeader("label","value")
- Legger til et par(navn og verdi) til en "http header" som skal sendest
Egenskaper
- onreadystatechange
- Inneholder en funksjon, en event handler, som skal benyttes når tilstanden til XMLHttpRequest-objektet endres.
- readyState
- Returnerer tilstenden til objektet:
- 0 = ikke initialisert
- 1 = lastes
- 2 = lastet
- 3 = interktivt
- 4 = komplett
- responseText
- Returnerer responsen på en forespørsel som en tekst
- responseXML
- Returnerer responsen på en forespørsel som XML. Responsen er i form av et XML dokument som kan parses ved hjelp av DOM-metoder.
- status
- Returnerer status som et tall (f.eks.: 404 for "Not Found" eller 200 for "OK")
- statusText
- Returnerer status som en tekst(f.eks.: "Not Found" eller "OK")