Reputation: 462
I am attempting to extend existing jQuery widgets with Backbone events so they can publish Backbone events that can be listened to. My strategy is to proxy the event inside of the widget's native event callback method. For example, in the jQueryUI slider widget's change event, I want to trigger an event named "trigger." My conundrum is that this code works as intended:
$(function() {
var $slider = $("#slider");
_.extend($slider, Backbone.Events);
$slider.on("trigger", function(msg){
alert("triggered: " + msg)
});
$slider.slider({
change: function(event, ui) {
$slider.trigger("trigger", ui.value);
}
});
});
Which is 3/4 of the way to where I want to go, but I'd prefer to be able to just do something like this in the change event:
change: function(event, ui) {
$(this).trigger("trigger", ui.value);
}
...to completely encapsulate the widget and not worry about the actual singleton instance of the widget. My issue is that this second approach doesn't work and I was wondering if someone can explain to me why. In Firebug, both $(this) and $slider point to the same DOM element.
Upvotes: 3
Views: 3646
Reputation: 10678
You can use _.extend(jQuery.fn, Backbone.Events)
to add all the event methods to anything wrapped in $()
Have look at this jsFiddle. http://jsfiddle.net/Zct7D/
It works similarly to what you are looking for. The biggest shortfall I see is that you have to .trigger
on the same reference you bound (.on
) to.
In the example I use.
var derpDiv = $("#derp").on("....
derpDiv.trigger("update....
That works. But something like this does not appear to work.
$("#derp").on("update", function() {});
// somewhere else in the code
$("#derp").trigger("update", "Message");
But with some more tweaking it could be made to work.
Upvotes: 1
Reputation: 12431
The context of your change handler (this
) is the DOM element which triggered the event. This is the same DOM element you've already assigned to your $slider
variable.
I think you may be complicating things unnecessarily, though it might be that I don't fully understand what you're trying to do. However, you should be able to pick up events triggered by plug-ins on the child elements of a backbone view
using the built-in events hash. Try the following (and see fiddle here):
var SliderView = Backbone.View.extend({
// Set the view's el property to existing element in DOM
el: '#slider-view',
events: {
// jQuery UI slider triggers a slidechange event which we can subscribe
// to using the view's event object
'slidechange #slider': 'handleSliderChange'
},
render: function() {
// Worth caching a reference to the element in case we want to refer
// to it again elsewhere in the view - maybe to clean it up on exit
this.$slider = this.$el.find('#slider').slider({});
},
handleSliderChange: function(e, ui) {
// Our handler is invoked with the same ui parameter received
// by the slider's change handler.
console.log('Slider changed: ', e, ui.value);
}
});
// Create and render an instance of the view
new SliderView().render();
Upvotes: 2