Anyone that's worked with JavaScript in the browser knows that it's all about events. And in our daily work with the DOM we use the provided events like "click", "change", and "load" all over the place. But what if you want to create new events for custom objects that might not even have any associated UI. Unfortunately, the W3C standard for custom events in JavaScript has spotty implementation across browsers, or none at all in some cases.
So, what are we to do...well...here's a simple implementation of the observer pattern that can help solve the lack of internal support for custom events. Here's the Observer "classes":
var Observer = function() {
this.observations = [];
};
var Observer = function() {
this.observations = [];
};
var Observation = function(name, func) {
this.name = name;
this.func = func;
};
Observer.prototype = {
observe: function(name, func) {
var exists = this.observations.findAll(function(i) {
return i.name == name && i.func == func; }).length > 0;
if (!exists) { this.observations.push(new Observation(name, func)); }
},
unobserve: function(name, func) {
this.observations.remove(function(i) {
return i.name == name && i.func == func;
});
},
fire: function(name, data, scope) {
var funcs = this.observations.findAll(function(i) {
return i.name == name; });
funcs.forEach(function(i) { i.func.call(scope || window, data); });
}
};
First thing you'll notice is methods on the "observations" array like forEach() and findAll(). These methods are added by my set of JavaScript extensions found in a previous post. You'll also notice that this is very simple...so simple in fact that I'm not going to go through it line-by-line...I'm just going to demonstrate. Here's how you might use this object:
var Person = function() {
this.name = "John Doe";
this.age = 23;
this.observer = new Observer();
this.changeName = function(newName) {
this.name = newName;
this.observer.fire("nameChanged", newName);
};
this.changeAge = function(newAge) {
this.age = newAge;
this.observer.fire("ageChanged", newAge);
};
};
var p1 = new Person();
var p2 = new Person();
p1.observer.observe("nameChanged", alertNameChanged);
p2.observer.observe("ageChanged", alertAgeChanged);
function alertNameChanged(data) { alert("name changed to: " + data); }
function alertAgeChanged(data) { alert("age changed to: " + data); }
p1.changeName("James Doeson");
p2.changeAge(35);
Super simple...create an observer, observe a few things by name, fire a few things by name. So now you have a behavior very similar to custom events. One thing to note is that you can change the scope of the callback by passing a third parameter to the observe() method. So, if you want this to reference some different object within the callback function, just pass it in.
Comments