why some events do not work in backbone - javascript

In the events hash, i want to use resize event, but they
do not work neither. However, click event works well. why resize does not work?
var SubheaderView = Backbone.View.extend({
id: 'gallery',
tagName: 'div',
events: {
'click #minor': 'getPadding',
'resize #minor': 'getPadding' //not work
},
initialize: function() {
this.render();
},
render: function() {
this.$el.append(subheaderTemplate);
},
getPadding: function() {
var pad_top = Math.floor($('#minor').height() * 0.4);
var pad_left = Math.floor($('#minor').width() * 0.07);
var pad = pad_top + 'px 0px 0px ' + pad_left + 'px';
$('#cover h1').css({'padding': pad});
}
});

It does not related to Backbone at all. According to MDN, only window has a resize event.

You can do something like this:
Add this code to backbone.js file you are using
Backbone.View.prototype.eventAggregator = _.extend({}, Backbone.Events);
$(window).resize(function () {
Backbone.View.prototype.eventAggregator.trigger('window:resize');
});
Then bind the event aggregator to any view to want to use the resize event
this.eventAggregator.bind('window:resize',this.resize)
where this.resize is the function to be called for the resize event

Related

JQuery not recognising elements added through backbone view even after using 'on'

$(document).ready(function(){
$('.tagLines').on('mouseover', function(){
$(this).css("background-color","#ffffff").css("box-shadow", "0 0 4px 4px #C9C9C9");
}).on('mouseleave', function(){
$(this).css('background-color', '#F7F7F7').css("box-shadow", "0 0 2px 2px #C9C9C9");
}).on('click', function(){
window.location.hash = "manageMarks";
});
//this section is for all the views used in the application
var PGHome = Backbone.View.extend({
tagName: 'div',
initialize: function(){
},
render: function(){
var template = _.template($("#home").html(), {} );
this.$el.html( template );
}
});
var pgHome = new PGHome({el: $("#bodyContainer") });
//***********************************************************
//this is a router for the application
var NavRouter = Backbone.Router.extend({
routes:{
"manageMarks": "manage",
"": "home"
}
});
var navRouter = new NavRouter();
navRouter.on('route:manage', function(){
console.log("Manage Modules");
}).on('route:home', function (){
pgHome.render();
});
Backbone.history.start();
//******************************************
});
The above is a js snippet and its working as far as rendering a view with backbone is concerned. The problem is after the view is rendered, the elements rendered's events (click, mouseover, mouseleave) are not firing. The events where working prior to adding them with backbone. Can anyone help?
You need use event delegation, because you add events, before element has been appended to page
$("#bodyContainer").on('mouseover', '.tagLines', function(){
$(this).css("background-color","#ffffff").css("box-shadow", "0 0 4px 4px #C9C9C9");
}).on('mouseleave', '.tagLines', function(){
$(this).css('background-color', '#F7F7F7').css("box-shadow", "0 0 2px 2px #C9C9C9");
}).on('click', '.tagLines', function(){
window.location.hash = "manageMarks";
});
There isn't .tagLine element in DOM when bind events to it.
The code like this,
var PGHome = Backbone.View.extend({
tagName: 'div',
events:{
'mouseover .tagLines': function(){
// ...
},
'mouseleave .tagLines': function(){
// ...
},
'click .tagLines': function(){
// ...
}
},
initialize: function(){},
render: function(){
var template = _.template($("#home").html(), {} );
this.$el.html( template );
}
});

how to call the function when the page first loaded in backbone?

How to call the updateh1Css when the page first load? For now, it works when the window is resized, but I also want to call it when the page first load.
var SubheaderView = Backbone.View.extend({
id: 'gallery',
tagName: 'div',
initialize: function() {
$(window).on('resize', this.updateh1Css);
this.render();
},
render: function() {
this.$el.append(subheaderTemplate);
},
updateh1Css: function() {
var pad_top = Math.floor($('#minor').height() * 0.4);
var pad_left = Math.floor($('#minor').width() * 0.07);
var pad = pad_top + 'px 0px 0px ' + pad_left + 'px';
$('#cover h1').css({'padding': pad});
}
});
Since you're using jQuery you can use $(document).ready
initialize: function() {
$(window).on('resize', this.updateh1Css);
$(document).ready(this.updateh1Css);
this.render();
}
This will make it run when the document first finishes loaded.

Drop event in backbone view

I'm trying to add a drop event in my backbone view but I can't get it right. Below is the code I'm using and you can also check out this jsfiddle.
var View = Backbone.View.extend({
events: {
'drop .dropzone': 'drop'
},
drop: function(e) {
e.preventDefault();
alert('Dropping');
},
initialize: function() {},
render: function() {}
});
$(function() {
var view = new View({
el: $('.dropzone');
});
});​
if your view's el == .dropzone then you should do
events: {
'drop': 'drop'
},
if you specify just event type without selector it will listen to event on the view's root element - $('.dropzone') in this case.
The way you did it here would try to find .dropzone element among children of .dropzone element - and clearly it would fail to find this element at all

Backbone.js hover event not triggering

I'm trying to use Backbone.js for the first time and I'm having some trouble. I don't know if my problem is that I'm not understanding how backbone is supposed to work or if it's just a code problem.
I'm trying to create a dynamic menu, and I have no problem creating the main menu bar with it's items, but I can't get the hover event to trigger whenever I hover one of the menu items.
Views
var MenuView = Backbone.View.extend({
initialize: function(items) {
this.menu = items;
//Main navigation bar
this.el = $("#main-nav");
this.trigger('start');
this.render();
},
render: function() {
var me = this;
_.each(this.menu, function(mi) {
mi.render(me.el);
});
return this;
},
handleHover: function(e) {
console.debug(e);
}
});
var MenuItemView = Backbone.View.extend({
tagName: 'li',
className:'menu-item',
events: { //none of these work
'hover a':'handleHover',
'mouseover a':'handleHover',
'mouseover':'handleHover',
'click': 'handleHover',
'click a': 'handleHover'
},
initialize: function(mi) {
this.menuItem = mi;
this.el = $("<li class=\"menu-item\"></li>")
},
render: function(parent) {
this.el.append('' + this.menuItem.get("text") + '');
parent.append(this.el);
return this;
},
handleHover: function(ev) {
console.debug("Hovering! " + ev + this.menuItem.get("cid"));
console.debug(ev);
return false;
}
});
Model
var MenuItem = Backbone.Model.extend({
defaults: {
parent: null,
children: [],
link: "",
text: ""
}
});
Startup code
$(document).ready(function() {
var menu = new MenuView([
new MenuItemView( new MenuItem({link: "/", text: "Home"})),
new MenuItemView( new MenuItem({link: "/", text: "Users"})),
new MenuItemView( new MenuItem({link: "/", text: "Configuration"}))
]);
});
Any help will be appreciated!
Thanks!
Update
Ok, after taking the definition of el outside of the initialize method on the MenuItemView view, it works, BUT that same element gets reused on all instances of the view, so I had to change the view to the following code in order to make it work the way I want it:
var MenuItemView = Backbone.View.extend({
events: { //none of these work
'hover a':'handleHover',
'mouseover a':'handleHover',
'mouseover':'handleHover',
'click': 'handleHover',
'click a': 'handleHover'
},
el: $('<li class="menu-item"></li>'),
initialize: function(mi) {
this.menuItem = mi;
this.el = $(this.el).clone(true);
},
render: function(parent) {
this.el.append('' + this.menuItem.get("text") + '');
parent.append(this.el);
return this;
},
handleHover: function(ev) {
console.debug("Hovering! " + ev + this.menuItem.get("cid"));
console.debug(ev);
return false;
}
});
Wny do I have to clone the element on a new instance?
hover is not a normal event, but a 'convenience' event provided by jquery. It is a combination of mouseenter and mouseleave.
Binding to mouseenter and mouseleave instead of hover will do what you need.
Re: "Why do I have to clone the element on a new instance?"
The underlying problem is right here:
var MenuItemView = Backbone.View.extend({
// ...
el: $('<li class="menu-item"></li>'),
The $('<li class="menu-item"></li>') call is executed when MenuItemView is being defined so you end up with only one $('<li>') being shared across all instances of MenuItemView.
If you create the el inside initialize or render then you'll have to bind the events by hand using delegateEvents:
By default, delegateEvents is called within the View's constructor for you [...]
So if you create this.el yourself then you'll have to call this.delegateEvents() yourself. For example:
var MenuItemView = Backbone.View.extend({
// ...
render: function() {
this.el = $('<li class="menu-item"><a>' + this.cid + '</a></li>');
this.delegateEvents();
return this;
},
//...
});
Demo: http://jsfiddle.net/ambiguous/RPqMh/2/
However, if you clone your this.el with the withDataAndEvents flag on, then you should be fine:
var MenuItemView = Backbone.View.extend({
el: $('<li class="menu-item"></li>'),
// ...
initialize: function() {
this.el = this.el.clone(true);
this.el.append('<a>' + this.cid + '</a>');
},
//...
});
Demo: http://jsfiddle.net/ambiguous/hCW3F/1/
But if you just this.el.clone(), it won't work because the delegate won't be bound to the clone:
var MenuItemView = Backbone.View.extend({
el: $('<li class="menu-item"></li>'),
// ...
initialize: function() {
this.el = this.el.clone();
this.el.append('<a>' + this.cid + '</a>');
},
// ...
});
Demo: http://jsfiddle.net/ambiguous/KZNPA/
But if you add your own delegateEvents call, you'll be okay:
var MenuItemView = Backbone.View.extend({
el: $('<li class="menu-item"></li>'),
// ...
initialize: function() {
this.el = this.el.clone();
this.el.append('<a>' + this.cid + '</a>');
},
render: function() {
this.delegateEvents();
return this;
},
// ...
});
Demo: http://jsfiddle.net/ambiguous/KZNPA/1/
It seems to me that you don't need this properties:
tagName: 'li',
className:'menu-item'
in MenuItemView if you specify this.el = $('<li class="menu-item"></li>');

Understanding Backbone.js event handler

So here is my view:
$(function() {
var ImageManipulation = Backbone.View.extend({
el: $('body'),
tagName: "img",
events: {
'mouseover img': 'fullsize',
'click img#current': 'shrink'
},
initialize: function() {
_.bindAll(this, 'render', 'fullsize', 'shrink');
//var message = this.fullsize;
//message.bind("test", this.fullsize);
},
render: function() {
},
fullsize: function() {
console.log("in fullsize function");
console.log(this.el);
$('.drop-shadow').click(function() {
console.log(this.id);
if (this.id != 'current') {
$('.individual').fadeIn();
$(this).css('position', 'absolute');
$(this).css('z-index', '999');
$(this).animate({
top: '10px',
height: '432px',
}, 500, function() {
this.id = "current";
console.log("animation complete");
return true;
});
};
});
},
shrink: function() {
$('.individual').fadeOut();
$('#current').animate({
height: '150px',
}, 500, function() {
this.id = "";
$(this).css('position', 'relative');
$(this).css('z-index', '1');
console.log("animation complete");
return true;
});
}
});
var startImages = new ImageManipulation();
});
What I don't understand is how to change the el to make 'this' take over the click function I have in full-size. I would much rather have the click jQuery function removed and have the mouseover function be another click, but I cant seem to figure out how to assign 'this' to the particular image that is being clicked. I hope my question makes sense.
Backbone's event handler assumes that you want to know about the object (both its code, and its DOM representation, the View.el object) for every event, and that the event is intended to change some aspect of the view and/or model. The actual target of the click is something you're assumed to know, or assumed to be able to derive.
Derivation is rather simple:
fullsize: function(ev) {
target = $(ev.currentTarget);
And replace all your this. references within your call to target.. this. will continue to refer to the View instance. In your inner function, the anonymous one assigned to .drop-shadow, this. will refer to the object that was just clicked on. If you want access to the surrounding context, use the closure forwarding idiom:
fullsize: function(ev) {
var target = ev.currentTarget;
var self = this;
$('.drop-shadow').click(function(inner_ev) {
console.log(this.id); // the same as inner_ev.currentTarget
console.log(self.cid); // the containing view's CID

Categories

Resources