Skip to content

Instantly share code, notes, and snippets.

@bxt
Created September 24, 2011 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bxt/1239893 to your computer and use it in GitHub Desktop.
Save bxt/1239893 to your computer and use it in GitHub Desktop.
jQuery binding event handlers to non-DOM objects Javascipt code examples
// This is a little demo File on how to bind event listeners
// to own, non-DOM objects with jQuery.
// Since calling the default action is calling the identically
// named methods of our custom action and that would usually
// mean triggering the event again we use this handy callback:
function preventSelfcallCallback (event) {
event.preventDefault();
}
// Constructor for our custom event dispatching objects
function MyKlass (name) {
// Set some attributes, so we can see something happen
this.name=name;
this.count=0;
// Now bind our recursivity preventer
// since our methods will be named like the events
$(this).bind('increase decrease',preventSelfcallCallback);
// Note that a unbind or a namespaced trigger could
// pretty much throw us into infinite loop!
// maybe it's better to use some kind of slot object
// for event binding.
}
// Fix some problems with unbind first (jQ seems to call
// non-existing DOM-methods...)
//MyKlass.prototype={removeEventListener:$.noop,detachEvent:$.noop};
// Ok now it seems the binding to non-DOM is a wanted feature
// and not just a hack. The above line is usually not needed
// as it was fixed by the master himself:
// https://github.com/jquery/jquery/commit/7f5179b65431b77e89fa32623a5000e3630c191c
// http://bugs.jquery.com/ticket/6184
// However when I first ran this code I used exactly the know
// affected version 1.4.2 as this is the version currently
// deployed in production... ;)
// Method to increase the counter, triggers the increase event
MyKlass.prototype.increase=function() {
this.count++;
$(this).trigger('increase');
}
// Method to decrease the counter, triggers the decrease event
MyKlass.prototype.decrease=function() {
this.count--;
$(this).trigger('decrease');
}
// Create two instances
var myFirstInstance=new MyKlass('my first instance');
var mySecondInstance=new MyKlass('my second instance');
// First bin a increase handler to the first instance
$(myFirstInstance).bind('increase',function(){
console.log(this.name,'is now',this.count);
})
// Another increase handler, this time namespaced
$(myFirstInstance).bind('increase.namespace',function(){
console.log(this.name,'is now',this.count,'(from namespace!)');
})
// And a namespaced decrease handler
$(myFirstInstance).bind('decrease.namespace',function(){
console.log(this.name,'is merely',this.count,'(from namespace!)');
})
// That's our setup for now
// Time to do some triggering
// This triggers the two bound events, including the namespaced one
myFirstInstance.increase();
// Console yields:
// >>> my first instance is now 1
// >>> my first instance is now 1 (from namespace!)
// Triggers the other event
myFirstInstance.decrease();
// >>> my first instance is merely 0 (from namespace!)
// Manually trigger only the non-namespaced handlers,
// seems like you can use even the advanced jQuery event stuff!
$(myFirstInstance).trigger('!increase');
// >>> my first instance is now 1
// Now unbind the two namespaced events
$(myFirstInstance).unbind('.namespace');
// The namespaced increase handler is gone:
myFirstInstance.increase();
// >>> my first instance is now 1
// As is the namespaced decrease handler:
myFirstInstance.decrease();
// (console outputs nothing here!)
// No handlers bound to mySecondInstance's events
mySecondInstance.increase();
mySecondInstance.increase();
// Now we build a jQuery-object-List from our to instances
// and bind a handler to all two events on both instances.
$()
.add(myFirstInstance)
.add(mySecondInstance)
.bind('increase decrease',function(event){
console.log('oh a change! ',this.name,'is ',this.count);
// We can even prevent calling downstream handlers
event.stopImmediatePropagation();
});
// This is such a downstream handler, will not be called!
$()
.add(myFirstInstance)
.add(mySecondInstance)
.bind('increase decrease',function(){
console.log('This handler would not be called');
});
// The old handler as well as our new ones are called now
myFirstInstance.increase();
// >>> my first instance is now 1
// >>> oh a change! my first instance is 1
// The second instance and the other event got the handler too
mySecondInstance.decrease();
// >>> oh a change! my second instance is 1
// Wow. When using jQuery you get a free event library,
// full with propagation control, namespaced handlers,
// multi-bind functionality, a well known API.
// It's just a little hacky, jQuery will try to call
// DOM-methods on your objects, so having a method named
// detachEvent in your object might lead to some funny stuff.
// Also, jQuery adds an own field to you object as you can
// see here:
console.log(JSON.stringify(mySecondInstance));
// >>> {"name":"my second instance","count":1,"jQuery1316895832458":31}
// Maybe its better to just use an empty object for event handling:
var dispatcher=$({});
dispatcher.bind('foo',function(){
console.log('Still a hack, but better');
})
dispatcher.trigger('foo');
// >>> Still a hack though.
// Another option is not preventDefault-ing
// but rather call the methods with trigger:
// First another dummy class
function Foobar(){}
// Now the methods don't include trigger-calls
Foobar.prototype.aCall=function(){
console.log('call method!');
}
// Instantiate
var foobar=new Foobar();
// Bind a handler
$(foobar).bind('aCall',function(){
console.log('call handler');
});
// And now, handler and method are called
$(foobar).trigger('aCall');
// >>> call handler
// >>> call method!
// You could do interesting stuff with preventDefault etc. here
// Happy coding!
// (This code was run and tested on jQuery 1.6.4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment