Trigger event in Backbone.js and Saiku - javascript

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' });

Related

Marionette.js questions about events and how to correctly unbind them

Good day to all.
I'm writing an application using Marionette.js and recently I started noticing that moving from view to view and starting/stopping different modules memory consumption grows and not getting released. I started wondering whether I unbind my events correctly and whether I bind to them correctly as well.
So, I have the following cases
Modules
My application consists of sub-applications (modules). When I define a module I do some binding to global event aggregator. Something like this:
MyApplication.module(...) {
var api = { ... some functions here ... }
// Binding to events
MyApplication.vent.on('some:event', function() {...});
MyApplication.vent.on('some:other:event', function() {...});
}
I have checked the documentation and understand that "on" is not a very good choice, I should probably use "listenTo":
MyApplication.module(...) {
var api = { ... some functions here ... }
// Binding to events
this.listenTo(MyApplication.vent, 'some:event', function() {...});
this.listenTo(MyApplication.vent, 'some:other:event', function() {...});
}
But, here is the question, when module gets stopped, does it call "stopListening" or some other internal method that unbinds all the events I have bound in it? I checked the source code of the marionette's module and documentation but, if I understood correctly, when stop is called I need to take care of unbinding everything myself. Am I right?
Controllers
Can be initialized and closed. From the documentation I see that:
Each Controller instance has a built in close method that handles unbinding all of the events that are directly attached to the controller instance, as well as those that are bound using the EventBinder from the controller.
Does it mean that if do the following I correctly unbind all of the events I bound in the controller? I guess the answer is yes.
MyApplication.module(...) {
var controller = Marionette.Controller.extend({
...
// This will be unbinded as I understand?
this.listenTo(someObject, 'some:event', _.bind(function() {
// This will also be unbinded
this.listenTo(someOtherObject, 'some:event', function() {
// This won't be, because in this case this is not in a "controller"
// context but in a function's context which wasn't bound to "controler"
// context.
this.listenTo(some3rdObject, 'some:event', function() { ... });
});
}, this));
});
// Create controller when this sub-application gets initialized.
Contents.addInitializer(function () {
MyModule.Controller = new controller();
});
// Destroy controller and unbind all its event handlers.
Contents.addFinalizer(function () {
MyModule.Controller.close();
delete Contents.Controller;
});
}
So, with controllers I don't need to do anything as long as I use "listenTo", correct?
Views
In views, according to documentation, all gets unbinded when the view gets closed. And again, as long as I use
this.listenTo(..., 'some:event', function() {...});
I should be ok, correct?
To summarize... I only need to take care of unbinding in module's stop event, in all other cases it is taken care of by marionette's core as long as I don't use direct "on" and use "this.listenTo" instead.
Thank you all very much in advance for your answers.
Controllers and Views do their cleaning work correctly but Modules doesn't do it.
Here is more detailed info:
Controller
If you close controller it will unbind all events that are bonded using listenTo in context of controller. You can look in in controller source code.
View
According to Backbone.View source code remove method does stopListening. Also Marionette.View's close calls backbone's remove under the hood. Here is source code.
Module
I've checked Marionette.Module source code but there is no stopListening in stop method. So, Marionette.Module#stop does not do unbinding of events and you should do it manually in finalizer or in onStop, onBeforeStop handlers.
UPDATED: After Marionette.js v1.7.0 Marionette.Module calls stopListening on stop to unbind all events.

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

Can an Orbeon event in an XBL be dispatched from Javascript?

Orbeon version: Orbeon Forms 3.8.0.201005270113
I have the following code in a Javascript file. This code is executed, but it seems like the model in the XBL is not found.
ORBEON.xforms.Document.dispatchEvent("model-name", "event-name");
Here is the model in the XBL. There are several models in the XBL. I don't see any message, so it seems as though the model isn't found. I don't see any errors in the logs.
<xforms:model id="model-name" xxforms:external-events="event-name">
<xforms:action ev:event="event-name">
<xforms:message>Test</xforms:message>
</xforms:action>
</xforms:model>
Does anyone know if there is some trick to getting a dispatch to work from Javascript to XBL?
Thanks very much!
UPDATED:
Another thing that could be the problem (maybe?) is that calling the javascript from the XBL using instance(this) isn't working. I wonder if the instance of the class isn't tied to a component instance, therefore it can't find the model?
Here's the call to the javascript from the xbl that doesn't invoke the init method:
<xxforms:script>YAHOO.xbl.fr.myTest.instance(this).init();</xxforms:script>
Here's the call that does invoke the init() method:
<xxforms:script>YAHOO.xbl.fr.myTest.prototype.init();</xxforms:script>
Here's the javascript:
YAHOO.namespace("xbl.fr");
YAHOO.xbl.fr.myTest = function() {};
ORBEON.xforms.XBL.declareClass(YAHOO.xbl.fr.myTest, "xbl-fr-myTest");
YAHOO.xbl.fr.myTest.prototype = {
},
init: function() {
alert('test');
},
valueChanged: function() {
},
};
AFAIK you can't address the XBL-internal model directly from outside, because of its strong encapsulation.
Instead, you'll have to dispatch the event to the xbl component node. For example, if you want an instance of the fr:currency XBL to handle a certain event, you'll have to dispatch the event to that fr:currency element that's part of your XForm.
Inside the XBL, you can define xbl:handlers to act upon that event, triggering some JavaScript action or something else.

Listening and firing events with Javascript and maybe jQuery

In my JavaScript and Flex applications, users often perform actions that I want other JavaScript code on the page to listen for. For example, if someone adds a friend. I want my JavaScript app to then call something like triggerEvent("addedFriend", name);. Then any other code that was listening for the "addedFriend" event will get called along with the name.
Is there a built-in JavaScript mechanism for handling events? I'm ok with using jQuery for this too and I know jQuery makes extensive use of events. But with jQuery, it seems that its event mechanism is all based around elements. As I understand, you have to tie a custom event to an element. I guess I can do that to a dummy element, but my need has nothing to do with DOM elements on a webpage.
Should I just implement this event mechanism myself?
You have a few options:
jQuery does allow you to do this with objects not associated with the document. An example is provided below.
If you're not already using jQuery on your page, then adding it is probably overkill. There are other libraries designed for this. The pattern you are referring to is called PubSub or Publish/Subscribe.
Implement it yourself, as you've suggested, since this is not difficult if you're looking only for basic functionality.
jQuery example:
var a = {};
jQuery(a).bind("change", function () {
alert("I changed!");
});
jQuery(a).trigger("change");
I would implement such using MVVM pattern with knockjs library.
Just create an element, and use jquery events on it.
It can be just a global variable, doesn't even have to be connected to the DOM.
That way you accomplish your task easily and without any extra libs.
Isn't it possible to bind onchange events in addition to click events? For instance, if addFriend is called and modifies a list on the page, you could bind the change event to then invoke additional functionality.
$('#addFriendButton').click( function() {
// modify the #friendList list
});
$('#friendList').change( function() {
myOtherAction();
});
This is total Host independent, no need for jQuery or dom in this case!
function CustomEvents(){
//object holding eventhandlers
this.handlers_ = {};
}
//check if the event type does not exist, create it.
//then push new callback in array.
CustomEvents.prototype.addEventListner = function (type, callBack){
if (!this.handlers_[type]) this.handlers_[type] = [];
this.handlers_[type].push(callBack);
}
CustomEvents.prototype.triggerEvent = function (type){
//trigger all handlers attached to events
if (!this.handlers_[type]) return;
for (var i=0, handler; handler = this.handlers_[type][i]; i++)
{
//call handler function and supply all the original arguments of this function
//minus the first argument which is the type of the event itself
if (typeof handler === "function") handler.apply(this,arguments.slice(1));
}
}
//delete all handlers to an event
CustomEvents.prototype.purgeEventType = function(type){
return delete this.handlers_[type];
}
test:
var customEvents = new CustomEvents();
customEvents.addEventListner("event A", function(arg){alert('Event A with arguments' + arg);));
customEvents.triggerEvent("event A", "the args");
EDIT added arguments passing

How can i define my own event in jQuery?

How can i define my own event in jQuery?
Define and attach your own custom events with .bind():
// make myObject listen for myFancyEvent
$('#myobject').bind('myFancyEvent', function(){
alert('Yow!');
});
...then .trigger() them directly:
$('#myobject').trigger('myFancyEvent');
...or mixed in with other event handlers:
$('#myobject').click( function(){
doSomething();
$(this).trigger('myFancyEvent');
});
You shouldn't have trouble finding a lot of information on the subject. This article is a couple of years old, but still a good overview.
You can throw events like this:
$("#element").trigger("your.event", [ 'Pamela', 'Anderson' ] );
Note that extra parameters should be passed as an array.
How to listen for events:
$("#element").bind("your.event", function(event, firstName, lastName) {
// Callback
});
The "#element" selector can be substituted with document if the event isn't specific for a particular dom node.
jQuery documentation:
Bind
Trigger
Refer to this link.
Here are some code snippet from the article above.
You can trigger custom events on any DOM object of your choosing using jQuery. Just trigger it using the following code:
$("#myelement").trigger('fuelified');
You can subscribe to that event using either bind or live functions in jQuery:
$("#myelement").bind('fuelified',function(e){ ... });
$(".cool_elements").live('fuelified',function(e){ ... });
You can even pass additional data about the event when triggering it and reference it on the listeners end:
$("#myelement").trigger('fuelified',{ custom: false });
$("#myelement").bind('fuelified',function(e,data){ if(data.custom) ... });
The element the trigger has been called on, is available to listener’s callback function as the variable this.

Categories

Resources