Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add a resize event to the window in a view using Backbone?

I have been trying to attach a handler to the resize event in one of my Backbone views. After doing some research I have discovered that you can only attach events to the view's element or its descendants.

This is an issue for me because the visual effect I am trying to achieve is not possible using pure CSS and requires some JS to set the dimensions of the content area element based on the window minus the header element.

If you are having trouble visualizing what I am trying to do, imagine a thin header and a content area which must occupy the remaining space with no CSS background trickery.

define(
    [
        'jQuery',
        'Underscore',
        'Backbone',
        'Mustache',
        'text!src/common/resource/html/base.html'
    ],
    function ($, _, Backbone, Mustache, baseTemplate) {
        var BaseView = Backbone.View.extend({

            el: $('body'),

            events: {
                'resize window': 'resize'
            },

            render: function () {
                var data = {};

                var render = Mustache.render(baseTemplate, data);

                this.$el.html(render);

                this.resize();
            },

            resize: function () {
                var windowHeight = $(window).height();

                var headerHeight = this.$el.find('#header').height();

                this.$el.find('#application').height( windowHeight - headerHeight );
            }
        });

        return new BaseView;
    }
);
like image 748
Eli Avatar asked Feb 02 '12 09:02

Eli


2 Answers

var BaseView = Backbone.View.extend({

    el: $('body'),

    initialize: function() {
        // bind to the namespaced (for easier unbinding) event
        // in jQuery 1.7+ use .on(...)
        $(window).bind("resize.app", _.bind(this.resize, this));
    },

    remove: function() {
        // unbind the namespaced event (to prevent accidentally unbinding some
        // other resize events from other code in your app
        // in jQuery 1.7+ use .off(...)
        $(window).unbind("resize.app");

        // don't forget to call the original remove() function
        Backbone.View.prototype.remove.call(this);
        // could also be written as:
        // this.constructor.__super__.remove.call(this);
    }, ...

Don't forget to call the remove() function on the view. Never just replace the view with another one.

like image 62
roberkules Avatar answered Sep 21 '22 14:09

roberkules


You might let window.onresize trigger a custom backbone.js event and then let Views or Models listen to that to have custom responses for various elements.

Case 1. A view listens to the window event directly.

window.onload = function() {

  _.extend(window, Backbone.Events);
  window.onresize = function() { window.trigger('resize') };

  ViewDirect = Backbone.View.extend({

    initialize: function() {
      this.listenTo(window, 'resize', _.debounce(this.print));
    },

    print: function() {
      console.log('Window width, heigth: %s, %s',
        window.innerWidth,
        window.innerHeight);
    },

  });

  var myview = new ViewDirect();

  }

Case 2. You may want to retain the window size without inspecting it each time you need it, hence you store the window size in a backbone model: in this case the window model listens to the window, while the view listens to the window model:

window.onload = function() {

  _.extend(window, Backbone.Events);
  window.onresize = function() { window.trigger('resize') };

  WindowModel = Backbone.Model.extend({

    initialize: function() {
      this.set_size();
      this.listenTo(window, 'resize', _.debounce(this.set_size));
    },

    set_size: function() {
      this.set({
        width: window.innerWidth,
        height: window.innerHeight
      });
    }

  });

  ViewWithModel = Backbone.View.extend({

    initialize: function() {
      this.listenTo(this.model, 'change', this.print);
      ...
    },

    print: function() {
      console.log('Window width, heigth: %s, %s',
        this.model.width,
        this.model.height);
    },
  });

  var window_model = new WindowModel();
  var myview = new ViewWithModel({model: window_model});

}
like image 33
mindrones Avatar answered Sep 18 '22 14:09

mindrones