Use listenTo() rather than bind() in the views so that the events get unbound upon removal.

This commit is contained in:
Dan Wilson 2013-05-14 12:43:22 +01:00
parent c80dabd31e
commit 5ef821c92a
12 changed files with 56 additions and 65 deletions

View File

@ -40,11 +40,9 @@ my.Flot = Backbone.View.extend({
_.bindAll(this, 'render', 'redraw', '_toolTip', '_xaxisLabel');
this.needToRedraw = false;
this.model.bind('change', this.render);
this.model.fields.bind('reset', this.render);
this.model.fields.bind('add', this.render);
this.model.records.bind('add', this.redraw);
this.model.records.bind('reset', this.redraw);
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model.fields, 'reset add', this.render);
this.listenTo(this.model.records, 'reset add', this.redraw);
var stateData = _.extend({
group: null,
// so that at least one series chooser box shows up
@ -59,7 +57,7 @@ my.Flot = Backbone.View.extend({
model: this.model,
state: this.state.toJSON()
});
this.editor.state.bind('change', function() {
this.listenTo(this.editor.state, 'change', function() {
self.state.set(self.editor.state.toJSON());
self.redraw();
});
@ -403,8 +401,7 @@ my.FlotControls = Backbone.View.extend({
initialize: function(options) {
var self = this;
_.bindAll(this, 'render');
this.model.fields.bind('reset', this.render);
this.model.fields.bind('add', this.render);
this.listenTo(this.model.fields, 'reset add', this.render);
this.state = new recline.Model.ObjectState(options.state);
this.render();
},

View File

@ -17,9 +17,7 @@ my.Grid = Backbone.View.extend({
initialize: function(modelEtc) {
var self = this;
_.bindAll(this, 'render', 'onHorizontalScroll');
this.model.records.bind('add', this.render);
this.model.records.bind('reset', this.render);
this.model.records.bind('remove', this.render);
this.listenTo(this.model.records, 'add reset remove', this.render);
this.tempState = {};
var state = _.extend({
hiddenFields: []
@ -168,7 +166,7 @@ my.GridRow = Backbone.View.extend({
initialize: function(initData) {
_.bindAll(this, 'render');
this._fields = initData.fields;
this.model.bind('change', this.render);
this.listenTo(this.model, 'change', this.render);
},
template: ' \

View File

@ -77,29 +77,29 @@ my.Map = Backbone.View.extend({
};
// Listen to changes in the fields
this.model.fields.bind('change', function() {
this.listenTo(this.model.fields, 'change', function() {
self._setupGeometryField();
self.render();
});
// Listen to changes in the records
this.model.records.bind('add', function(doc){self.redraw('add',doc);});
this.model.records.bind('change', function(doc){
this.listenTo(this.model.records, 'add', function(doc){self.redraw('add',doc);});
this.listenTo(this.model.records, 'change', function(doc){
self.redraw('remove',doc);
self.redraw('add',doc);
});
this.model.records.bind('remove', function(doc){self.redraw('remove',doc);});
this.model.records.bind('reset', function(){self.redraw('reset');});
this.listenTo(this.model.records, 'remove', function(doc){self.redraw('remove',doc);});
this.listenTo(this.model.records, 'reset', function(){self.redraw('reset');});
this.menu = new my.MapMenu({
model: this.model,
state: this.state.toJSON()
});
this.menu.state.bind('change', function() {
this.listenTo(this.menu.state, 'change', function() {
self.state.set(self.menu.state.toJSON());
self.redraw();
});
this.state.bind('change', function() {
this.listenTo(this.state, 'change', function() {
self.redraw();
});
this.elSidebar = this.menu.$el;
@ -546,9 +546,9 @@ my.MapMenu = Backbone.View.extend({
initialize: function(options) {
var self = this;
_.bindAll(this, 'render');
this.model.fields.bind('change', this.render);
this.listenTo(this.model.fields, 'change', this.render);
this.state = new recline.Model.ObjectState(options.state);
this.state.bind('change', this.render);
this.listenTo(this.state, 'change', this.render);
this.render();
},

View File

@ -199,30 +199,30 @@ my.MultiView = Backbone.View.extend({
}
this._showHideSidebar();
this.model.bind('query:start', function() {
self.notify({loader: true, persist: true});
});
this.model.bind('query:done', function() {
self.clearNotifications();
self.$el.find('.doc-count').text(self.model.recordCount || 'Unknown');
});
this.model.bind('query:fail', function(error) {
self.clearNotifications();
var msg = '';
if (typeof(error) == 'string') {
msg = error;
} else if (typeof(error) == 'object') {
if (error.title) {
msg = error.title + ': ';
}
if (error.message) {
msg += error.message;
}
} else {
msg = 'There was an error querying the backend';
this.listenTo(this.model, 'query:start', function() {
self.notify({loader: true, persist: true});
});
this.listenTo(this.model, 'query:done', function() {
self.clearNotifications();
self.$el.find('.doc-count').text(self.model.recordCount || 'Unknown');
});
this.listenTo(this.model, 'query:fail', function(error) {
self.clearNotifications();
var msg = '';
if (typeof(error) == 'string') {
msg = error;
} else if (typeof(error) == 'object') {
if (error.title) {
msg = error.title + ': ';
}
self.notify({message: msg, category: 'error', persist: true});
});
if (error.message) {
msg += error.message;
}
} else {
msg = 'There was an error querying the backend';
}
self.notify({message: msg, category: 'error', persist: true});
});
// retrieve basic data like fields etc
// note this.model and dataset returned are the same
@ -371,7 +371,7 @@ my.MultiView = Backbone.View.extend({
_bindStateChanges: function() {
var self = this;
// finally ensure we update our state object when state of sub-object changes so that state is always up to date
this.model.queryState.bind('change', function() {
this.listenTo(this.model.queryState, 'change', function() {
self.state.set({query: self.model.queryState.toJSON()});
});
_.each(this.pageViews, function(pageView) {
@ -379,7 +379,7 @@ my.MultiView = Backbone.View.extend({
var update = {};
update['view-' + pageView.id] = pageView.view.state.toJSON();
self.state.set(update);
pageView.view.state.bind('change', function() {
self.listenTo(pageView.view.state, 'change', function() {
var update = {};
update['view-' + pageView.id] = pageView.view.state.toJSON();
// had problems where change not being triggered for e.g. grid view so let's do it explicitly
@ -393,7 +393,7 @@ my.MultiView = Backbone.View.extend({
_bindFlashNotifications: function() {
var self = this;
_.each(this.pageViews, function(pageView) {
pageView.view.bind('recline:flash', function(flash) {
self.listenTo(pageView.view, 'recline:flash', function(flash) {
self.notify(flash);
});
});

View File

@ -35,11 +35,9 @@ my.SlickGrid = Backbone.View.extend({
initialize: function(modelEtc) {
var self = this;
this.$el.addClass('recline-slickgrid');
_.bindAll(this, 'render');
this.model.records.bind('add', this.render);
this.model.records.bind('reset', this.render);
this.model.records.bind('remove', this.render);
this.model.records.bind('change', this.onRecordChanged, this);
_.bindAll(this, 'render', 'onRecordChanged');
this.listenTo(this.model.records, 'add remove reset', this.render);
this.listenTo(this.model.records, 'change', this.onRecordChanged);
var state = _.extend({
hiddenColumns: [],

View File

@ -30,10 +30,10 @@ my.Timeline = Backbone.View.extend({
var self = this;
this.timeline = new VMM.Timeline();
this._timelineIsInitialized = false;
this.model.fields.bind('reset', function() {
this.listenTo(this.model.fields, 'reset', function() {
self._setupTemporalField();
});
this.model.records.bind('all', function() {
this.listenTo(this.model.records, 'all', function() {
self.reloadData();
});
var stateData = _.extend({

View File

@ -42,8 +42,8 @@ my.FacetViewer = Backbone.View.extend({
},
initialize: function(model) {
_.bindAll(this, 'render');
this.model.facets.bind('all', this.render);
this.model.fields.bind('all', this.render);
this.listenTo(this.model.facets, 'all', this.render);
this.listenTo(this.model.fields, 'all', this.render);
this.render();
},
render: function() {

View File

@ -65,7 +65,7 @@ my.Fields = Backbone.View.extend({
// TODO: this is quite restrictive in terms of when it is re-run
// e.g. a change in type will not trigger a re-run atm.
// being more liberal (e.g. binding to all) can lead to being called a lot (e.g. for change:width)
this.model.fields.bind('reset', function(action) {
this.listenTo(this.model.fields, 'reset', function(action) {
self.model.fields.each(function(field) {
field.facets.unbind('all', self.render);
field.facets.bind('all', self.render);

View File

@ -90,9 +90,8 @@ my.FilterEditor = Backbone.View.extend({
},
initialize: function() {
_.bindAll(this, 'render');
this.model.fields.bind('all', this.render);
this.model.queryState.bind('change', this.render);
this.model.queryState.bind('change:filters:new-blank', this.render);
this.listenTo(this.model.fields, 'all', this.render);
this.listenTo(this.model.queryState, 'change change:filters:new-blank', this.render);
this.render();
},
render: function() {

View File

@ -25,7 +25,7 @@ my.Pager = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.listenTo(this.model, 'change', this.render);
this.render();
},
onFormSubmit: function(e) {

View File

@ -24,7 +24,7 @@ my.QueryEditor = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.listenTo(this.model, 'change', this.render);
this.render();
},
onFormSubmit: function(e) {

View File

@ -52,9 +52,8 @@ my.ValueFilter = Backbone.View.extend({
},
initialize: function() {
_.bindAll(this, 'render');
this.model.fields.bind('all', this.render);
this.model.queryState.bind('change', this.render);
this.model.queryState.bind('change:filters:new-blank', this.render);
this.listenTo(this.model.fields, 'all', this.render);
this.listenTo(this.model.queryState, 'change change:filters:new-blank', this.render);
this.render();
},
render: function() {