Clics de enlace de eventos con backbone.js y jQuery

I need to bind two events in my backbone.js-view in order to toggle a menu. The idea is that if a button with the id #toggler is clicked the menu appers and any click outside the #menu element will hide the menu.

Unfortunately I cannot get this working with backbone's event binding without having the outsideMenuHandler() called on every click regardless if I clicked on the #menu element, or not.

¿Qué debo cambiar para que esto funcione?

This is what I have done in backbone.js, which doesn't work as intended:

myView = Backbone.View.extend({

    events: {
        'click #menu': 'insideMenuHandler',
        'click':       'outsideMenuHandler'
    }

    insideMenuHandler: function(e) {}, // Called when clicking #menu
    outsideMenuHandler: function(e) {} // Called on every click both on and off #menu

}

Just as a reference, here's what I would do using jQuery alone:

$(document).click(function(event) {
    if ( $(event.target).closest('#menu').get(0) == null ) {
        $("#menu").slideUp();
    }
});   

preguntado el 30 de enero de 12 a las 19:01

2 Respuestas

There are a couple things you need to sort out.

En primer lugar, si tu insideMenuHandler devoluciones false o llamadas e.stopPropogation() entonces tu outsideMenuHandler won't get called for clicks on #menu. Por ejemplo:

http://jsfiddle.net/ambiguous/8GjdS/

But that's not your whole problem. Your outsideMenuHandler will only be called for clicks on your view; so, if someone clicks on the page outside your view, your outsideMenuHandler won't get called and your menu won't go down. If you want the menu to go down when someone clicks anywhere outside #menu, then you'll have to manually bind to body and manually unbind when your view is destroyed. Something like this:

var myView = Backbone.View.extend({
    events: {
        'click #menu': 'insideMenuHandler'
    },

    initialize: function() {
        _.bindAll(this, 'insideMenuHandler', 'outsideMenuHandler');
    },

    render: function() {
        // Both <body> and <html> for paranoia.
        $('body, html').on('click', this.outsideMenuHandler);
        // ...
        return this;
    },

    remove: function() {
        // Clean up after ourselves.
        $('body, html').off('click', this.outsideMenuHandler);
        // ...
    },

    // ...
    outsideMenuHandler: function(e) {
        // ...
        return false;
    }
});

and then be sure to properly remove your view. For example:

http://jsfiddle.net/ambiguous/MgkWG/1/

Respondido el 31 de enero de 12 a las 00:01

Thanks a lot for your answer. Very appreciated! A quick question - as I understand, letting a click event return false will prevent any "default event" from occurring, meaning that all other clicks will be disabled as the outsideMenuHandler devoluciones false. Am I getting myself into trouble if I let my outsideMenuHandler retorno true after performing my logic (hiding my menu)? - Industrial

@Industrial: You'll end up with double calls to outsideMenuHandler from the body, html binding but that might not be a problem. You could probably get away with only binding outsideMenuHandler a html but you'd want to browser check that to make sure it behaves properly in all the browsers you care about. - mu es demasiado corto

The problem is, that you bind your event to the DOM element that you define as the views el. So if this is not the window.document as in your jquery example you cant notice any click outside them. The easiest way in your example would be to add the events manually with jquery and not with backbone.

Respondido el 31 de enero de 12 a las 00:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.