5

I would like to call a function when a "load" event is triggered:

events: {
    "load #eventPicture" : "_resizeHeaderPic"
}

I don't want to do something like this.$("#eventPicture").on("load", _resizeHeaderPic); because I have a lot of views (it's a Single Page App) and I could go back to show another view before the image was loaded. So, if I then come back to this view I would have two listener for that "load" event. Right? By putting everything in my events hash, I can undelegate properly. But it seems that "load #eventPicture" does not work. Any suggestion?

Bertuz
  • 2,390
  • 3
  • 25
  • 50

1 Answers1

4

You cannot track load event from Backbone events because this event fires only on image instance and doesn't bubble. So Backbone.View's $el cannot track it.

jQuery callback on image load (even when the image is cached)

UPDATE

I would suggest to use another concept (JSFiddle). This is best practice:

var LayoutView = Backbone.View.extend({
    el : '[data-container]',
    show : function (view) {
        // remove current view
        this.$view && this.$view.remove();
        // save link to the new view
        this.$view = view;
        // render new view and append to our element
        this.$el.html(this.$view.render().el);
    }
});

var ImageView = Backbone.View.extend({
    template : _.template('<img src="https://fbcdn-sphotos-g-a.akamaihd.net/hphotos-ak-prn2/1375054_4823566966612_1010607077_n.jpg"/>'),
    render : function () {
        this.$el.html(this.template());
        this.$('img').on('load', _.bind(this.onLoad, this));
        return this;
    },
    onLoad : function () {
        console.log('onLoad');
    }
});

var OtherView = Backbone.View.extend({
    template : _.template('lalala'),
    render : function () {
        this.$el.html(this.template());
        return this;
    }
});

var Router = Backbone.Router.extend({
    routes : {
        'other' : 'other',
        '*any' : 'image'
    },
    initialize : function (options) {
        this.layout = new LayoutView();
    },
    other : function () {
        this.layout.show(new OtherView());
    },
    image : function () {
        this.layout.show(new ImageView());
    }
});

new Router();
Backbone.history.start();
Community
  • 1
  • 1
Vitalii Petrychuk
  • 14,035
  • 8
  • 51
  • 55
  • Mmmm I see. The only solution I've found is overriding the `remove` function of the View and placing a `this.$("#muse-eventPicture").off("load");`. Do you think is it the neatest solution possible? Keep in mind I was already overriding `remove` for other purposes – Bertuz Oct 12 '13 at 17:29
  • You don't need to off `load` event. `remove` method removes the whole view element from the DOM with all its children and events. – Vitalii Petrychuk Oct 12 '13 at 17:38
  • The fact is that I share the same `div` the `view` has as `$el` with other `views`. Only a view per time is shown of course, and when a view is rendered it takes place of the other. But the "root" `div` is never removed. This means that the previous listeners could be still listening the event (I've had cases of duplicate listeners, in other words the listeners of previous view instances were still listening to the DOM events). That's why I need to remove what I listen to – Bertuz Oct 12 '13 at 17:52
  • 1
    I have updated an answer and suggest to follow it. Or just use `off` like you described above. – Vitalii Petrychuk Oct 12 '13 at 18:18