Jake
Jake

Reputation: 462

Backbone.js events in jQuery

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

Answers (2)

Morgan ARR Allen
Morgan ARR Allen

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

net.uk.sweet
net.uk.sweet

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

Related Questions