machineghost
machineghost

Reputation: 35766

"Load" event in "events" property of Backbone View

Normally any event I can listen for in jQuery I can also listen for in Backbone. In other words, if I have:

var MyView = Backbone.View.extend();
var view = new MyView();
view.$el.html('<button>');
var onClick = function() {
    alert('woot!');
};

and I want to trigger onClick when the button is clicked, I could do:

$('button').on('click', onClick);

but because I'm using Backbone I'd instead do:

var MyView = Backbone.View.extend({
    events: {click: onClick}
});

However, that doesn't work with the load event of iframes, so if I have:

view.$el.html('<iframe src="www.stackoverflow.com"></iframe>');
var onLoad = function() {
    alert('woot!');
};

I can do:

$('iframe').on('load', onLoad);

but I can't do:

events: {load: onLoad}

My question is two-part: 1) why doesn't this work, and 2) is there any way to work around it, but still use Backbone's events instead of raw JQuery?

Upvotes: 4

Views: 7777

Answers (1)

mu is too short
mu is too short

Reputation: 434845

The events in events are attached using delegateEvents and that uses the delegation form of jQuery's on. But on delegation only works with events that bubble:

In all browsers, the load, scroll, and error events (e.g., on an <img> element) do not bubble. [...] Such events are not supported for use with delegation, but they can be used when the event handler is directly attached to the element generating the event.

So a load event in the events object won't do anything for you because load doesn't bubble up the DOM so it doesn't work with event delegation.

You're left with doing it manually (probably using this.$('iframe').on to properly isolate it to iframes inside your view's el) or using a separate view for the <iframe>. The latter will work because if you don't include a selector in events:

events: {
    load: 'handler'
}

then the event is bound directly to the view's el. If you have a view like this:

var V = Backbone.View.extend({
    tagName: 'iframe',
    attributes: {
        src: 'http://example.com'
    },
    events: {
        load: 'loaded'
    },
    loaded: function() {
        // This should get called.
    }
});

then the el will be <iframe src="http://example.com"></iframe> and the load event will be bound directly to that <iframe>. This may or may not work depending on what exactly you need the event handler to do.

Upvotes: 5

Related Questions