Created
September 24, 2011 21:33
-
-
Save bxt/1239893 to your computer and use it in GitHub Desktop.
jQuery binding event handlers to non-DOM objects Javascipt code examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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