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 appears 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.
What should I change to make this work?
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();
}
});
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 appears 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.
What should I change to make this work?
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();
}
});
Share
Improve this question
edited Apr 7, 2022 at 18:22
Brian Tompsett - 汤莱恩
5,89372 gold badges61 silver badges133 bronze badges
asked Jan 30, 2012 at 19:36
IndustrialIndustrial
42.8k71 gold badges201 silver badges292 bronze badges
2 Answers
Reset to default 14There are a couple things you need to sort out.
First of all, if your insideMenuHandler
returns false
or calls e.stopPropogation()
then your outsideMenuHandler
won't get called for clicks on #menu
. For example:
http://jsfiddle/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/ambiguous/MgkWG/1/
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.