Event handling in nested compositeView - javascript

I am using the same structure as explained in the answers for this question -- > How to handle nested CompositeView using Backbone.Marionette?
to render my composite views and Item view. My Item view consists of LI tag. I want to handle click event for this Itemview. I am trying my code as below :which is not working The same events code snippet If I write in my first composite view, It get's triggered. But events do not get triggered in ItemView. Please help.
var topNavMenuView = Backbone.Marionette.ItemView.extend({
tagName :'li',
className:'dropdown',
template : _.template(topNavMenuItemTemplate) ,
initialize:function(options){
console.log("initialize");
this.id=options.menuCode;
},
events: {
'click li' : function(event){
alert('click');
},
'click ' : function(event){
alert('click');
}
}
});

View events should return events hash like this
events: {
'click': 'onClick'
},
onClick: function(){
alert('click');
}

Related

Marionette events click. How to get attribute of clicked item?

How can I get value attribute from players.html using Marionette's click event? I basically need to know which player was clicked. Here is my code:
players.html
{#myplayers}
<player class="standard" value="{player}" style="{style}"></player>
{/myplayers}
players.js
...
return Marionette.ItemView.extend({
model: new Models.Players(),
template: 'tmp/players',
events: {
'click player': 'playerSelect'
},
initialize: function() {
},
playerSelect: function(e) {
console.log('click test');
// I need here value (attribute), of player that was clicked
}
});
...
You can inspect e.currentTarget in your event handler:
playerSelect: function(e) {
var playerValue = e.currentTarget.getAttribute('value');
}
As an aside, player is not a known HTML tag or a valid name for a custom element. The HTML spec caters for unrecognised tags so your template will still be rendered, but it will be treated as an unknown element.
If that isn't what you intended may want to use a standard HTML5 tag.

Asynchronously add events in backbone

In backbone, how do you asynchronously add events, based on other events. I want to allow click handlers on a certain set of buttons, but not until their containing button is clicked. Here's how I have things set up at the moment:
var ProductsView = Backbone.View.extend({
events : {
"click .filter-options-container" : "filterOptionContainerClick"
},
filterOptionContainerClick: function(e){
$(e.currentTarget).addClass('active');
//want to add an event to all .filter-options to allow them to trigger the filterOptionClick function when clicked
},
filterOptionClick: function(e){
$('.filter-option').removeClass('active');
$(e.currentTarget).addClass('active');
$('.filter-options-container').removeClass('active');
}
});
return ProductsView;
Instead of adding click handlers for sub-buttons whenever the container is clicked, you can use another approach:
register sub-buttons' click handlers once with events map.
add boolean property to the View to store state of the container
click
toggle that property in filterOptionContainerClick handler
depends on the value of the property, allow/disallow clicking on
sub-buttons
So the code should look like this:
var ProductsView = Backbone.View.extend({
events : {
"click .filter-options-container" : "filterOptionContainerClick",
"click .filter-options" : "filterOptionClick" // register sub-buttons' click handlers
},
initialize: function() {
this.enabled = false; // state of the container click
},
filterOptionContainerClick: function(e){
this.enabled = !this.enabled;
if (this.enabled) $(e.currentTarget).addClass('active');
else $(e.currentTarget).removeClass('active');
},
filterOptionClick: function(e){
if (!this.enabled) return;
$('.filter-option').removeClass('active');
$(e.currentTarget).addClass('active');
$('.filter-options-container').removeClass('active');
}
});

event ID, event binding switch-like

is there an id for each fired event?
I am yet to dig into events, for now i have a view (div) with some buttons, a click on the div itself should do the same as a click on one of the buttons.
When i click on any button, the event elevates and the function that bind to 'click div' also called.
For a quick fix that i did, i save the event object and on 'click div' i check if the calle event is the same that i saved, then do nothing.
What is the better way to do this?
And also i cant find ids in events, are there any and can they be added to the event object?
if( arguments ){
if( arguments[0] ){ // jquery event
if( this.lastEvent == arguments[0] ){ //already processed event
return;
}
this.lastEvent = arguments[0];
}
}
UPDATE:
as suggested - what id did, in view:
events: {
'click .btn-mark-saw': 'mark_saw',
'click .btn-mark-circle': 'mark_circle',
'click':'mark_circle'
},
mark_saw: function(event){
event.stopPropagation();
//...
this.render();
},
mark_circle: function(event) {
event.stopPropagation();
//...
this.render();
},
it works, thank you!
This should serve your purpose.
$(document).ready(function(){
$("#divID").live("click", function(){
//div click action..
});
$("#buttonID").live("click", function(event){
//button click action..
event.stopPropagation();
});
});
Thanks..

Ember.View Contenteditable events

I'm trying to get an Ember.View to listen to events triggered by a contenteditable element, but am having a little trouble.
The end result I'm going for is to have the contenteditable changes bound to an Ember Object property.
Events are correctly bound using jQuery directly as given in this answer: contenteditable change events
$(function () {
$(document).on('focus', '[contenteditable]', function(event) {
var $this = $(this);
console.log("$" + event.type);
return $this;
});
$(document).on('blur keyup paste', '[contenteditable]', function(event) {
var $this = $(this);
console.log("$" + event.type);
return $this;
});
});
But event handlers that specified on the Ember.View never get called:
App.ContentEditable = Ember.View.extend({
item: App.Item.create({name:"Editable content"}),
tagName: "span",
contenteditable:"true",
attributeBindings: ["contenteditable"],
// Only event that gets triggered
click: function(){ console.log("click") },
// None of these events are triggered
focusin: function(){ console.log("focusin") },
focusout: function(){ console.log("focusout") },
keyup: function(){ console.log("keyup") },
blur: function(){ console.log("blur") },
paste: function(){ console.log("paste") },
});​
I've put together a jsfiddle showing that the .on() events are logged to the console but the events on the Ember.View are not: http://jsfiddle.net/chrisconley/RqSn4/
That's because the event names in Ember are translated to a more Ember-like naming convention. This stuff happens in packages/ember-views/lib/system/event_dispatcher.js. As you can see, you have to rename your existing event handlers into keyUp, focusIn and focusOut.
The other events blur and paste are not handled by default, thats what customEvents on Ember.Application is for, see http://jsfiddle.net/pangratz666/CHVRt/
App = Ember.Application.create({
customEvents: {
blur: 'blur',
paste: 'paste'
}
});

Backbone.js button click event is fired for all instances of the button instead of just the one that is clicked. Why?

I am learning backbone.js and am quite new. I have a view that acts as a button:
simpleButton = Backbone.View.extend({
template: "<button class='${classes}'>${text}</button>",
el: $("body"),
events: {
"click": "onClick",
"focus": "onFocus",
"blur": "onBlur"
},
initialize: function (args) {
_.bindAll(this, 'render');
this.rendered = false;
this.text = args.text || 'button';
this.classes = args.classes || [];
this.classes.push('ui-button');
//console.debug("Wh.views.simpleButton.initialize classes ",this.classes);
if (args.autoRender === true) this.render();
},
render: function () {
//console.debug("Wh.views.simpleButton.render classes ",this.classes);
if (this.rendered === false) {
$.tmpl(
this.template, {
classes: this.classes.join(' '),
text: this.text
}
).appendTo(this.el);
this.rendered = true;
}
},
//event handlers
onClick: function (ev) {
console.debug(this);
alert("click on ", ev, this);
},
onFocus: function (ev) {
////console.debug(ev);
},
onBlur: function (ev) {
}
});
My problem is that if I create two buttons, and click just one of them, I get the alert box two times, and the debug showing me "this" shows the first button first, and the second button next.
Am I missing something?
The events you define are bound to the "el" property of your view. In your case it is "body" so when you fire up click with 2 simpleButton views instantiated, you have 2 of them listening for the same event.
Each view you instantiate should represent one and only one DOM element defined by the el property. So if you want to create a button view (not sure this is 'best practice' in a real program) you could have :
SimpleButton = Backbone.View.extend({
template : "<button class='${classes}'>${text}</button>",
tagName : "div", // defines the html tag that will wrap your template
className: ".buttonbox",
...
});
mybtn = new SimpleButton();
mybtn.render().appendTo('body')
That way your click event will only concern the one div.buttonbox inside of which your button lives.
Notice : Backbone idea of the render function is creating an html string you'll use afterwards to append prepend or whatever in the DOM. That way if you create many you can do it so you only refresh the DOM once (refreshing the DOM is expensive)...
Use this in your View .it will unbind the click events
initialize : function() {
$(this.el).unbind("click");
}
Just a thought that creating a Backbone.View for each and every button in your app could be a performance overkill and you can't leverage the "delegate" feature in jQuery. I'd instead create a Backbone.View for the parent element of those buttons instead.
Of course, if you have a few special buttons with complicated logic then they probably do deserve their own View classes. :)
Give your buttons unique ids, for example <button id="button1"> and <button id="button2">, then in your events hash, you need to specify the click event and the id of the button you want to handle that event for, e.g:
events : {
"click #button1" : "onClick",
"click #button2" : "doSomethingElse"
}
Now this will call onClick() only when you click on the button with id=button1 and call doSomethingElse() when you click on the button with id=button2

Categories