I can attach handlers to Backbone Views like:
var TodoView = Backbone.View.extend({ events: { "xxx": "eventHandler1" "yyy": "eventHandler2" } });
But what if I want to attach more than 1 handler to the same event?
var TodoView = Backbone.View.extend({ events: { "xxx": "eventHandler1" "yyy": "eventHandler2" "xxx": "eventHandler3" // this isn't valid ... at least in CoffeeScript } });
I could create a custom handler like
function compositeXXX() { eventHandler1(); eventHandler2 }
But this doesn't seem ideal ...
The addEventListener() method You can add many event handlers of the same type to one element, i.e two "click" events. You can add event listeners to any DOM object not only HTML elements. i.e the window object. The addEventListener() method makes it easier to control how the event reacts to bubbling.
One event can have more than one event handler method in the same class or in different classes. At the run time only one handler method will be triggered at a time. After triggering the one that has to be deactivated and then another handler method will have to be registered to be triggered.
Both handlers will run, the jQuery event model allows multiple handlers on one element, therefore a later handler does not override an older handler. The handlers will execute in the order in which they were bound.
This:
events: { "xxx": "eventHandler1", "yyy": "eventHandler2", "xxx": "eventHandler3" }
won't work because events
is an object literal and you can have at most one (key,value) pair in an object. That would probably be the same as saying:
events: { "xxx": "eventHandler3", "yyy": "eventHandler2" }
This CoffeeScript:
events: "xxx": "eventHandler1" "yyy": "eventHandler2" "xxx": "eventHandler3"
is functionally identical to the JavaScript version and won't work for the same reason.
Andy Ray's idea of using
'event selector': 'callback1 callback2'`
won't work either as Backbone won't understand that it should split the value on whitespace; similarly, this:
'event selector': [ 'callback1', 'callback2' ]
won't work because Backbone doesn't know what to do with an array in this context.
Views bind their events through delegateEvents
and that looks like this:
delegateEvents: function(events) { // Some preamble that doesn't concern us here... for (var key in events) { var method = events[key]; if (!_.isFunction(method)) method = this[events[key]]; if (!method) throw new Error('Method "' + events[key] + '" does not exist'); // And some binding details that are of no concern either... } }
So method
starts out as the value for 'event selector'
. If it is a function from something like:
'event selector': function() { ... }
then it is used as-is, otherwise it is converted to a property of this
:
method = this[events[key]]; // i.e. method = this[method]
If one were bold, one could adjust delegateEvents
to understand an array or whitespace delimited string:
// Untested code. var methods = [ ]; if (_.isArray(method)) methods = method; else if (_.isFunction(method)) methods = [ method ]; else methods = method.split(/\s+/); for (var i = 0; i < methods.length; ++i) { method = methods[i]; if (!_.isFunction(method)) method = this[method]; // And the rest of the binding stuff as it is now with a possible adjustment // to the "method does not exist" exception message... }
A fairly simple patch like that would allow you to use a whitespace delimited list of handlers:
'event selector': 'callback1 callback2'
or an array of handlers:
'event selector': [ 'callback1', 'callback2' ]
or even a mixed array of method names and functions:
'event selector': [ 'callback_name1', function() { ... }, 'callback_name2' ]
If you don't want to patch your Backbone or forward such a patch to the Backbone maintainers then you could go with your original "manual dispatching" idea:
'event selector': 'dispatcher' //... dispatcher: function(ev) { this.handler1(ev); this.handler2(ev); }
I solved this issue by using jQuery's event namespaces
var TodoView = Backbone.View.extend({ events: { "xxx.handler1": "eventHandler1", "yyy": "eventHandler2", "xxx.handler3": "eventHandler3" } });
This isn't what event namespaces were originally intended for, but as long as they don't clash with other namespaces it shouldn't cause a problem.
The main issue is just that you can only have one value per key in an object and this makes the keys unique.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With