Simpel AJAX met Prototype
Laatste tijd zie je steeds meer Javascript libraries verschijnen, ook AJAX frameworks. In dit artikel zal ik het populaire Javascript library Prototype introduceren, met de nadruk op haar AJAX functionaliteit. Wanneer je veel met het XMLHttpRequest object werkt, zie je vaak dezelfde code terugkomen. Het XHR object aanmaken, server-side script met parameters aanroepen en data uitlezen. Ongetwijfeld zul je al een eigen createXMLHttpRequestObject() functie hebben, maar het leidt tot allemaal losse functies hier en daar, verspreid over verschillende bestanden. Met Prototype kunnen we eleganter code schrijven. In Afhankelijke listboxes met PHP, MySQLi en Prototype gaf Mathieu al een korte introductie tot de AJAX functionaliteit van Prototype, met dit artikel gaan we er dieper op in.
Voordelen Prototype
Het gebruik van Prototype, of een ander goed Javascript library, heeft meerdere voordelen dan handmatig alles scripten. De notaties zijn vaak korter en daarmee kun je veel sneller code schrijven. Geef toe, document.getElementById('divje') is toch veel langer dan $('divje'). Scheelt weer een paar bytes. Een ander groot voordeel is dat je geen zorgen hoeft te maken over cross-browser compatabiliteit, met andere woorden zorgen dat het werkt onder verschillende browsers.
AJAX.Request
Met Prototype kunnen we ook met het XHR object werken. Prototype heeft namelijk een Ajax object, dat weer verschillende classes heeft. Zo heb je Ajax.Request, Ajax.Updater en Ajax.Responders. We zullen beginnen met een simpele call naar een server-side script. Hiervoor heb je Ajax.Request nodig.
-
// <script language="JavaScript" type="text/javascript" src="prototype.js"></script> staat bovenaan
-
<script language="Javascript">
-
var id = 1337; // random id
-
var script = 'mijn_server_side_script.php';
-
var params = 'id=' + id + '&uber=tri';
-
new Ajax.Request
-
(
-
url,
-
{
-
method: 'get',
-
parameters: params,
-
onComplete: mijn_functie
-
}
-
);
-
-
function mijn_functie(request) {
-
-
// inject HTML
-
$('content').innerHTML = request.responseText;
-
}
-
</script>
-
-
<div id="content"></div>
Nu nog onze server-side script:
Wanneer je deze code uitvoert, zie je onmiddelijk de output:
id = 1337 en de uber coder is tri.
Laten we even de code ontleden. Ajax.Request verwacht als eerste parameter de URL naar je server-side script. In dit geval is dat 'mijn_server_side_script.php'. Als tweede argument gebruiken wij een anonymous object. In dit object geven we verschillende parameters door. We beginnen met de request methode, GET of POST, in dit geval willen wij een GET request uitvoeren. Daarna geven we parameters door aan de property 'parameters'. Als laatste geven we aan welke functie wordt geroepen nadat de XHR call succesvol is afgerond. We konden het ook korter schrijven op een regel:
-
new Ajax.Request ( url, { method: 'get', parameters: params, onComplete: mijn_functie } );
Het argument aan je defineerde functie is het XHR object. Dus request in de functie mijn_functie is het XHR object. Hiermee kun je dus responseText of responseXML uitlezen.
Ajax.Request kan meer argumenten aan. Voor meer informatie, hier is een onofficiele documentatie te vinden. Sam Stephenson, ontwikkelaar van Prototype, had blijkbaar geen zin om documentatie te maken maar gelukkig hebben anderen dat wel gedaan.
AJAX.Updater
In ons voorbeeld deden we niet veel met de data die we terugkregen van onze server-side script. Je kunt bijvoorbeeld JSON data uitpakken of andere transformaties uitvoeren. Om nou voor elke XHR call een functie te schrijven die simpelweg alleen wat HTML in innerHTML inject, kunnen we Ajax.Updater gebruiken.
-
new Ajax.Updater('content', url, { method: 'get', parameters: params });
Deze code levert dezelfde functionaliteit als onze eerste voorbeeld, alleen dit keer wordt automatisch de inhoud van de div 'content' automatisch ge-update. Je hoeft alleen als eerste argument aangeven welke id je wilt gebruiken, de rest is hetzelfde behalve dat je dit keer geen onComplete property hoeft aan te geven. Simpel!
Ajax.PeriodicalUpdater
Af en toe heb wil je Ajax.Updater om de periode aanroepen. Dit kunnen we doen met Javascript's ingebouwde timer events, maar gelukkig heeft Prototype dit al ingebouwd, met Ajax.PeriodicalUpdater.
-
new Ajax.PeriodicalUpdater("content", url, { frequency: 1, decay: 2 });
Met de frequency geef je aan om de hoeveel secondes een nieuwe request moet worden gemaakt. Een handig vernufje is de decay property. Het kan zijn dat je vaak dezelfde content ophaalt. Is dat het geval, dan vermenigvuldigt Prototype de frequentie met de waarde van decay totdat er nieuwe content is. Dus bij de tweede request controleert Prototype of de vorige content hetzelfde is. Is dat het geval dan duurt het 1 * 2 = 2 secondes voordat een nieuwe request wordt gemaakt. Is daarna de content weer hetzelfde, dan duurt het 2 * 2 = 4 secondes voordat een nieuwe request wordt gemaakt. Dit gaat dus door totdat er nieuwe content is, dan is de frequentie weer 1. Jaja, handig!
Ajax.Responders
Zoals je misschien al zag, konden we de callback handling defineren in het betreffende AJAX object. We hebben dit gedaan voor onComplete, maar konden het ook doen voor onCreate, onFailure en nog meer. We kunnen dit voor alle functies instellen met Ajax.Responders. Deze code heb ik letter overgenomen van de onofficiele documentatie.
-
<script>
-
var myGlobalHandlers = {
-
onCreate: function(){
-
Element.show('systemWorking');
-
},
-
-
onComplete: function() {
-
if(Ajax.activeRequestCount == 0){
-
Element.hide('systemWorking');
-
}
-
}
-
};
-
-
Ajax.Responders.register(myGlobalHandlers);
-
</script>
-
-
<div id='systemWorking'><img src='spinner.gif'/>Loading...</div>
Bij het maken van de XHR request verschijnt er een activity indicator (zooo web 2.0), iets wat ten sterkste aangeraden zodat de gebruiker weet dat er activiteit is. De onComplete callback wil je waarschijnlijk niet voor elke XHR call gelden, maar bijvoorbeeld onFailure wel.
Ik heb jullie laten zien dat AJAX niet moeilijk en saai hoeft te zijn met Prototype. Voor meer documentatie, hier is een overzicht.
Volg Scriptorama via RSS!
Reageer ook!
Prototype als library en script.aculo.us voor effecten vind ik een mooi framework. Toch heb ik zo mijn bedenkingen als het gaat om de naamgeving van een functie als '$'. Moet een functienaam niet aangeven wat de functie inhoudt?
Door Vincent
op 07.10.06 @ 8:50 am | Permalink
Ik vind in dit geval van niet. Ik zie $() nu eigenlijk als onderdeel van de js syntax, net als $F(). Kan niet meer zonder.
Door Tri Pham
op 07.10.06 @ 9:18 am | Permalink
Het lijkt me dat '$' een gebruikelijk symbool is voor een variable. Niet zo'n gekke associatie. Daarnaast wordt de leesbaarheid van je code er niet minder om vind ik.
Door Michel
op 07.10.06 @ 10:50 am | Permalink
Wellicht nog meer gemak met prototype:
http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
Niet meer wachten op het voltooien van het onLoad event maar zodra de DOM geladen is aan de slag...
(gespot op ajaxian.com)
Door Jeroen Sen
op 07.11.06 @ 10:51 pm | Permalink
Kwijl :D
Ik wist niet dat prototype zo ongelooflijk opties had!!
Maar een ding vraag ik me af, is er eigenlijk een bescherming ingebouwd voor server-delays? Dat als binnen bepaalde tijd niets terug heeft gehad hij stopt of dat je niet perongelijk meerdere verbindingen opent zoals met een search-suggest?
Of moet je hier zelf iets voor maken?
Ik weet nu wel zeker dan in de vergolgende versie van mijn eigen php-framework (RWF) gebruik gaat maken van prototype!
Door Sebastiaan Stok
op 07.15.06 @ 1:31 pm | Permalink
Ja, er zit een timer van 10 sec op. Na deze 10 sec krijg je een exception.
Door Tri Pham
op 07.15.06 @ 1:40 pm | Permalink
Als je een input veld wil vullen met Ajax dan kan je niet Ajax.Updater gebruiken, want deze probeert de innerHTML van het input veld te vullen. Dit werk niet met Firefox (niet getest in IE). Oplossing is dan:
function mijn_functie(request) {
// inject HTML
$('content').value = request.responseText;
}
-- Aad --
Door Aad
op 08.01.06 @ 1:31 pm | Permalink
[...] I found the following code on the internet. By using this code, a spinner is showed automaticly if an Ajax request is running. Very nice! [...]
Door Gamecreatures’ Development Blog » Prototype automatic Spinner op 08.10.07 @ 12:25 pm | Permalink
eeuh in het erste voorbeeldje staat een fout.
var script = 'mijn_server_side_script.php';
moet zijn
var url = 'mijn_server_side_script.php';
Door Fire2Burn
op 11.17.07 @ 4:02 pm | Permalink
Met jQuery werkt 't naar mijn idee ook erg makkelijk - zo niet makkelijker.
Voorbeeldje gemaakt "lijstje sorteren dmv drag 'n drop"
http://harm.glucose-ontwerp.nl/dev/sortlist.php
Feedbaque welkom.
Door Harm
op 12.01.08 @ 11:40 am | Permalink
Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>