Tutorials
AJAX
AJAX (asynchroon javascript and xml) en een klein beetje Javascript events.
Pagina 1
Introductie/verklaring van het buzz-word
Laten we maar eens beginnen met dit buzz-word van het jaar 2005 uit elkaar plooien:
Als extratje laat ik nog even een klein beetje event-afhandeling zien, om jullie te bevorderen het te gebruiken.
[red]Ik vereis wel dat je weet wat ik bedoel met objecten (bijna gelijk aan die van PHP) en dat je weet dat Java niet Javascript is, en natuurlijk dat Javascript hoofdletter gevoelig is.[/red]
Voorbeelden
Ik heb nog een paar voorbeelden bijgevoegd, die ik zelf heb gebruikt/gemaakt om XMLHTTPRequest te begrijpen. Ze zijn allemaal heel simpel, en niet hier besproken of gedocumenteerd o.i.d. Bij vragen, kan je natuurlijk het forum raadplegen.
http://phphulp.ikhoefgeen.nl/XMLHttpRequest.zip
Alternatieve leeswijze
Deze tutorial is ook verkrijgbaar als PDF op http://phphulp.ikhoefgeen.nl/AJAX.pdf
[red]Af en toe zijn er php-tags gebruikt om de javascript-code op de vrolijken. Denk zo: korte tags betekent javascript, normale, nette en lange tags zijn ook daadwerkelijk PHP. En bij mijn doctype van m'n XML-voorbeeld gaan we de mist even in :-) [/red]
[red]Ik raad aan om vragen over je eigen applicatie te stellen op het forum, en alleen vragen over de tutorial-voorbeelden of algemene XMLHTTPRequest-problemen hier in de comments te plaatsen.[/red]
- [item]Asynchroon: Dit slaat op het niet-synchroon laden van gegevens met het laden van de rest van de pagina. Je kan de gegevens dus achteraf op ieder willekeurig moment opvragen. Dit is ook meteen de kracht van AJAX. Je hoeft dus niet altijd de hele pagina te laden, maar kan nu ook een klein stukje opvragen. Dit is veel sneller en doordat het scherm niet eens hoeft te flikkeren geeft dit veel meer het gevoel van een echte interactieve applicatie.[/item]
[item]Javascript: XMLHTTPRequest, zoals het officieel heet, wordt ook gebruikt in Flash, Java en nog een hele collectie andere programmeer-talen. Maar wij hebben het hier over javascript, dat zo ongeveer door iedere moderne browser (vanaf IE 5.5+ en Mozilla 1.4+) wordt ondersteund. Dit maakt AJAX ook echt het overwegen waard.[/item]
[item]AND (dankje Legolas)[/item]
[item]XML: XMLHTTPRequest was ontworpen voor het inladen van XML-documenten, maar daar is het zeker niet tot gelimiteerd! Ik bespreek hier drie methoden van het formuleren van gegevens.[/item]
Als extratje laat ik nog even een klein beetje event-afhandeling zien, om jullie te bevorderen het te gebruiken.
[red]Ik vereis wel dat je weet wat ik bedoel met objecten (bijna gelijk aan die van PHP) en dat je weet dat Java niet Javascript is, en natuurlijk dat Javascript hoofdletter gevoelig is.[/red]
Voorbeelden
Ik heb nog een paar voorbeelden bijgevoegd, die ik zelf heb gebruikt/gemaakt om XMLHTTPRequest te begrijpen. Ze zijn allemaal heel simpel, en niet hier besproken of gedocumenteerd o.i.d. Bij vragen, kan je natuurlijk het forum raadplegen.
http://phphulp.ikhoefgeen.nl/XMLHttpRequest.zip
Alternatieve leeswijze
Deze tutorial is ook verkrijgbaar als PDF op http://phphulp.ikhoefgeen.nl/AJAX.pdf
[red]Af en toe zijn er php-tags gebruikt om de javascript-code op de vrolijken. Denk zo: korte tags betekent javascript, normale, nette en lange tags zijn ook daadwerkelijk PHP. En bij mijn doctype van m'n XML-voorbeeld gaan we de mist even in :-) [/red]
[red]Ik raad aan om vragen over je eigen applicatie te stellen op het forum, en alleen vragen over de tutorial-voorbeelden of algemene XMLHTTPRequest-problemen hier in de comments te plaatsen.[/red]
Pagina 2
Javascript Events
Ikzelf maak maar al te graag gebruik van events. Dit is een soort alternatief voor de onmouseover en onclick attributen in je tags.
De functie die ik maar al te graag gebruik, ook weer puur om van de ongelijkheden in verschillende browsers af te komen:
Een voorbeeld van gebruik van deze functie:
Stel, we hebben een plaatje met als id ‘afbeelding’ (<img src="" id="afbeelding" alt=""/>). Deze kunnen we vanuit Javascript oproepen via document.getElementById('afbeelding') en dan aan een variabele toewijzen.
[red]Pas op: Je kan pas een element uit de pagina selecteren nadat de pagina helemaal geladen is. Gebruik hiervoor het onload-event. Zelf vind ik dit de meest handige aanpak.[/red]
Nu moeten we dus een even hangen aan dit object. Zie het totaalvoorbeeld, aangezien dat naar mijn mening veel makkelijker uitlegt dan al die code tussen tekst:
De functie die ik maar al te graag gebruik, ook weer puur om van de ongelijkheden in verschillende browsers af te komen:
function addEvent(obj, eventType,fn, useCapture)
{
if (obj.addEventListener) {
obj.addEventListener(eventType, fn, useCapture);
return true;
} else {
if (obj.attachEvent) {
var r = obj.attachEvent("on"+eventType, fn);
return r;
}
}
}
Een voorbeeld van gebruik van deze functie:
Stel, we hebben een plaatje met als id ‘afbeelding’ (<img src="" id="afbeelding" alt=""/>). Deze kunnen we vanuit Javascript oproepen via document.getElementById('afbeelding') en dan aan een variabele toewijzen.
[red]Pas op: Je kan pas een element uit de pagina selecteren nadat de pagina helemaal geladen is. Gebruik hiervoor het onload-event. Zelf vind ik dit de meest handige aanpak.[/red]
- [item]Maak een functie genaamd init() en zet hier alles in wat er moet gebeuren zodra de pagina geladen is (variabelen een waarde geven, andere functies starten bijvoorbeeld)[/item]
[item]Plaats deze regel onderaan in je code: addEvent(window, 'load', init);[/item]
[item]Doe een schietgebedje. Er is een redelijke kans dat je computer kan exploderen.[/item]
Nu moeten we dus een even hangen aan dit object. Zie het totaalvoorbeeld, aangezien dat naar mijn mening veel makkelijker uitlegt dan al die code tussen tekst:
function init()
{
var afbeeldingObject = document.getElementById('afbeelding');
addEvent(afbeeldingObject, 'click', laatLezerSchrikken);
}
function laatLezerSchrikken()
{
alert('Boeh!');
}
addEvent(window, 'load', init);
Pagina 3
Javascript Events (overbodige extra's)
Nog even een klein voorbeeldje van wat je nog meer kan met events. Dit is echt overbodige luxe, maar ik vind toch dat je het moet weten :-)
<?
function init()
{
var inputObject = document.getElementById('invulformulier');
addEvent(inputObject, 'keyup', geefOverbodigeInformatie);
return;
}
function geefOverbodigeInformatie(e)
{
if(e.keyCode == 13)
{
alert('Jij grapjas, jij drukte op enter!');
}
//voor meer keycodes, probeer eens alert(e.keyCode);
return;
}
addEvent(window, 'load', init);
?>
In dit geval is er een element wat je de aandacht kan geen, zoals een formulier-element (<select/> en <input/> bijvoorbeeld) maar ook op window werkt het. Zo kan je dus vrij gemakkelijk de escape-knop afvangen. Experimenteren met de return (false/true/niets) levert weer andere effecten op.
<?
function init()
{
var inputObject = document.getElementById('invulformulier');
addEvent(inputObject, 'keyup', geefOverbodigeInformatie);
return;
}
function geefOverbodigeInformatie(e)
{
if(e.keyCode == 13)
{
alert('Jij grapjas, jij drukte op enter!');
}
//voor meer keycodes, probeer eens alert(e.keyCode);
return;
}
addEvent(window, 'load', init);
?>
In dit geval is er een element wat je de aandacht kan geen, zoals een formulier-element (<select/> en <input/> bijvoorbeeld) maar ook op window werkt het. Zo kan je dus vrij gemakkelijk de escape-knop afvangen. Experimenteren met de return (false/true/niets) levert weer andere effecten op.
Pagina 4
Het XMLHTTPRequest object - het object aanmaken
De implantatie van XMLHTTPRequest verschilt helaas wel per browser. Gelukkig merken we dat eigenlijk alleen in het initialiseren (het aanmaken) van het object. De rest is zo goed als algemeen onder alle implantaties.
Deze functie gebruik ik altijd voor het maken van een object. Hij is eigenlijk heel onlogisch en niet netjes en maakt gebruik van een hoopje bij elkaar gebietste hacks voor zowel IE als Mozilla, maar werkt wel.
<?
function createHTTPHandler(){
var httphandler = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
try {
httphandler = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
httphandler = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
httphandler = false;
}
}
@end @*/
if (!httphandler && typeof XMLHttpRequest!='undefined') {
httphandler = new XMLHttpRequest();
}
return httphandler;
}
?>
Een voorbeeld van het gebruiken van deze functie is overdreven simpel:
<? var XMLHTTPObject = createHTTPHandler(); ?>
En nu hebben we ons XMLHTTPObject in de gelijknamige variabele.
Initialiseren ervan kan het beste pas waneer de pagina geladen is, omdat elementen in je pagina pas beschikbaar zijn waneer de pagina klaar is met laden. Zie mijn event-pagina’s voor een van de vele methoden.
Deze functie gebruik ik altijd voor het maken van een object. Hij is eigenlijk heel onlogisch en niet netjes en maakt gebruik van een hoopje bij elkaar gebietste hacks voor zowel IE als Mozilla, maar werkt wel.
<?
function createHTTPHandler(){
var httphandler = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
try {
httphandler = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
httphandler = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
httphandler = false;
}
}
@end @*/
if (!httphandler && typeof XMLHttpRequest!='undefined') {
httphandler = new XMLHttpRequest();
}
return httphandler;
}
?>
Een voorbeeld van het gebruiken van deze functie is overdreven simpel:
<? var XMLHTTPObject = createHTTPHandler(); ?>
En nu hebben we ons XMLHTTPObject in de gelijknamige variabele.
Initialiseren ervan kan het beste pas waneer de pagina geladen is, omdat elementen in je pagina pas beschikbaar zijn waneer de pagina klaar is met laden. Zie mijn event-pagina’s voor een van de vele methoden.
Pagina 5
Het XMLHTTPRequest object - het object zijn parame
Je hebt nu een leuk object, maar dat object heeft echt geen flauw idee wat het moet doen. Het is er gewoon, als een zombie. Dus kleden we het wat aan.
<?
XMLHTTPObject.open('GET', 'pagina.php?wachtwoord=1234', true);
?>
De eerste parameter (string), in mijn voorbeeld ‘GET’ kan ‘GET’ of ‘POST’ zijn. Ik neem aan dat het verschil wel bekend is. GET geeft zijn parameters via de url mee, POST via de body van de aanvraag.
Mijn tweede parameter, ‘pagina.php’, is de url die aangevraagd moet worden. Hier kan je ook nog standaard GET-parameters aan toevoegen, zoals bekend.
Derde parameter (boonlean) is de keuze of we een synchroon of een asynchroon vraagje willen stellen. Zet je deze op ‘false’, dan zal je pagina bevriezen waneer de aanvraag wordt uitgevoerd. Of dat nou echt is wat we willen...
de open()-functie doet niets anders dan parameters instellen. Er wordt nog geen data verzonden, en is nog niets in gang gezet!
Okee, nu weten we welke pagina we willen hebben, en op wat voor manier. Maar wat moet er gebeuren met het antwoord?
<?
XMLHTTPObject.onreadystatechange=function() {
if (XMLHTTPObject.readyState==4) {
//die iets leuks
}
}
?>
onreadystatechange is een mooi voorbeeld van een andere manier van events gebruiken. Waneer ons object naar een andere fase van de aanvraag springt, moet deze functie worden uitgevoerd. In mijn voorbeeld maak ik gebruik van een naamloze functie, die direct aan het event wordt geplakt. Je kan function(){ ook vervangen door bijvoorbeeld ‘geefOverbodigeInformatie’ uit mijn event(extra)-voorbeeld.
Ik denk dat je via addEvent() (weer uit mijn event-voorbeeld) ook dit event kan uitbuiten, maar dat heb ik nog nooit geprobeerd, en deze methode lijkt mij onderweg ook handiger.
Dan komen we meteen bij mijn if-lus. Deze kijkt in welke fase mijn object dan wel ooit niet bezig is.
Er zijn 4 fasen.
Vanaf fase 3 zou je in principe de binnengetrokken data kunnen gaan gebruiken, maar waarschijnlijk is de afhandeling sneller dan het ophalen, en dan loopt het zootje vast. Niet doen dus, altijd wachten op fase 4.
Houd er rekening mee dat deze functie pas uitgevoerd wordt nadat de aanvraag dus gestart is, en dat is nog steeds niet het geval. Ik ga mijn cliff-hanger niet nu al verraden.
En we hebben data, en wel in het object. En dat gaan we eruit halen, muhaha!
<?
var inhoudDiv = document.getElementById('inhoud');
inhoudDiv.innerHTML = XMLHTTPObject.responseText;
?>
En dan zit er in onze div het antwoord van de aanvraag.
Als alternatief kan je responseXML gebruiken, maar daar kom ik op terug in de pagina’s over alternatieve data-formaten.
We kunnen nog wat meer parameters meesturen, waar we later geen spijt van zullen krijgen:
<?
XMLHTTPObject.setRequestHeader("Cache-Control", "no-cache");
XMLHTTPObject.setRequestHeader("X_USERAGENT", "MijnAjaxApplicatie");
?>
Ik stuur nog een header mee om caching te voorkomen. Als alternatief kan je je url nooit hetzelfde laten worden, door bijvoorbeeld een timestamp als parameter mee te sturen. Ik stuur ook nog een header mee waaraan ik de aanvraag van mijn object straks in mijn script aan terug kan herkennen. Later wordt wel duidelijk waarom ik dat zou willen.
<?
XMLHTTPObject.open('GET', 'pagina.php?wachtwoord=1234', true);
?>
De eerste parameter (string), in mijn voorbeeld ‘GET’ kan ‘GET’ of ‘POST’ zijn. Ik neem aan dat het verschil wel bekend is. GET geeft zijn parameters via de url mee, POST via de body van de aanvraag.
Mijn tweede parameter, ‘pagina.php’, is de url die aangevraagd moet worden. Hier kan je ook nog standaard GET-parameters aan toevoegen, zoals bekend.
Derde parameter (boonlean) is de keuze of we een synchroon of een asynchroon vraagje willen stellen. Zet je deze op ‘false’, dan zal je pagina bevriezen waneer de aanvraag wordt uitgevoerd. Of dat nou echt is wat we willen...
de open()-functie doet niets anders dan parameters instellen. Er wordt nog geen data verzonden, en is nog niets in gang gezet!
Okee, nu weten we welke pagina we willen hebben, en op wat voor manier. Maar wat moet er gebeuren met het antwoord?
<?
XMLHTTPObject.onreadystatechange=function() {
if (XMLHTTPObject.readyState==4) {
//die iets leuks
}
}
?>
onreadystatechange is een mooi voorbeeld van een andere manier van events gebruiken. Waneer ons object naar een andere fase van de aanvraag springt, moet deze functie worden uitgevoerd. In mijn voorbeeld maak ik gebruik van een naamloze functie, die direct aan het event wordt geplakt. Je kan function(){ ook vervangen door bijvoorbeeld ‘geefOverbodigeInformatie’ uit mijn event(extra)-voorbeeld.
Ik denk dat je via addEvent() (weer uit mijn event-voorbeeld) ook dit event kan uitbuiten, maar dat heb ik nog nooit geprobeerd, en deze methode lijkt mij onderweg ook handiger.
Dan komen we meteen bij mijn if-lus. Deze kijkt in welke fase mijn object dan wel ooit niet bezig is.
Er zijn 4 fasen.
- [item]ik doe niks, maar ben er klaar voor[/item]
[item]ik doe de aanvraag[/item]
[item]ik krijg antwoorden binnen[/item]
[item]ik heb alle antwoorden binnen[/item]
Vanaf fase 3 zou je in principe de binnengetrokken data kunnen gaan gebruiken, maar waarschijnlijk is de afhandeling sneller dan het ophalen, en dan loopt het zootje vast. Niet doen dus, altijd wachten op fase 4.
Houd er rekening mee dat deze functie pas uitgevoerd wordt nadat de aanvraag dus gestart is, en dat is nog steeds niet het geval. Ik ga mijn cliff-hanger niet nu al verraden.
En we hebben data, en wel in het object. En dat gaan we eruit halen, muhaha!
<?
var inhoudDiv = document.getElementById('inhoud');
inhoudDiv.innerHTML = XMLHTTPObject.responseText;
?>
En dan zit er in onze div het antwoord van de aanvraag.
Als alternatief kan je responseXML gebruiken, maar daar kom ik op terug in de pagina’s over alternatieve data-formaten.
We kunnen nog wat meer parameters meesturen, waar we later geen spijt van zullen krijgen:
<?
XMLHTTPObject.setRequestHeader("Cache-Control", "no-cache");
XMLHTTPObject.setRequestHeader("X_USERAGENT", "MijnAjaxApplicatie");
?>
Ik stuur nog een header mee om caching te voorkomen. Als alternatief kan je je url nooit hetzelfde laten worden, door bijvoorbeeld een timestamp als parameter mee te sturen. Ik stuur ook nog een header mee waaraan ik de aanvraag van mijn object straks in mijn script aan terug kan herkennen. Later wordt wel duidelijk waarom ik dat zou willen.
Pagina 6
Het XMLHTTPRequest object - de cliff-hanger verkla
<?
XMLHTTPObject.send(null);
?>
Hahaha, dat was het dan. send() zet het allemaal in werking. send() moet altijd een parameter meekrijgen, namelijk de inhoud van de body van de aanvraag. Ik maakte een GET-aanvraag, dus de body blijft leeg. Ik moet toch ‘null’ invullen, anders krijg ik foutmeldingen. In het geval van een POST-aanvraag vul je daar in plaats van ‘null’ je gegevens in, geschreven als parameter=waare¶meter2=waarde. Komt je vast bekend voor. Daarbij moet je in het geval van POST ook nog even 2 standaard headers meesturen (komt je misschien wel bekend voor uit een goed formulier)
<?
XMLHTTPObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
XMLHTTPObject.setRequestHeader('Connection', 'close');
?>
De eeste is om de server te laten weten wat voor data het is, de tweede is voor het oplossen van een bug in Mozilla (anders geeft hij de content-length niet goed mee, en dat wil nog wel eens voor problemen zorgen)
Dankje Steffan voor dat laatste.
XMLHTTPObject.send(null);
?>
Hahaha, dat was het dan. send() zet het allemaal in werking. send() moet altijd een parameter meekrijgen, namelijk de inhoud van de body van de aanvraag. Ik maakte een GET-aanvraag, dus de body blijft leeg. Ik moet toch ‘null’ invullen, anders krijg ik foutmeldingen. In het geval van een POST-aanvraag vul je daar in plaats van ‘null’ je gegevens in, geschreven als parameter=waare¶meter2=waarde. Komt je vast bekend voor. Daarbij moet je in het geval van POST ook nog even 2 standaard headers meesturen (komt je misschien wel bekend voor uit een goed formulier)
<?
XMLHTTPObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
XMLHTTPObject.setRequestHeader('Connection', 'close');
?>
De eeste is om de server te laten weten wat voor data het is, de tweede is voor het oplossen van een bug in Mozilla (anders geeft hij de content-length niet goed mee, en dat wil nog wel eens voor problemen zorgen)
Dankje Steffan voor dat laatste.
Pagina 7
De afhandeling van de vraag
Het voorgaande was het javascript-gebeuren, nu weer terug naar PHP. Ik neem aan dat je PHP wel aardig beheerst, en dat ik hier dus niet iedere stap uit hoef te leggen.
Ik heb een aanvraag gedaan naar pagina.php, met als GET-parameters ‘wachtwoord’. Dat wil ik nu gehashed weer terug sturen naar de cliënt.
<?php echo md5($_GET['wachtwoord']); ?>
Dat is inderdaad aanzienlijk makkelijker dan het aanvragen. Maar ik had ook nog een aparte header mee gestuurd, iets met USERAGENT. Waar was dat dan goed voor? Dat was om de compatibiliteit te verhogen. Zo kan je snel kijken of je te maken hebt met een gebruiker die de pagina via mijn object aanroept, of gewoon met de browser er heen gaat. In dat laatste geval kan je dan complete HTML-uitvoer geven. Voor de AJAX klant stuur je alleen de benodigde informatie terug. De rest heeft hij immers nog. Hoe herken ik mijn object dan nu?
<?php
if(isset($_SERVER['HTTP_X_USERAGENT']) && $_SERVER['HTTP_X_USERAGENT'] == 'MijnAjaxApplicatie')
{
//een ajax-klant
}
else
{
//een saaie browser die een saaie standaard aanroep doet.
}
?>
Ik heb een aanvraag gedaan naar pagina.php, met als GET-parameters ‘wachtwoord’. Dat wil ik nu gehashed weer terug sturen naar de cliënt.
<?php echo md5($_GET['wachtwoord']); ?>
Dat is inderdaad aanzienlijk makkelijker dan het aanvragen. Maar ik had ook nog een aparte header mee gestuurd, iets met USERAGENT. Waar was dat dan goed voor? Dat was om de compatibiliteit te verhogen. Zo kan je snel kijken of je te maken hebt met een gebruiker die de pagina via mijn object aanroept, of gewoon met de browser er heen gaat. In dat laatste geval kan je dan complete HTML-uitvoer geven. Voor de AJAX klant stuur je alleen de benodigde informatie terug. De rest heeft hij immers nog. Hoe herken ik mijn object dan nu?
<?php
if(isset($_SERVER['HTTP_X_USERAGENT']) && $_SERVER['HTTP_X_USERAGENT'] == 'MijnAjaxApplicatie')
{
//een ajax-klant
}
else
{
//een saaie browser die een saaie standaard aanroep doet.
}
?>
Pagina 8
De 4 manieren van het schrijven van data
Bij mijn weten zijn er 4 manieren om gegevens de ‘coderen’. Ik bedoel de manier waarop je het antwoord gaat schrijven. Ik wou ze even kort bespreken:
Beginners raad ik aan om gewoon eerst met HTML aan de gang te gaan, en later platte tekst. Voor open-source projecten en openbare API's is XML onomstotelijk de beste. Ben je bezig met een serieuze applicatie, dan heb je deze tutorial niet nodig, en weet je al lang dat je voor JSON gaat.
Beginners raad ik aan om gewoon eerst met HTML aan de gang te gaan, en later platte tekst. Voor open-source projecten en openbare API's is XML onomstotelijk de beste. Ben je bezig met een serieuze applicatie, dan heb je deze tutorial niet nodig, en weet je al lang dat je voor JSON gaat.
- [item]Als gewone saaie HTML met alles erop er eraan[/item]
[item]Als platte tekst, die gesplitst moet worden[/item]
[item]Als XML[/item]
[item]Als JSON[/item]
Pagina 9
Manier 1: Gewone HTML
Deze heb ik al hierboven in mijn voorgaande voorbeelden gebruikt, omdat deze de makkelijkste methode is.
Maar daarbij ook de smerigste. Je stuurt namelijk allemaal zooi op die de browser ook prima zelf kan: de opmaak. Een antwoord wordt daardoor vele malen groter en minder abstract. Die abstractie is makkelijk bij het maken van meerdere applicaties, of het aanpassen van het uiterlijk. Heb je die abstractie niet, dan moet je dus ook je PHP-bestanden allemaal aanpassen.
Maar daarbij ook de smerigste. Je stuurt namelijk allemaal zooi op die de browser ook prima zelf kan: de opmaak. Een antwoord wordt daardoor vele malen groter en minder abstract. Die abstractie is makkelijk bij het maken van meerdere applicaties, of het aanpassen van het uiterlijk. Heb je die abstractie niet, dan moet je dus ook je PHP-bestanden allemaal aanpassen.
Pagina 10
Manier 2: Platte tekst
Deze manier gebruik ik zelf graag (Tot nu toe) omdat hij bijna net zo simpel is, maar ook abstractie geeft.
<?
Javascript voorbeeld: (mijn antwoord zit in ‘XMLHTTPObject.responseText’)
//de if-lus e.d.
if(XMLHTTPObject.repsonseText != '')
{
var dataAlsString = XMLHTTPObject.repsonseText;
var dataAlsArray = new Array();
dataAlsArray = dataAlsString.split('||');
alert('Titel:'+dataAlsArray[0]+'\n'
+'Auteur:'+dataAlsArray[1]+'\n'
+'Pagina\'s:'+dataAlsArray[2]);
}
?>
Als antwoord had ik opgestuurd: “De Ijzeren Wil||Bas Haring||174”
Het grote nadeel is dat het antwoord zo abstract is, dat je niet weet wat wat is. Misschien was de drukkerij wel ‘De Ijzeren Wil’ genaamd, en heette het boek ‘Bas Haring’. Ik moet mijn applicatie uit het hoofd kennen om de data te kunnen snappen. Dit is niet erg als je systeem alleen voor jezelf is, en je er later nooit meer naar om hoeft te kijken, maar kut waneer dat dus niet het geval is.
Daarbij komt nog eens het probleem bij uitbreiden. Wil je meer data versturen, bijvoorbeeld voor een ander object dat wel gebruik maakt van hetzelfde adres (PHP-bestand), dan moet je de toevoegingen erachter zetten.
<?
Javascript voorbeeld: (mijn antwoord zit in ‘XMLHTTPObject.responseText’)
//de if-lus e.d.
if(XMLHTTPObject.repsonseText != '')
{
var dataAlsString = XMLHTTPObject.repsonseText;
var dataAlsArray = new Array();
dataAlsArray = dataAlsString.split('||');
alert('Titel:'+dataAlsArray[0]+'\n'
+'Auteur:'+dataAlsArray[1]+'\n'
+'Pagina\'s:'+dataAlsArray[2]);
}
?>
Als antwoord had ik opgestuurd: “De Ijzeren Wil||Bas Haring||174”
Het grote nadeel is dat het antwoord zo abstract is, dat je niet weet wat wat is. Misschien was de drukkerij wel ‘De Ijzeren Wil’ genaamd, en heette het boek ‘Bas Haring’. Ik moet mijn applicatie uit het hoofd kennen om de data te kunnen snappen. Dit is niet erg als je systeem alleen voor jezelf is, en je er later nooit meer naar om hoeft te kijken, maar kut waneer dat dus niet het geval is.
Daarbij komt nog eens het probleem bij uitbreiden. Wil je meer data versturen, bijvoorbeeld voor een ander object dat wel gebruik maakt van hetzelfde adres (PHP-bestand), dan moet je de toevoegingen erachter zetten.
Pagina 11
Manier 3: Als XML
Bij XML kan je overal je gegevens uitbreiden, alle kanten op. En al je gegevens in je antwoord zijn mooi gelabeld, dus het is duidelijk voor buitenstaanders, of jezelf over 1 jaar.
Nadeel is de grote hoeveelheid code die je meestuurt (voor iedere waarde moet je 2 maal een sleutel meesturen. Een begin-tag en een eind-tag.) en de nog grotere hoeveelheid code die je nodig hebt om de boel te parsen. Dit gaat bijna hetzelfde als het parsen van de html-pagina.
<?
var antwoord = XMLHTTPObject.responseXML;
var root = antwoord.documentELement;
var boeken = root.getElementsByTagName('boek');
var schrijver = null;
var titel = null;
var paginas = null;
for(i = 0; i < boeken.length; i++)
{
paginas = getNodeValue(boeken.item(i), 'paginas');
schrijver = getNodeValue(boeken.item(i), 'schrijver');
titel = getNodeValue(boeken.item(i), 'titel');
alert('Titel:'+titel+'\n'
+'Auteur:'+schrijver+'\n'
+'Pagina\'s'+paginas);
}
function getNodeValue(obj,tag)//dankje Peter Paul Koch (www.quikrsmode.org)
{
return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
?>
Het antwoord ziet er dan ongeveer zo uit:
<?xml version="1.0" encoding="UTF-8"?>
<boeken>
<boek>
<titel>De Ijzeren Wil</titel>
<schrijver>Bas Haring</schrijver>
<paginas>168</paginas>
</boek>
</boeken>
[red]Let wel op dat waneer je het antwoord met PHP maakt, je de header ‘Content-type: application/xml’ meestuurt, anders wordt het niets, en ziet javascript het gewoon als saaie HTML, en bestaat het reponseXML niet eens.[/red]
Nadeel is de grote hoeveelheid code die je meestuurt (voor iedere waarde moet je 2 maal een sleutel meesturen. Een begin-tag en een eind-tag.) en de nog grotere hoeveelheid code die je nodig hebt om de boel te parsen. Dit gaat bijna hetzelfde als het parsen van de html-pagina.
<?
var antwoord = XMLHTTPObject.responseXML;
var root = antwoord.documentELement;
var boeken = root.getElementsByTagName('boek');
var schrijver = null;
var titel = null;
var paginas = null;
for(i = 0; i < boeken.length; i++)
{
paginas = getNodeValue(boeken.item(i), 'paginas');
schrijver = getNodeValue(boeken.item(i), 'schrijver');
titel = getNodeValue(boeken.item(i), 'titel');
alert('Titel:'+titel+'\n'
+'Auteur:'+schrijver+'\n'
+'Pagina\'s'+paginas);
}
function getNodeValue(obj,tag)//dankje Peter Paul Koch (www.quikrsmode.org)
{
return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
?>
Het antwoord ziet er dan ongeveer zo uit:
<?xml version="1.0" encoding="UTF-8"?>
<boeken>
<boek>
<titel>De Ijzeren Wil</titel>
<schrijver>Bas Haring</schrijver>
<paginas>168</paginas>
</boek>
</boeken>
[red]Let wel op dat waneer je het antwoord met PHP maakt, je de header ‘Content-type: application/xml’ meestuurt, anders wordt het niets, en ziet javascript het gewoon als saaie HTML, en bestaat het reponseXML niet eens.[/red]
Pagina 12
Manier 4: JSON
Jeej, Jason, nog een griek :-)
Bij deze methode gaat het erom dat je het antwoord als javascript-object (arrays en objecten zijn in Javascript heel erg vergelijkbaar) terugstuurt. Het voordeel is dat je het antwoord niet zelf meer hoeft te parsen.
Modernere browsers hebben inmiddels de functies JSON.parse & JSON.stringify om je responseText string om te zetten naar objecten.
Oudere browsers, zoals Firefox voor versie 3.5, en Internet Explorer, hebben die functies nog niet. Maar omdat JSON letterlijk Javascript is, kan je eval** gebruiken om hetzelfde te doen. Eval heeft wel één groot nadeel: het voert je code ook uit, dus ook de functieaanroepen die iemand kwaadwillend erin heeft gewerkt. Voorzichtigheid is dus geboden, al valt het in praktijk wel mee.
Omdat JSON inmiddels veel gebruikt wordt, heeft zo'n beetje iedere Javascript bibliotheken oplossingen voor het veilig parsen ingebouwd. jQuery heeft parseJSON, Prototype komt met evalJSON, Mootools JSON.decode.
Sinds PHP 5.2 heeft PHP zelf ook [php]json_encode[/php] voor het vertalen van je array of object in een JSON. Kant en klaar. Uiteraard heb je dan ook [php]json_decode[/php], welke je in de praktijk eerder zal gebruiken om met webservices zoals Twitter API te praten wanneer je JSON in plaats van XML gebruikt als codering.
Voorbeeldje:
api.php:
<?php
$post = new stdClass();
$post->tags = array('json', 'tutorial', 'javascript');
$post->author = 'Jelmer';
echo json_encode($post);
?>
Javascript:
** Wanneer je eval gebruikt om je JSON string te parsen, moet je even opletten dat je haakjes, ( en ) om de string zet.
Bij deze methode gaat het erom dat je het antwoord als javascript-object (arrays en objecten zijn in Javascript heel erg vergelijkbaar) terugstuurt. Het voordeel is dat je het antwoord niet zelf meer hoeft te parsen.
Modernere browsers hebben inmiddels de functies JSON.parse & JSON.stringify om je responseText string om te zetten naar objecten.
Oudere browsers, zoals Firefox voor versie 3.5, en Internet Explorer, hebben die functies nog niet. Maar omdat JSON letterlijk Javascript is, kan je eval** gebruiken om hetzelfde te doen. Eval heeft wel één groot nadeel: het voert je code ook uit, dus ook de functieaanroepen die iemand kwaadwillend erin heeft gewerkt. Voorzichtigheid is dus geboden, al valt het in praktijk wel mee.
Omdat JSON inmiddels veel gebruikt wordt, heeft zo'n beetje iedere Javascript bibliotheken oplossingen voor het veilig parsen ingebouwd. jQuery heeft parseJSON, Prototype komt met evalJSON, Mootools JSON.decode.
Sinds PHP 5.2 heeft PHP zelf ook [php]json_encode[/php] voor het vertalen van je array of object in een JSON. Kant en klaar. Uiteraard heb je dan ook [php]json_decode[/php], welke je in de praktijk eerder zal gebruiken om met webservices zoals Twitter API te praten wanneer je JSON in plaats van XML gebruikt als codering.
Voorbeeldje:
api.php:
<?php
$post = new stdClass();
$post->tags = array('json', 'tutorial', 'javascript');
$post->author = 'Jelmer';
echo json_encode($post);
?>
Javascript:
function getPost()
{
var request = createHTTPHandler();
request.open('GET', 'api.php', true);
request.onreadystatechange = function() {
if(request.readyState == 4) {
var post = parseGetPostResponse(request.responseText);
// post is nu een eersteklas javascript object
alert(post.author + ': ' + post.tags.join());
}
}
request.send();
}
function parseGetPostResponse(json)
{
// Eerst proberen of de browser JSON veilig kan parsen
if(JSON && JSON.parse)
return JSON.parse(json);
// Zo niet, gebruik dan maar eval.
else
return eval('(' + json + ')');
}
** Wanneer je eval gebruikt om je JSON string te parsen, moet je even opletten dat je haakjes, ( en ) om de string zet.
Reacties
0