Monday, June 11, 2007

Trimming it down to the bare essentials

Tatlin tower - about as practical as one of my ideasOne of the difficulties with getting acceptance for mobile Ajax is that Ajax is synonymous with hefty frameworks in the desktop world. Only last week the entire concept was dismissed out of hand by a colleague with the words "I tried it, but you had to load a 70K library to do it."

There's nothing wrong with frameworks so long as you have a fat pipe and loads of memory to deal with it. I've lost count of the times prototype.js (which is indeed 70K) has saved my life.

But on a mobile device bandwidth and memory are typically scarce, so you'll be wanting to cut back on all the helpful features of things like prototype and stick to the core of Ajax.

The core of the Ajax technique is use of the XMLHttpRequest object. This lets you (as the name suggests) make HTTP requests out of the browser under Javascript control. It's almost as misnamed as AJAX itself: you're not constrained to XML. This opaque naming extends to the method names, as we'll see.

The way this works is as follows:

1. You create a new XMLHttpRequest object (new)

2. Tell it to open a URL somewhere (open)

3. Tell it to go off and fetch the url (send)

4. Wait for it to come back with something


The fourth stage is the trickiest as XMLHttpRequest expects you to find out what it's doing via an event handler called onreadystatechange. This reports four possible states and the one you'll be interested in state 4, which is the state signalled when the request has returned some data.

It's probably easier to explain with some code:

(These examples are from majax.js on my site: http://slackr.eu/m/ You might want to fire this up in a browser to see if it works: I've tested it in Opera 8.65 and S60 Browser, but your mileage may vary)

1. var req;

req is a global for now: as I work towards my own microframework for Ajax I'll encapsulate this properly, but it'll do.
2. var callback;

this is a global for the name of the function that will actually do some stuff on the page. I could just code this into the script below, but I'm trying to be a bit formal.

3. function _statechange() {

4. if (req.readyState == 4) {


5. processResponse(req.responseText);



6. }


7. }


Lines 3 to 7 are the function that reacts when onreadystate changes. I should have included some HTTP error checking, but this is an example...

8. function setCallback(myfunc) {

9. callback = myfunc;


10. }

This is the code I call in the page to register the handler that actually writes to the page

11. function processResponse(t) {
12. callback(t);

13. }

And the above passes control to the page

14. function ajaxRequest(method, url, async) {

15. req = new XMLHttpRequest();


16. req.onreadystatechange = _statechange;


17. req.open(method, url, async);


18. req.send();


19. }


And the above is the meat of the whole thing. It gets three arguments in line 14 - a method which is either "GET" or "POST", a URL to get the data from and a boolean that determines whether the request is asynchronous or not - e.g., whether it blocks any further interaction in the browser while it process. Fragmentation alert: I haven't yet been able to get the S60 browser to respond to synchronous events. That's probably okay, as you're unlikely ever to want to do it.

Line 15 gets us a new XMLHttpRequest and stores it in our global req variable. 16 registers the eventhandler with our function at line 3. Lines 17 and 18 prepare the request and send it.

When the request executes the onreadystatechange event fires once for open, once for sending and then fires when the server begins responding. Only when the server has indicated that it has finished does readystate 4 fire and we can process our response.

The response has a number of properties which I'll look it later but for now the only one we're interested in is req.responseText. Unsurprisingly this contains the response as a string - can't emphasise that enough. You can also extract the response as XML if you fancy some hardcore DOM hacking.

In the actual page, I set the callback that writes to the page to simply put responseText into a div as its innerHTML.

And that's it. The actual Ajax Javascript is 406 bytes.

The example code can been seen at

http://slackr.eu/m/src/majax.js.txt
http://slackr.eu/m/src/fx.js.txt
http://slackr.eu/m/src/ajax.html.txt

No comments: