From ac49a05587404b08f90eff28b7ee5a5a4b712505 Mon Sep 17 00:00:00 2001 From: Sam Saccone Date: Thu, 17 Apr 2014 19:23:47 -0400 Subject: [PATCH] Call stopListening on behaviors onClose --- spec/javascripts/behaviors.spec.js | 37 +++++++++++++++++++++++++++++- src/marionette.behavior.js | 5 ++++ src/marionette.behaviors.js | 13 ++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/spec/javascripts/behaviors.spec.js b/spec/javascripts/behaviors.spec.js index b858332628..f04832f0d2 100644 --- a/spec/javascripts/behaviors.spec.js +++ b/spec/javascripts/behaviors.spec.js @@ -338,10 +338,45 @@ describe("Behaviors", function(){ layout = new Layout(); layout.render(); layout.close(); - expect(onCloseSpy).toHaveBeenCalled(); + expect(onCloseSpy).toHaveBeenCalled(1); }); }); + describe("behavior instance events", function() { + var model, v, listenToSpy, onSpy; + + beforeEach(function() { + listenToSpy = new sinon.spy(); + onSpy = new sinon.spy(); + model = new Backbone.Model(); + + v = new (Marionette.View.extend({ + behaviors: { + cat: { + behaviorClass: (Marionette.Behavior.extend({ + initialize: function() { + this.listenTo(model, "change", listenToSpy); + this.on("wow", onSpy); + } + })) + } + } + })); + + v.close(); + }); + + it("shoud unbind listenTo on close", function() { + model.set("klingon", "dominion"); + expect(listenToSpy).not.toHaveBeenCalled(); + }); + + it("shoud still be bound to 'on' on close", function() { + v.triggerMethod("wow"); + expect(onSpy).toHaveBeenCalled(); + }); + }); + describe("behavior model events", function() { var modelSpy, collectionSpy, V, hold, m, testBehavior; beforeEach(function() { diff --git a/src/marionette.behavior.js b/src/marionette.behavior.js index 274bd89c16..edd1082322 100644 --- a/src/marionette.behavior.js +++ b/src/marionette.behavior.js @@ -31,6 +31,11 @@ Marionette.Behavior = (function(_, Backbone){ _.extend(Behavior.prototype, Backbone.Events, { initialize: function(){}, + // stopListening to behavior `onListen` events. + close: function() { + this.stopListening(); + }, + // Setup class level proxy for triggerMethod. triggerMethod: Marionette.triggerMethod }); diff --git a/src/marionette.behaviors.js b/src/marionette.behaviors.js index 172f8b3223..b53b7efdb3 100644 --- a/src/marionette.behaviors.js +++ b/src/marionette.behaviors.js @@ -22,7 +22,7 @@ Marionette.Behaviors = (function(Marionette, _) { 'delegateEvents', 'undelegateEvents', 'onShow', 'onClose', 'behaviorEvents', 'triggerMethod', - 'setElement' + 'setElement', 'close' ]); } @@ -38,6 +38,17 @@ Marionette.Behaviors = (function(Marionette, _) { }, this); }, + close: function(close, behaviors) { + var args = _.tail(arguments, 2); + close.apply(this, args); + + // Call close on each behavior after + // closing down the view. + // This unbinds event listeners + // that behaviors have registerd for. + _.invoke(behaviors, 'close', args); + }, + onShow: function(onShow, behaviors) { var args = _.tail(arguments, 2);