teaching machines

Taming jQuery

January 15, 2013 by . Filed under aphasia, public.

In our AphasiaWeb project, I’ve run into a few problems that deserve some mention.

jQuery.load and Caching

We have several places in our code where we retrieve content from the server with a jQuery.load() call:

var params = {
  'user_id' : userid,
  'category_id' : curCategoryId
};
$("#parent").load(url, params);

I was finding that after adding posts, new content failed to show up. It appeared that load() wasn’t being called.

A bit of investigation revealed that load() was being called, but jQuery first looks for the response in a cache keyed on the URL and parameters. To prevent these cache hits, one solution is to make sure not to repeat keys. We can’t switch the URL, but we can add a dummy parameter that is guaranteed to be unique for every call—like a clock reading. The server can simply ignore the parameter.

var params = {
  'user_id' : userid,
  'category_id' : curCategoryId,
  'nocache' : (new Date()).getTime()
};
$("#parent").load(url, params);

There are other ways to fix this problem.

Register callbacks on the unborn

Our posts page shows all the posts in a particular category. When we add a new post, the posts page gets a button/link to the new post. However, clicking on the button wasn’t taking me to the new post. That’s because we were registering the click event handler via jQuery.bind, which looks at the current DOM and hooks up the event only to nodes that currently match the selector. In our case, our new button didn’t yet exist when the bind() call executed.

jQuery provides several ways to hook up event handlers to nodes that come along in the future. My solution was to use $(parent).on(event, selector, handler). The parent node retains the parameters so that when future objects get added to it, the parent provides all the information needed to register the callback.

$("#menu").on('click', ".button", function () {
  curPostId = this.name;
  $.mobile.changePage("#post");
});

Returning parseable results

So far, we’ve used PHP scripts to formulate HTML content that the client needs to insert into the DOM. It’s been a simple matter of echoing the pieces out and using $(‘#target’).load to insert the response.

However, our PHP scripts occasionally return compound data that isn’t just inserted into the client pages. For these situations, I’ve been making a JSON structure in PHP:

$json['result'] = somefunc();
$json['path'] = sprintf('%s/images/%s.jpg', $user, $image);
echo json_encode($json);

On the client, I can call the PHP script with jQuery.getJSON, which parses the response using jQuery.parseJSON and yields a JavaScript object:

$.getJSON(url, function (data) {
  console.log(data.result + ' -> ' + data.path);
});