Friday, May 25th, 2007

Event.observeMethod: More AOP for JavaScript

Category: JavaScript, Library, Prototype

<>p>Christos Constandinou has created Event.observeMethod, a library that gives you a way of adding event listeners to methods in an object and running other methods before, around and/ or after the method you are listening to.

The code itself is small, based on Prototype, and only 49 lines (1.8kb), uncompressed.

javascript
< view plain text >
  1. Event.observeMethod( window, 'myNewFunc', myBeforeFunc, Event.BEFORE );
  2. Event.observeMethod( Friend, "initialize", this.addBirthday.bind( this ) );

Dojo has allowed you to do this kind of thing in its connect() model. You tend to wonder how often people need this granularity versus just being able to attach normal events.

It makes a lot of sense in large scale applications, but maybe not your JS hacking?

Related Content:

Posted by Dion Almaer at 8:15 am
11 Comments

+++--
3.6 rating from 23 votes

11 Comments »

Comments feed TrackBack URI

Broken link?

Comment by Greg — May 25, 2007

@Dion,
I’d find this kind of thing very useful. In parts of the application I’m working on I have some Event.observe’s that conditionally choose when to call another function is executed. If I wanted to base another action of that function being called, I’d have to duplicate the checks for the element’s existence and the conditional checks to get it to fire at the same time. It also adds a layer of abstraction that changes “I do funcB when this and this happen so it coincides with this funcA” to “I do funcB when I do funcA”.

Comment by Jon Hartmann — May 25, 2007

210 Ajax Frameworks and counting.

Should change that title to 211 Ajax Frameworks and Counting…

Comment by Mike — May 25, 2007

this is the same as decorators in python only less powerful

Comment by Uriel Katz — May 25, 2007

Some aspect oriented programming flavor there. At the very least it can’t hurt. I figure it could be useful for inserting activities before serializing a form or some such thing.

Comment by Adam Sanderson — May 25, 2007

I wrote a similar script that is used to add prioritized preprocessors and postprocessors to methods while still retaining original context. Such functionality can be pretty useful, but most of the time it probably isn’t worth the extra bandwidth unless its being used in a large web app.

For instance, I wrote an active record-based JavaScript database library. The base library only includes the necessary logic with no data/param validation (good for production), but I have a separate validation module that attaches to the pre-existing methods as preprocessors, ceasing operation and throwing an error as necessary.

Comment by Andy Kant — May 25, 2007

I’ve been struggling with very similar problems, but came up with two totally different solutions. For the idea of objects or methods having events I am creating a library I call Object.Event (click on my name below to go to the post), but the methods need to specify that an event is happening, i.e. this.notify(‘event_name’);

For simple method interception or modification I use the following:


Function.prototype.intercept = function(interceptor){
var original_function = this;
return function(){
return interceptor.apply(this,[original_function.bind(this)].concat($A(arguments)));
};
};

test = function(str){
alert(str);
}.intercept(function(original_function,str){
return original_function(str.toUpperCase());
});

test('testing');

Comment by Ryan Johnson — May 25, 2007

Dion, you should get your comments system to automatically wrap a code tag with pre if it’s not an allowed tag =)

Comment by Ryan Johnson — May 25, 2007

I am providing a library, Cerny.js, which puts emphasis on improving JavaScript development in large teams. Method call interception is one of the key ingredients of Cerny.js and it allows you to achieve dynamic type checking, tracing, profiling and programming by contract. I consider it very useful, but then again, i am the author .-)

Read more at http://www.cerny-online.com/cerny.js !

Comment by Robert Cerny — May 25, 2007

Dojo has done this since forever. It’s a great tool that I use regulary. Think of it in terms of GUI programming. Create a “Bean” type object, you can tell your gui ( or service ) components to listen for changes in it’s properties. It lets components which are interested in an event ask to be notified when it occurs instead of forcing your dataset to be responsible for knowing about and notifying everything that is interestested in it. In otherwords it a natural extension of the existing javascript event paradigm.

Comment by Vance Dubberly — May 25, 2007

I had to modify the code so that it would work with prototyped methods. Since prototyped methods are not attached to the objects until it is initialized, the scope does not transfer to the new initialized object.

this also works with server side JScript (ASP).


if(!scope.listeners[method]){
scope.listners[method] = this.getAspects();

var $scope = scope;
if(!$scope[method] && $scope.prototype[method])
$scope = scope.prototype;

var _method = $scope[method];
$scope[method] = function(){
var arg = $(arguments);
// using [this] scope ensures its applied to the owning object
Event.dispatchCustomEvent(this, scope.listeners[Event.BEFORE], args);
Event.dispatchCustomEvent(this, scope.listeners[Event.AROUND], args);

var r = _method.apply(this, args);
args.push(r);
args.push(this);

Event.dispatchCustomEvent(this, scope.listeners[Event.AROUND], args);
Event.dispatchCustomEvent(this, scope.listeners[Event.AFTER], args);
return r;
}
}

Comment by Steven Moberg — September 13, 2007

Leave a comment

You must be logged in to post a comment.