xhroot

Custom Object Events in jQuery

Events are a useful tool for directing control flow in javascript.

Consider this familiar line:

1
$('#save').click(saveModel);

#save is the id of a DOM element of some sort, likely a button. If you click on it, saveModel() will execute. This is the same as below:

1
$('#save').bind('click', saveModel);

jQuery’s bind watches #save for click events and fires saveModel when it detects one. We could also force a click event by manually firing it with trigger:

1
$('#save').trigger('click');

Any behavior that would have initiated by actually clicking the button is kicked off by trigger.

Less known is that bind and trigger can also be set on non-DOM objects:

The jungle object keeps a running count of animals it encounters. bind sets up listeners for the main animals in the jungle, ‘monkey’ and ‘bear’ (just go with it). When the document is ready, we fire off 4 events, 2 of which match our listeners, and addAnimal executes accordingly.

Notice that event names are case sensitive, so ‘MONKEY’ did not trigger addAnimal. Typos can be a real head scratcher since the browser doesn’t consider it illegal to be broadcasting ‘MONKEY’ sporadically. Google’s Closure Library assigns common events to constants for this reason, a practice I mimic in my own code. At runtime, if the property is misspelled, the browser should report an error to the console.

trigger links the ‘jungle’ to event.target when it fires so we have a reference to the original object within the addAnimal function.

This example is somewhat contrived. But imagine that we had an application that used server push and Ajax calls, and that we wanted to encapsulate both features into a single class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// constructor
var Data = function() {};

// This is an incoming server push message.
Data.prototype.animalMessage(x) {
  $(this).trigger('NEW-ANIMAL', [x]);
};
// This is an Ajax call.
Data.prototype.getAnimals() {
  $.get('/animals/', $.proxy(this.getAnimalsCallback, this));
};

Data.prototype.getAnimalsCallback(x) {
  $(this).trigger('NEW-ANIMAL', [x]);
};

var zoo = [];

// To use the Data class, create a new instance.
var data = new Data();

// Watch it for 'NEW-ANIMAL' events.
$(data).bind('NEW-ANIMAL', function(event, animal) {
  console.log(animal);
});

data.getAnimals();

All we care about regarding our data instance is if a ‘NEW-ANIMAL’ arrives. We don’t care if it came in through a server push or from an Ajax ‘GET’.

The second parameter in trigger is an array of parameters to pass to any listeners. By default, an event object will be the first parameter passed to bound functions. Subsequent function parameters will be the array parameters in order.

Comments