Problem:
I'm trying to attach a resize event to the window from a view using the new listenTo() method in Backbone.js. The event seems to bind to the window, however, when the window is actually resied the following error is thrown:
Uncaught TypeError: Object [object Object] has no method 'apply' jquery.js:2 p.event.dispatch jquery.js:2 p.event.add.g.handle.h
Here is the code that attaches the event to the view:
this.listenTo($(window),"resize", this.resizeContext, this));
Here is the resizeContext function:
  resizeContext: function(event) {
            console.log("resizing context for "+this.id);
            this.setHeight();
            // trigger resize event (use event bus)
            this.options.vent.trigger("resize", event);
        }
Note: using the standard $(window).on("resize",this.resizeContext) attaches the event and runs as it should.  I am trying to take advantage of the new stopListening() feature that is added to view.remove();
The new listenTo and stopListening are methods of the Backbone.Events mixin, and they can only be used to listen to Backbone events which are triggered with .trigger, such as the built-in collection:add, or model:change events. 
That means that you won't be able to utilize the stopListening functionality for DOM events such as window:resize.
Consider overriding the View.removemethod instead.
var SomeView = Backbone.View.extend({
  initialize:function() {
    $(window).on("resize",this.resizeContext)
  },
  remove: function() {
    $(window).off("resize",this.resizeContext);
    //call the superclass remove method
    Backbone.View.prototype.remove.apply(this, arguments);
  }
});
                        If you want to keep using listenTo you might want to use following one off wrapper for DOM elements:
/**
 * Use Backbone Events listenTo/stopListening with any DOM element
 *
 * @param {DOM Element}
 * @return {Backbone Events style object}
 **/
function asEvents(el) {
    var args;
    return {
        on: function(event, handler) {
            if (args) throw new Error("this is one off wrapper");
            el.addEventListener(event, handler, false);
            args = [event, handler];
        },
        off: function() {
            el.removeEventListener.apply(el, args);
        }
    };
}
Example:
view.listenTo(asEvents(window), "resize", handler);
and the listener will be remove automatically on view.remove() or view.stoplistening()
Here's more complex implementation for multiple event listeners https://gist.github.com/epeli/5927950
In my code, I need to do .debounce((this.resizeContext).bind(this)).
Which makes it harder to be turned off. As a dirty solution, I just turn off all 'resize' listener when remove the view. I guess in the new view, if there is any resize listener, it will be turned on again.
remove: function() {
    $(window).off("resize");
    //call the superclass remove method
    Backbone.View.prototype.remove.apply(this, arguments);
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With