From aba55f9fb03eb32498d6c731e5984bb827a6d591 Mon Sep 17 00:00:00 2001 From: Jason Morrison Date: Fri, 28 Sep 2012 14:18:28 +0100 Subject: [PATCH] CompositeView provides bindTo and invokes unbindFromAll in leave() --- .../backbone-support/composite_view.js | 14 +++++++++++++ spec/javascripts/composite_view_spec.js | 21 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lib/assets/javascripts/backbone-support/composite_view.js b/lib/assets/javascripts/backbone-support/composite_view.js index b924ce7..280f36b 100644 --- a/lib/assets/javascripts/backbone-support/composite_view.js +++ b/lib/assets/javascripts/backbone-support/composite_view.js @@ -6,11 +6,25 @@ Support.CompositeView = function(options) { _.extend(Support.CompositeView.prototype, Backbone.View.prototype, { leave: function() { this.unbind(); + this.unbindFromAll(); this.remove(); this._leaveChildren(); this._removeFromParent(); }, + bindTo: function(source, event, callback) { + source.bind(event, callback, this); + this.bindings = this.bindings || []; + this.bindings.push({ source: source, event: event, callback: callback }); + }, + + unbindFromAll: function() { + _.each(this.bindings, function(binding) { + binding.source.unbind(binding.event, binding.callback); + }); + this.bindings = []; + }, + renderChild: function(view) { view.render(); this.children.push(view); diff --git a/spec/javascripts/composite_view_spec.js b/spec/javascripts/composite_view_spec.js index 78af703..45b3903 100644 --- a/spec/javascripts/composite_view_spec.js +++ b/spec/javascripts/composite_view_spec.js @@ -163,5 +163,26 @@ describe("Support.CompositeView", function() { expect($("#test2").size()).toEqual(1); expect(view.children.size()).toEqual(1); }); + + it("removes any bindings that were bound via bindTo", function() { + var model1 = new Backbone.Model({}), + model2 = new Backbone.Model({}), + eventListener = sinon.spy(), + bindToView = new (Support.CompositeView.extend({ + initialize: function(options) { + this.bindTo(options.model1, 'change', eventListener); + this.bindTo(options.model2, 'change', eventListener); + } + }))({ + model1: model1, + model2: model2 + }); + + bindToView.leave(); + model1.trigger('change'); + model2.trigger('change'); + + expect(eventListener.called).toBeFalsy(); + }); }); });