Disable specific event in a Backbone.js view

backbone-events, backbone.js, javascript

Solution

You can specify the events you want to use when you call `delegateEvents`:

delegateEvents `delegateEvents([events])`

Uses jQuery's `delegate` function to provide declarative callbacks for DOM events within a view. If an events hash is not passed directly, uses `this.events` as the source.

So you could do something like this:

var v = new View({
    model: model,
});
v.undelegateEvents();
var e = _.clone(v.events);
delete e.mousedown;
v.delegateEvents(e);
v.render();

You might want to push that logic into a method on View though:

detach_mousedown: function() {
    this.undelegateEvents();
    this.events = _.clone(this.events);
    delete this.events.mousedown;
    this.delegateEvents();
}

//...

v.detach_mousedown();

You need the `this.events = _.clone(this.events)` trickery to avoid accidentally altering the "class's" `events` (i.e. this.constructor.prototype.events) when you only want to change it for just one object. You could also have a flag for the `View` constructor that would do similar things inside its `initialize`:

initialize: function() {
    if(this.options.no_mousedown)
        this.detach_mousedown()
    //...
}

Another option would be to have a base view without the `mousedown` handler and then extend that to a view that does have the `mousedown` handler:

var B = Backbone.View.extend({
    events: {
        "mouseup": "over"
    },
    //...
});
var V = B.extend({
    events: {
        "mousedown": "start",
        "mouseup": "over"
    },
    start: function() { /* ... */ }
    //...
});

You'd have to duplicate the `B.events` inside `V` or mess around with a manual `extend` on the `events` as `_.extend` won't merge the properties, it just replaces things wholesale.

Problem

I am working on a nested backbone view, in which if you click on, it will create a new instance of the same view. I want to disable only a specific event, not all of them; in this case, the click. I tried using undelegateEvents(), but this will disable all the functions. Any ideas on how can this be done? Here is a piece of the code I am working on: ``` var View = Backbone.View.extend({ events: { "mousedown": "start", "mouseup": "over" }, start: function() { var model = this.model; var v = new View({ model: model, }); v.undelegateEvents(); //I just want to disable mousedown v.render(); }, over: function() { /* some code here */ }, render: function() { /* some code here */ } }); ``` The idea is to ban clicking in the second instantiated view while keeping the other events. The first one will have all of its events. Thanks

Original source