Is there anyway to bind events with "if" dependence in Backbone? - javascript

I wanna know if there is anyway to depend event binding with "if" in Backbone.
For example, if i have user profile model and i want to bind "Send Message" button event only if the attribute "acceptMsgs" sets true.
My current solution is to check it in the event firing, if there is better way, pls correct me.

I'm not sure if it's a better way to do it, but you can use a function that returns a hash for the event hash (and of course in the function you can check for some condition).
For example something along the lines of
myView = Backbone.Views.extend({
events: function () {
if (someCondition) {
return { "#someButton click" : "nameOfFunction"}
}
}
//the rest of your view
});
Alternatively you can forgo the event hash and bind your events in the initialize method, for example
initialize: function (options) {
if (someCondition) {
this.$el.on("click", "#someButton", nameOfFunction);
}
}

Related

Trigger event in Backbone.js and Saiku

I'm new to backbone. I have been looking it has been used in Saiku. I came across the below line.
Saiku.session.trigger('workspace:new', { workspace: this });
Is 'workspace:new' an event? How does backbone trigger recognize it as an event?
Short answer: yes, workspace:new is an event.
Backbone has several built-in events that you can listen for. But you can also trigger custom events, as this code does. The event is identified by only a string (in this case, "workspace:new"). When you call trigger on an object that inherits from Backbone's Event Module, that event "happens." As a second parameter to trigger, you can pass some data about the event, anything you want accessible from the event handler function.
Then, usually somewhere else, there will be code waiting for that event to happen. That is set up by calling the .on or .listenTo methods.
Here's a basic example: (See it in action on JSBin)
var model = new Backbone.Model();
model.on('my-event', function (data) {
console.log("my-event happened!");
console.log(data);
});
model.trigger('my-event');
model.trigger('my-event', 'some-data');
model.trigger('my-event', { anything: 'works' });

Can I trigger a backbone event for .ready()?

I want to trigger a backbone event when the view has rendered. Ideally, I'd write something like this:
var DetailView = Backbone.View.extend({
id: 'detailpage',
events: {
'ready document': '_bringSlideDown',
'click .close-slideDown': '_closeSlideDown'
},
and I would be able to create and call a _bringSlideDown function once the view has finished loading. This doesn't work - is there a better way to call this event?
Specifically, I want the event to only run once, which is why I'm not nesting it in the render function. I want the view to be able to render multiple times, but want to use Backbone's .off() method to handle this event once before unbinding it. Thanks!
I have three points that I want to mention.
First, by best practice I execute Backbone code until the DOM is
ready, so if you follow this rule, your backbone view will be
executed after the DOM was ready(so there is no way to listen for the ready event).
If you want to listen for DOM additions with jQuery, you should use
plugins like: https://github.com/brandonaaron/livequery
Regarding your use case, instead of listen to the DOM, check in the render
method if is the first time that you are rendering the view using
a flag.
I would do something like this:
var YourView = Backbone.View.extend({
_rendered : false,
events : {
'click .close-slideDown': '_closeSlideDown'
},
render: function(){
//some render stuff
if( !this._rendered ){
this._rendered = true;
this._bringSlideDown();
}
}
});
Basically

Backbone View custom events

I want to validate a users input by keydown. For this I require a keydown event.
Unfortunatly I only have found custom model events:
initalize: function(){
this.model = new ModelClass();
this.model.bind("keydown", this.validate, this);
}
That approach surely is fine for model events but I don't believe this is the right way for view, ui-related stuff...
To give you a better explication, this is how I would like to use my event:
var SomeView;
SomeView = Backbone.View.extend({
events: {
"keydown input#some-field": "validate" // custom event
, "change input#some-field": "doSomethingElse" // predefined backbone event
},
validate: function(attr){
// validation
}
});
So what is the approach to create custom Backbone Events which are callable in the View?
what is the approach to create custom Backbone Events which are callable in the View?
I feel as if your problem is not a problem,because backbone.view default has been to support the events.
you can write code like what you want to:
//This is the right thing to do
SomeView = Backbone.View.extend({
events: {
"keydown input#some-field": "validate" // custom event
, "change input#some-field": "doSomethingElse" // predefined backbone event
},
validate: function(attr){
// validation
}
});
Reference here:
http://backbonejs.org/docs/todos.html#section-22
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EDIT :
you can see here:
http://backbonejs.org/docs/backbone.html#section-156
The most critical sentence is:
this.$el.delegate(selector, eventName, method);
because backbone's events is jquery's delegate(http://api.jquery.com/delegate/),so jQuery's delegate to support the event, backbone are available.
I'm not sure I'm understanding what the problem is. Your second example is definitely how I would and have gone about setting up event handlers in Backbone Views. Backbone's validate method only exists in the model and is called automatically before the models set and save are called. It is left undefined as default. If you are validating in the view though your way should work. But i believe event handling functions are only passed the event. so it should probably be
validate: function (event) {
// do Something here
}
also you should keep in mind that backbone event delegation takes place in the el. so you will need to either set it manually or render into it in order for event delegation to to work

Prevent single attribute from firing this.bind("change")

In Backbone.js, I have a model I am binding a change event to, but I want to prevent this from happening on specific attribute changes. For example, I want it to fire for every single time model.set() is called, except when calling model.set({arbitraryName: value}).
Here's what I have:
this.bind("change", function() {
this.update();
});
But I have no clue how to determine what is being set--any ideas?
EDIT
It looks like I can call
model.set({arbitraryName: value}, {silent: true})
to prevent the change event from firing (which works for what I need), but what if I have something bound like:
this.bind("change:arbitraryName", functionName)
You can consider using hasChanged in the event handler?
var self = this;
this.bind("change", function() {
if(!self.hasChanged("someAttribute")){
self.update();
}
});
I'm not sure I understand your question completely. Please notice the difference of the above, and the below.
this.bind("change:someAttribute", function(){
self.update();
});
The first one will fire update on any change where someAttribute remains constant. The second one will fire update on any change to someAttribute.
Hope this helps.

jQuery temporary unbinding events

Maybe I'm totally missing something about even handling in jQuery, but here's my problem.
Let's assume there are some event binding, like
$(element).bind("mousemove", somefunc);
Now, I'd like to introduce a new mousemove binding that doesn't override the previous one, but temporarily exclude (unbind) it. In other words, when I bind my function, I must be sure that no other functions will ever execute for that event, until I restore them.
I'm looking for something like:
$(element).bind("mousemove", somefunc);
// Somefunc is used regularly
var savedBinding = $(element).getCurrentBinding("mousemove");
$(element).unbind("mousemove").bind("mousemove", myfunc);
// Use myfunc instead
$(element).unbind("mousemove", myfunc).bind("mousemove", savedBindings);
Of course, the somefunc is not under my control, or this would be useless :)
Is my understanding that is possible to bind multiple functions to the same event, and that the execution of those functions can't be pre-determined.
I'm aware of stopping event propagation and immediate event propagation, but I'm thinking that they are useless in my case, as the execution order can't be determined (but maybe I'm getting these wrong).
How can I do that?
EDIT: I need to highlight this: I need that the previously installed handler (somefunc) isn't executed. I am NOT defining that handler, it may be or may be not present, but its installed by a third-party user.
EDIT2: Ok, this is not feasible right now, I think I'm needing the eventListenerList, which is not implemented in most browsers yet. http://www.w3.org/TR/2002/WD-DOM-Level-3-Events-20020208/changes.html
Another way could be to use custom events, something along these lines:
var flag = 0;
$(element).bind("mousemove", function() {
if(flag) {
$(this).trigger("supermousemove");
} else {
$(this).trigger("magicmousemove");
}
}).bind("supermousemove", function() {
// do something super
}).bind("magicmousemove", function() {
// do something magical
});
$("#foo").click(function() {
flag = flag == 1 ? 0 : 1; // simple switch
});
Highly annoying demo here: http://jsfiddle.net/SkFvW/
Good if the event is bound to multiple elements:
$('.foo').click(function() {
if ( ! $(this).hasClass('flag')) {
do something
}
});
(add class 'flag' to sort of unbind, add it to 'bind')

Categories

Resources