Skip to content

Commit 904d56a

Browse files
committed
[Time Conductor] #933 Clean up time conductor listeners on scope destruction
1 parent 11e0603 commit 904d56a

File tree

5 files changed

+50
-23
lines changed

5 files changed

+50
-23
lines changed

platform/features/conductor-v2/compatibility/src/ConductorRepresenter.js

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ define(
8585
ConductorRepresenter.prototype.destroy = function destroy() {
8686
this.conductor.off("bounds", this.boundsListener);
8787
this.conductor.off("timeSystem", this.timeSystemListener);
88+
this.conductor.off("follow", this.followListener);
8889
};
8990

9091
return ConductorRepresenter;

platform/features/conductor-v2/conductor/src/ui/MctConductorAxis.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,20 @@ define(
4343
this.xScale = undefined;
4444
this.xAxis = undefined;
4545
this.axisElement = undefined;
46-
this.setScale = this.setScale.bind(this);
47-
this.changeTimeSystem = this.changeTimeSystem.bind(this);
4846

4947
// Angular Directive interface
5048
this.link = this.link.bind(this);
5149
this.restrict = "E";
5250
this.template =
5351
"<div class=\"l-axis-holder\" mct-resize=\"resize()\"></div>";
5452
this.priority = 1000;
53+
54+
//Bind all class functions to 'this'
55+
Object.keys(MCTConductorAxis.prototype).filter(function (key) {
56+
return typeof MCTConductorAxis.prototype[key] === 'function';
57+
}).forEach(function (key) {
58+
this[key] = this[key].bind(this);
59+
}.bind(this));
5560
}
5661

5762
MCTConductorAxis.prototype.setScale = function () {
@@ -99,6 +104,11 @@ define(
99104
}
100105
};
101106

107+
MCTConductorAxis.prototype.destroy = function () {
108+
this.conductor.off('timeSystem', this.changeTimeSystem);
109+
this.conductor.off('bounds', this.setScale);
110+
};
111+
102112
MCTConductorAxis.prototype.link = function (scope, element) {
103113
var conductor = this.conductor;
104114
this.target = element[0].firstChild;
@@ -121,6 +131,8 @@ define(
121131
//On conductor bounds changes, redraw ticks
122132
conductor.on('bounds', this.setScale);
123133

134+
scope.$on("$destroy", this.destroy);
135+
124136
if (conductor.timeSystem() !== undefined) {
125137
this.changeTimeSystem(conductor.timeSystem());
126138
this.setScale();

platform/features/conductor-v2/conductor/src/ui/MctConductorAxisSpec.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
3232
d3;
3333

3434
beforeEach(function () {
35-
mockScope = {};
35+
mockScope = jasmine.createSpyObj("scope", [
36+
"$on"
37+
]);
3638

3739
//Add some HTML elements
3840
mockTarget = {
@@ -49,7 +51,8 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
4951
mockConductor = jasmine.createSpyObj("conductor", [
5052
"timeSystem",
5153
"bounds",
52-
"on"
54+
"on",
55+
"off"
5356
]);
5457
mockConductor.bounds.andReturn(mockBounds);
5558

@@ -85,6 +88,13 @@ define(['./MctConductorAxis'], function (MctConductorAxis) {
8588
expect(mockConductor.on).toHaveBeenCalledWith("bounds", directive.setScale);
8689
});
8790

91+
it("on scope destruction, deregisters listeners", function () {
92+
expect(mockScope.$on).toHaveBeenCalledWith("$destroy", directive.destroy);
93+
directive.destroy();
94+
expect(mockConductor.off).toHaveBeenCalledWith("timeSystem", directive.changeTimeSystem);
95+
expect(mockConductor.off).toHaveBeenCalledWith("bounds", directive.setScale);
96+
});
97+
8898
describe("when the time system changes", function () {
8999
var mockTimeSystem;
90100
var mockFormat;

platform/features/conductor-v2/conductor/src/ui/TimeConductorController.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@ define(
5353
this.initializeScope();
5454

5555
this.conductor.on('bounds', this.setFormFromBounds);
56-
this.conductor.on('follow', function (follow) {
57-
$scope.followMode = follow;
58-
});
5956
this.conductor.on('timeSystem', this.changeTimeSystem);
6057

6158
// If no mode selected, select fixed as the default
@@ -100,6 +97,13 @@ define(
10097

10198
// Watch scope for selection of mode or time system by user
10299
this.$scope.$watch('modeModel.selectedKey', this.setMode);
100+
101+
this.$scope.$on('$destroy', this.destroy);
102+
};
103+
104+
TimeConductorController.prototype.destroy = function () {
105+
this.conductor.off('bounds', this.setFormFromBounds);
106+
this.conductor.off('timeSystem', this.changeTimeSystem);
103107
};
104108

105109
/**

platform/features/conductor-v2/conductor/src/ui/TimeConductorControllerSpec.js

+16-16
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ define(['./TimeConductorController'], function (TimeConductorController) {
3030
var controller;
3131

3232
beforeEach(function () {
33-
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
33+
mockScope = jasmine.createSpyObj("$scope", [
34+
"$watch",
35+
"$on"
36+
]);
3437
mockWindow = jasmine.createSpyObj("$window", ["requestAnimationFrame"]);
3538
mockTimeConductor = jasmine.createSpyObj(
3639
"TimeConductor",
3740
[
3841
"bounds",
3942
"timeSystem",
40-
"on"
43+
"on",
44+
"off"
4145
]
4246
);
4347
mockTimeConductor.bounds.andReturn({start: undefined, end: undefined});
@@ -124,9 +128,16 @@ define(['./TimeConductorController'], function (TimeConductorController) {
124128
});
125129

126130
it("listens for changes to conductor state", function () {
127-
expect(mockTimeConductor.on).toHaveBeenCalledWith("timeSystem", jasmine.any(Function));
128-
expect(mockTimeConductor.on).toHaveBeenCalledWith("bounds", jasmine.any(Function));
129-
expect(mockTimeConductor.on).toHaveBeenCalledWith("follow", jasmine.any(Function));
131+
expect(mockTimeConductor.on).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem);
132+
expect(mockTimeConductor.on).toHaveBeenCalledWith("bounds", controller.setFormFromBounds);
133+
});
134+
135+
it("deregisters conductor listens when scope is destroyed", function () {
136+
expect(mockScope.$on).toHaveBeenCalledWith("$destroy", controller.destroy);
137+
138+
controller.destroy();
139+
expect(mockTimeConductor.off).toHaveBeenCalledWith("timeSystem", controller.changeTimeSystem);
140+
expect(mockTimeConductor.off).toHaveBeenCalledWith("bounds", controller.setFormFromBounds);
130141
});
131142

132143
it("when time system changes, sets time system on scope", function () {
@@ -164,17 +175,6 @@ define(['./TimeConductorController'], function (TimeConductorController) {
164175
expect(mockScope.boundsModel.start).toEqual(bounds.start);
165176
expect(mockScope.boundsModel.end).toEqual(bounds.end);
166177
});
167-
168-
it("responds to a change in 'follow' state of the time conductor", function () {
169-
var followListener = getListener("follow");
170-
expect(followListener).toBeDefined();
171-
172-
followListener(true);
173-
expect(mockScope.followMode).toEqual(true);
174-
175-
followListener(false);
176-
expect(mockScope.followMode).toEqual(false);
177-
});
178178
});
179179

180180
describe("when user makes changes from UI", function () {

0 commit comments

Comments
 (0)