diff --git a/dist/recline.dataset.js b/dist/recline.dataset.js
index 3ca6fd41..bd311509 100644
--- a/dist/recline.dataset.js
+++ b/dist/recline.dataset.js
@@ -3,9 +3,10 @@ this.recline = this.recline || {};
this.recline.Model = this.recline.Model || {};
(function(my) {
+ "use strict";
// use either jQuery or Underscore Deferred depending on what is available
-var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## Dataset
my.Dataset = Backbone.Model.extend({
@@ -298,7 +299,7 @@ my.Record = Backbone.Model.extend({
//
// NB: if field is undefined a default '' value will be returned
getFieldValue: function(field) {
- val = this.getFieldValueUnrendered(field);
+ var val = this.getFieldValueUnrendered(field);
if (field && !_.isUndefined(field.renderer)) {
val = field.renderer(val, field, this.toJSON());
}
@@ -588,10 +589,11 @@ this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.Memory = this.recline.Backend.Memory || {};
(function(my) {
+ "use strict";
my.__type__ = 'memory';
// private data - use either jQuery or Underscore Deferred depending on what is available
- var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+ var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## Data Wrapper
//
@@ -693,7 +695,7 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
'float': function (e) { return parseFloat(e, 10); },
number: function (e) { return parseFloat(e, 10); },
string : function (e) { return e.toString() },
- date : function (e) { return new Date(e).valueOf() },
+ date : function (e) { return moment(e).valueOf() },
datetime : function (e) { return new Date(e).valueOf() }
};
var keyedFields = {};
diff --git a/dist/recline.js b/dist/recline.js
index 9df9cacc..87af5a40 100644
--- a/dist/recline.js
+++ b/dist/recline.js
@@ -4,10 +4,11 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {};
// Note that provision of jQuery is optional (it is **only** needed if you use fetch on a remote file)
(function(my) {
+ "use strict";
my.__type__ = 'csv';
// use either jQuery or Underscore Deferred depending on what is available
- var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+ var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## fetch
//
@@ -295,6 +296,7 @@ this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.DataProxy = this.recline.Backend.DataProxy || {};
(function(my) {
+ "use strict";
my.__type__ = 'dataproxy';
// URL for the dataproxy
my.dataproxy_url = '//jsonpdataproxy.appspot.com';
@@ -304,7 +306,7 @@ this.recline.Backend.DataProxy = this.recline.Backend.DataProxy || {};
// use either jQuery or Underscore Deferred depending on what is available
- var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+ var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## load
//
@@ -370,10 +372,11 @@ this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
(function($, my) {
+ "use strict";
my.__type__ = 'elasticsearch';
// use either jQuery or Underscore Deferred depending on what is available
- var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+ var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## ElasticSearch Wrapper
//
@@ -567,8 +570,8 @@ this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
fields: fieldData
});
})
- .fail(function(arguments) {
- dfd.reject(arguments);
+ .fail(function(args) {
+ dfd.reject(args);
});
return dfd.promise();
};
@@ -655,10 +658,11 @@ this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.GDocs = this.recline.Backend.GDocs || {};
(function(my) {
+ "use strict";
my.__type__ = 'gdocs';
// use either jQuery or Underscore Deferred depending on what is available
- var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+ var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## Google spreadsheet backend
//
@@ -822,10 +826,11 @@ this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.Memory = this.recline.Backend.Memory || {};
(function(my) {
+ "use strict";
my.__type__ = 'memory';
// private data - use either jQuery or Underscore Deferred depending on what is available
- var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+ var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## Data Wrapper
//
@@ -927,7 +932,7 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
'float': function (e) { return parseFloat(e, 10); },
number: function (e) { return parseFloat(e, 10); },
string : function (e) { return e.toString() },
- date : function (e) { return new Date(e).valueOf() },
+ date : function (e) { return moment(e).valueOf() },
datetime : function (e) { return new Date(e).valueOf() }
};
var keyedFields = {};
@@ -1123,9 +1128,10 @@ this.recline = this.recline || {};
this.recline.Model = this.recline.Model || {};
(function(my) {
+ "use strict";
// use either jQuery or Underscore Deferred depending on what is available
-var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
+var Deferred = _.isUndefined(window.jQuery) ? _.Deferred : jQuery.Deferred;
// ## Dataset
my.Dataset = Backbone.Model.extend({
@@ -1418,7 +1424,7 @@ my.Record = Backbone.Model.extend({
//
// NB: if field is undefined a default '' value will be returned
getFieldValue: function(field) {
- val = this.getFieldValueUnrendered(field);
+ var val = this.getFieldValueUnrendered(field);
if (field && !_.isUndefined(field.renderer)) {
val = field.renderer(val, field, this.toJSON());
}
@@ -1709,7 +1715,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
-
+ "use strict";
// ## Graph view for a Dataset using Flot graphing library.
//
// Initialization arguments (in a hash in first parameter):
@@ -1743,14 +1749,11 @@ my.Flot = Backbone.View.extend({
var self = this;
this.graphColors = ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"];
- this.el = $(this.el);
_.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
@@ -1765,29 +1768,34 @@ 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();
});
- this.elSidebar = this.editor.el;
+ this.elSidebar = this.editor.$el;
},
render: function() {
var self = this;
var tmplData = this.model.toTemplateJSON();
var htmls = Mustache.render(this.template, tmplData);
- $(this.el).html(htmls);
- this.$graph = this.el.find('.panel.graph');
+ this.$el.html(htmls);
+ this.$graph = this.$el.find('.panel.graph');
this.$graph.on("plothover", this._toolTip);
return this;
},
+ remove: function () {
+ this.editor.remove();
+ Backbone.View.prototype.remove.apply(this, arguments);
+ },
+
redraw: function() {
// There are issues generating a Flot graph if either:
// * The relevant div that graph attaches to his hidden at the moment of creating the plot -- Flot will complain with
// Uncaught Invalid dimensions for plot, width = 0, height = 0
// * There is no data for the plot -- either same error or may have issues later with errors like 'non-existent node-value'
- var areWeVisible = !jQuery.expr.filters.hidden(this.el[0]);
+ var areWeVisible = !jQuery.expr.filters.hidden(this.el);
if ((!areWeVisible || this.model.records.length === 0)) {
this.needToRedraw = true;
return;
@@ -2108,10 +2116,8 @@ my.FlotControls = Backbone.View.extend({
initialize: function(options) {
var self = this;
- this.el = $(this.el);
_.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();
},
@@ -2120,7 +2126,7 @@ my.FlotControls = Backbone.View.extend({
var self = this;
var tmplData = this.model.toTemplateJSON();
var htmls = Mustache.render(this.template, tmplData);
- this.el.html(htmls);
+ this.$el.html(htmls);
// set up editor from state
if (this.state.get('graphType')) {
@@ -2144,7 +2150,7 @@ my.FlotControls = Backbone.View.extend({
// Private: Helper function to select an option from a select list
//
_selectOption: function(id,value){
- var options = this.el.find(id + ' select > option');
+ var options = this.$el.find(id + ' select > option');
if (options) {
options.each(function(opt){
if (this.value == value) {
@@ -2156,16 +2162,16 @@ my.FlotControls = Backbone.View.extend({
},
onEditorSubmit: function(e) {
- var select = this.el.find('.editor-group select');
+ var select = this.$el.find('.editor-group select');
var $editor = this;
- var $series = this.el.find('.editor-series select');
+ var $series = this.$el.find('.editor-series select');
var series = $series.map(function () {
return $(this).val();
});
var updatedState = {
series: $.makeArray(series),
- group: this.el.find('.editor-group select').val(),
- graphType: this.el.find('.editor-type select').val()
+ group: this.$el.find('.editor-group select').val(),
+ graphType: this.$el.find('.editor-type select').val()
};
this.state.set(updatedState);
},
@@ -2182,7 +2188,7 @@ my.FlotControls = Backbone.View.extend({
}, this.model.toTemplateJSON());
var htmls = Mustache.render(this.templateSeriesEditor, data);
- this.el.find('.editor-series-group').append(htmls);
+ this.$el.find('.editor-series-group').append(htmls);
return this;
},
@@ -2213,6 +2219,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
// ## (Data) Grid Dataset View
//
// Provides a tabular view on a Dataset.
@@ -2224,11 +2231,8 @@ my.Grid = Backbone.View.extend({
initialize: function(modelEtc) {
var self = this;
- this.el = $(this.el);
_.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: []
@@ -2268,7 +2272,7 @@ my.Grid = Backbone.View.extend({
onHorizontalScroll: function(e) {
var currentScroll = $(e.target).scrollLeft();
- this.el.find('.recline-grid thead tr').scrollLeft(currentScroll);
+ this.$el.find('.recline-grid thead tr').scrollLeft(currentScroll);
},
// ======================================================
@@ -2296,7 +2300,7 @@ my.Grid = Backbone.View.extend({
var modelData = this.model.toJSON();
modelData.notEmpty = ( this.fields.length > 0 );
// TODO: move this sort of thing into a toTemplateJSON method on Dataset?
- modelData.fields = _.map(this.fields, function(field) {
+ modelData.fields = this.fields.map(function(field) {
return field.toJSON();
});
// last header width = scroll bar - border (2px) */
@@ -2305,17 +2309,18 @@ my.Grid = Backbone.View.extend({
},
render: function() {
var self = this;
- this.fields = this.model.fields.filter(function(field) {
+ this.fields = new recline.Model.FieldList(this.model.fields.filter(function(field) {
return _.indexOf(self.state.get('hiddenFields'), field.id) == -1;
- });
+ }));
+
this.scrollbarDimensions = this.scrollbarDimensions || this._scrollbarSize(); // skip measurement if already have dimensions
var numFields = this.fields.length;
// compute field widths (-20 for first menu col + 10px for padding on each col and finally 16px for the scrollbar)
- var fullWidth = self.el.width() - 20 - 10 * numFields - this.scrollbarDimensions.width;
+ var fullWidth = self.$el.width() - 20 - 10 * numFields - this.scrollbarDimensions.width;
var width = parseInt(Math.max(50, fullWidth / numFields), 10);
// if columns extend outside viewport then remainder is 0
var remainder = Math.max(fullWidth - numFields * width,0);
- _.each(this.fields, function(field, idx) {
+ this.fields.each(function(field, idx) {
// add the remainder to the first field width so we make up full col
if (idx === 0) {
field.set({width: width+remainder});
@@ -2324,10 +2329,10 @@ my.Grid = Backbone.View.extend({
}
});
var htmls = Mustache.render(this.template, this.toTemplateJSON());
- this.el.html(htmls);
+ this.$el.html(htmls);
this.model.records.forEach(function(doc) {
var tr = $('
');
- self.el.find('tbody').append(tr);
+ self.$el.find('tbody').append(tr);
var newView = new my.GridRow({
model: doc,
el: tr,
@@ -2336,12 +2341,12 @@ my.Grid = Backbone.View.extend({
newView.render();
});
// hide extra header col if no scrollbar to avoid unsightly overhang
- var $tbody = this.el.find('tbody')[0];
+ var $tbody = this.$el.find('tbody')[0];
if ($tbody.scrollHeight <= $tbody.offsetHeight) {
- this.el.find('th.last-header').hide();
+ this.$el.find('th.last-header').hide();
}
- this.el.find('.recline-grid').toggleClass('no-hidden', (self.state.get('hiddenFields').length === 0));
- this.el.find('.recline-grid tbody').scroll(this.onHorizontalScroll);
+ this.$el.find('.recline-grid').toggleClass('no-hidden', (self.state.get('hiddenFields').length === 0));
+ this.$el.find('.recline-grid tbody').scroll(this.onHorizontalScroll);
return this;
},
@@ -2377,8 +2382,7 @@ my.GridRow = Backbone.View.extend({
initialize: function(initData) {
_.bindAll(this, 'render');
this._fields = initData.fields;
- this.el = $(this.el);
- this.model.bind('change', this.render);
+ this.listenTo(this.model, 'change', this.render);
},
template: ' \
@@ -2411,9 +2415,9 @@ my.GridRow = Backbone.View.extend({
},
render: function() {
- this.el.attr('data-id', this.model.id);
+ this.$el.attr('data-id', this.model.id);
var html = Mustache.render(this.template, this.toTemplateJSON());
- $(this.el).html(html);
+ this.$el.html(html);
return this;
},
@@ -2433,7 +2437,7 @@ my.GridRow = Backbone.View.extend({
',
onEditClick: function(e) {
- var editing = this.el.find('.data-table-cell-editor-editor');
+ var editing = this.$el.find('.data-table-cell-editor-editor');
if (editing.length > 0) {
editing.parents('.data-table-cell-value').html(editing.text()).siblings('.data-table-cell-edit').removeClass("hidden");
}
@@ -2479,7 +2483,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
-
+ "use strict";
// ## Map view for a Dataset using Leaflet mapping library.
//
// This view allows to plot gereferenced records on a map. The location
@@ -2526,7 +2530,6 @@ my.Map = Backbone.View.extend({
initialize: function(options) {
var self = this;
- this.el = $(this.el);
this.visible = true;
this.mapReady = false;
// this will be the Leaflet L.Map object (setup below)
@@ -2553,32 +2556,32 @@ 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;
+ this.elSidebar = this.menu.$el;
},
// ## Customization Functions
@@ -2598,7 +2601,7 @@ my.Map = Backbone.View.extend({
// }
infobox: function(record) {
var html = '';
- for (key in record.attributes){
+ for (var key in record.attributes){
if (!(this.state.get('geomField') && key == this.state.get('geomField'))){
html += '' + key + ': '+ record.attributes[key] + '
';
}
@@ -2647,10 +2650,9 @@ my.Map = Backbone.View.extend({
// Also sets up the editor fields and the map if necessary.
render: function() {
var self = this;
-
- htmls = Mustache.render(this.template, this.model.toTemplateJSON());
- $(this.el).html(htmls);
- this.$map = this.el.find('.panel.map');
+ var htmls = Mustache.render(this.template, this.model.toTemplateJSON());
+ this.$el.html(htmls);
+ this.$map = this.$el.find('.panel.map');
this.redraw();
return this;
},
@@ -2801,7 +2803,7 @@ my.Map = Backbone.View.extend({
if (!(docs instanceof Array)) docs = [docs];
_.each(docs,function(doc){
- for (key in self.features._layers){
+ for (var key in self.features._layers){
if (self.features._layers[key].feature.properties.cid == doc.cid){
self.features.removeLayer(self.features._layers[key]);
}
@@ -3008,7 +3010,6 @@ my.MapMenu = Backbone.View.extend({
Cluster markers \
\
\
- \
\
',
@@ -3022,11 +3023,10 @@ my.MapMenu = Backbone.View.extend({
initialize: function(options) {
var self = this;
- this.el = $(this.el);
_.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();
},
@@ -3035,28 +3035,28 @@ my.MapMenu = Backbone.View.extend({
// Also sets up the editor fields and the map if necessary.
render: function() {
var self = this;
- htmls = Mustache.render(this.template, this.model.toTemplateJSON());
- $(this.el).html(htmls);
+ var htmls = Mustache.render(this.template, this.model.toTemplateJSON());
+ this.$el.html(htmls);
if (this._geomReady() && this.model.fields.length){
if (this.state.get('geomField')){
this._selectOption('editor-geom-field',this.state.get('geomField'));
- this.el.find('#editor-field-type-geom').attr('checked','checked').change();
+ this.$el.find('#editor-field-type-geom').attr('checked','checked').change();
} else{
this._selectOption('editor-lon-field',this.state.get('lonField'));
this._selectOption('editor-lat-field',this.state.get('latField'));
- this.el.find('#editor-field-type-latlon').attr('checked','checked').change();
+ this.$el.find('#editor-field-type-latlon').attr('checked','checked').change();
}
}
if (this.state.get('autoZoom')) {
- this.el.find('#editor-auto-zoom').attr('checked', 'checked');
+ this.$el.find('#editor-auto-zoom').attr('checked', 'checked');
} else {
- this.el.find('#editor-auto-zoom').removeAttr('checked');
+ this.$el.find('#editor-auto-zoom').removeAttr('checked');
}
if (this.state.get('cluster')) {
- this.el.find('#editor-cluster').attr('checked', 'checked');
+ this.$el.find('#editor-cluster').attr('checked', 'checked');
} else {
- this.el.find('#editor-cluster').removeAttr('checked');
+ this.$el.find('#editor-cluster').removeAttr('checked');
}
return this;
},
@@ -3075,17 +3075,17 @@ my.MapMenu = Backbone.View.extend({
//
onEditorSubmit: function(e){
e.preventDefault();
- if (this.el.find('#editor-field-type-geom').attr('checked')){
+ if (this.$el.find('#editor-field-type-geom').attr('checked')){
this.state.set({
- geomField: this.el.find('.editor-geom-field > select > option:selected').val(),
+ geomField: this.$el.find('.editor-geom-field > select > option:selected').val(),
lonField: null,
latField: null
});
} else {
this.state.set({
geomField: null,
- lonField: this.el.find('.editor-lon-field > select > option:selected').val(),
- latField: this.el.find('.editor-lat-field > select > option:selected').val()
+ lonField: this.$el.find('.editor-lon-field > select > option:selected').val(),
+ latField: this.$el.find('.editor-lat-field > select > option:selected').val()
});
}
return false;
@@ -3096,11 +3096,11 @@ my.MapMenu = Backbone.View.extend({
//
onFieldTypeChange: function(e){
if (e.target.value == 'geom'){
- this.el.find('.editor-field-type-geom').show();
- this.el.find('.editor-field-type-latlon').hide();
+ this.$el.find('.editor-field-type-geom').show();
+ this.$el.find('.editor-field-type-latlon').hide();
} else {
- this.el.find('.editor-field-type-geom').hide();
- this.el.find('.editor-field-type-latlon').show();
+ this.$el.find('.editor-field-type-geom').hide();
+ this.$el.find('.editor-field-type-latlon').show();
}
},
@@ -3115,7 +3115,7 @@ my.MapMenu = Backbone.View.extend({
// Private: Helper function to select an option from a select list
//
_selectOption: function(id,value){
- var options = this.el.find('.' + id + ' > select > option');
+ var options = this.$el.find('.' + id + ' > select > option');
if (options){
options.each(function(opt){
if (this.value == value) {
@@ -3136,6 +3136,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
// ## MultiView
//
// Manage multiple views together along with query editor etc. Usage:
@@ -3260,7 +3261,6 @@ my.MultiView = Backbone.View.extend({
initialize: function(options) {
var self = this;
- this.el = $(this.el);
this._setupState(options.state);
// Hash of 'page' views (i.e. those for whole page) keyed by page name
@@ -3330,30 +3330,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
@@ -3366,7 +3366,7 @@ my.MultiView = Backbone.View.extend({
},
setReadOnly: function() {
- this.el.addClass('recline-read-only');
+ this.$el.addClass('recline-read-only');
},
render: function() {
@@ -3374,11 +3374,11 @@ my.MultiView = Backbone.View.extend({
tmplData.views = this.pageViews;
tmplData.sidebarViews = this.sidebarViews;
var template = Mustache.render(this.template, tmplData);
- $(this.el).html(template);
+ this.$el.html(template);
// now create and append other views
- var $dataViewContainer = this.el.find('.data-view-container');
- var $dataSidebar = this.el.find('.data-view-sidebar');
+ var $dataViewContainer = this.$el.find('.data-view-container');
+ var $dataSidebar = this.$el.find('.data-view-sidebar');
// the main views
_.each(this.pageViews, function(view, pageName) {
@@ -3390,25 +3390,37 @@ my.MultiView = Backbone.View.extend({
});
_.each(this.sidebarViews, function(view) {
- this['$'+view.id] = view.view.el;
+ this['$'+view.id] = view.view.$el;
$dataSidebar.append(view.view.el);
}, this);
- var pager = new recline.View.Pager({
+ this.pager = new recline.View.Pager({
model: this.model.queryState
});
- this.el.find('.recline-results-info').after(pager.el);
+ this.$el.find('.recline-results-info').after(this.pager.el);
- var queryEditor = new recline.View.QueryEditor({
+ this.queryEditor = new recline.View.QueryEditor({
model: this.model.queryState
});
- this.el.find('.query-editor-here').append(queryEditor.el);
+ this.$el.find('.query-editor-here').append(this.queryEditor.el);
},
+ remove: function () {
+ _.each(this.pageViews, function (view) {
+ view.view.remove();
+ });
+ _.each(this.sidebarViews, function (view) {
+ view.view.remove();
+ });
+ this.pager.remove();
+ this.queryEditor.remove();
+ Backbone.View.prototype.remove.apply(this, arguments);
+ },
+
// hide the sidebar if empty
_showHideSidebar: function() {
- var $dataSidebar = this.el.find('.data-view-sidebar');
+ var $dataSidebar = this.$el.find('.data-view-sidebar');
var visibleChildren = $dataSidebar.children().filter(function() {
return $(this).css("display") != "none";
}).length;
@@ -3421,19 +3433,19 @@ my.MultiView = Backbone.View.extend({
},
updateNav: function(pageName) {
- this.el.find('.navigation a').removeClass('active');
- var $el = this.el.find('.navigation a[data-view="' + pageName + '"]');
+ this.$el.find('.navigation a').removeClass('active');
+ var $el = this.$el.find('.navigation a[data-view="' + pageName + '"]');
$el.addClass('active');
// add/remove sidebars and hide inactive views
_.each(this.pageViews, function(view, idx) {
if (view.id === pageName) {
- view.view.el.show();
+ view.view.$el.show();
if (view.view.elSidebar) {
view.view.elSidebar.show();
}
} else {
- view.view.el.hide();
+ view.view.$el.hide();
if (view.view.elSidebar) {
view.view.elSidebar.hide();
}
@@ -3502,7 +3514,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) {
@@ -3510,7 +3522,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
@@ -3524,7 +3536,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);
});
});
@@ -3650,7 +3662,7 @@ my.parseQueryString = function(q) {
// Parse the query string out of the URL hash
my.parseHashQueryString = function() {
- q = my.parseHashUrl(window.location.hash).query;
+ var q = my.parseHashUrl(window.location.hash).query;
return my.parseQueryString(q);
};
@@ -3690,6 +3702,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
// ## SlickGrid Dataset View
//
// Provides a tabular view on a Dataset, based on SlickGrid.
@@ -3719,13 +3732,10 @@ this.recline.View = this.recline.View || {};
my.SlickGrid = Backbone.View.extend({
initialize: function(modelEtc) {
var self = this;
- this.el = $(this.el);
- 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);
+ this.$el.addClass('recline-slickgrid');
+ _.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: [],
@@ -3739,6 +3749,8 @@ my.SlickGrid = Backbone.View.extend({
);
this.state = new recline.Model.ObjectState(state);
+
+ this._slickHandler = new Slick.EventHandler();
},
events: {
@@ -3804,7 +3816,7 @@ my.SlickGrid = Backbone.View.extend({
});
// Restrict the visible columns
- var visibleColumns = columns.filter(function(column) {
+ var visibleColumns = _.filter(columns, function(column) {
return _.indexOf(self.state.get('hiddenColumns'), column.id) === -1;
});
@@ -3850,7 +3862,7 @@ my.SlickGrid = Backbone.View.extend({
this.getItem = function(index) {return rows[index];};
this.getItemMetadata = function(index) {return {};};
this.getModel = function(index) {return models[index];};
- this.getModelRow = function(m) {return models.indexOf(m);};
+ this.getModelRow = function(m) {return _.indexOf(models, m);};
this.updateItem = function(m,i) {
rows[i] = toRow(m);
models[i] = m;
@@ -3873,7 +3885,7 @@ my.SlickGrid = Backbone.View.extend({
this.grid.setSortColumn(column, sortAsc);
}
- this.grid.onSort.subscribe(function(e, args){
+ this._slickHandler.subscribe(this.grid.onSort, function(e, args){
var order = (args.sortAsc) ? 'asc':'desc';
var sort = [{
field: args.sortCol.field,
@@ -3882,7 +3894,7 @@ my.SlickGrid = Backbone.View.extend({
self.model.query({sort: sort});
});
- this.grid.onColumnsReordered.subscribe(function(e, args){
+ this._slickHandler.subscribe(this.grid.onColumnsReordered, function(e, args){
self.state.set({columnsOrder: _.pluck(self.grid.getColumns(),'id')});
});
@@ -3898,7 +3910,7 @@ my.SlickGrid = Backbone.View.extend({
self.state.set({columnsWidth:columnsWidth});
});
- this.grid.onCellChange.subscribe(function (e, args) {
+ this._slickHandler.subscribe(this.grid.onCellChange, function (e, args) {
// We need to change the model associated value
//
var grid = args.grid;
@@ -3921,7 +3933,12 @@ my.SlickGrid = Backbone.View.extend({
}
return this;
- },
+ },
+
+ remove: function () {
+ this._slickHandler.unsubscribeAll();
+ Backbone.View.prototype.remove.apply(this, arguments);
+ },
show: function() {
// If the div is hidden, SlickGrid will calculate wrongly some
@@ -4067,6 +4084,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
// turn off unnecessary logging from VMM Timeline
if (typeof VMM !== 'undefined') {
VMM.debug = false;
@@ -4090,13 +4108,12 @@ my.Timeline = Backbone.View.extend({
initialize: function(options) {
var self = this;
- this.el = $(this.el);
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({
@@ -4113,7 +4130,7 @@ my.Timeline = Backbone.View.extend({
render: function() {
var tmplData = {};
var htmls = Mustache.render(this.template, tmplData);
- this.el.html(htmls);
+ this.$el.html(htmls);
// can only call _initTimeline once view in DOM as Timeline uses $
// internally to look up element
if ($(this.elementId).length > 0) {
@@ -4129,7 +4146,7 @@ my.Timeline = Backbone.View.extend({
},
_initTimeline: function() {
- var $timeline = this.el.find(this.elementId);
+ var $timeline = this.$el.find(this.elementId);
var data = this._timelineJSON();
this.timeline.init(data, this.elementId, this.state.get("timelineJSOptions"));
this._timelineIsInitialized = true
@@ -4197,14 +4214,14 @@ my.Timeline = Backbone.View.extend({
if (!date) {
return null;
}
- var out = date.trim();
+ var out = $.trim(date);
out = out.replace(/(\d)th/g, '$1');
out = out.replace(/(\d)st/g, '$1');
- out = out.trim() ? moment(out) : null;
- if (out.toDate() == 'Invalid Date') {
- return null;
- } else {
+ out = $.trim(out) ? moment(out) : null;
+ if (out && out.isValid()) {
return out.toDate();
+ } else {
+ return null;
}
},
@@ -4234,6 +4251,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
// ## FacetViewer
//
@@ -4271,9 +4289,8 @@ my.FacetViewer = Backbone.View.extend({
},
initialize: function(model) {
_.bindAll(this, 'render');
- this.el = $(this.el);
- 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() {
@@ -4290,17 +4307,17 @@ my.FacetViewer = Backbone.View.extend({
return facet;
});
var templated = Mustache.render(this.template, tmplData);
- this.el.html(templated);
+ this.$el.html(templated);
// are there actually any facets to show?
if (this.model.facets.length > 0) {
- this.el.show();
+ this.$el.show();
} else {
- this.el.hide();
+ this.$el.hide();
}
},
onHide: function(e) {
e.preventDefault();
- this.el.hide();
+ this.$el.hide();
},
onFacetFilter: function(e) {
e.preventDefault();
@@ -4338,7 +4355,8 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
-
+ "use strict";
+
my.Fields = Backbone.View.extend({
className: 'recline-fields-view',
template: ' \
@@ -4377,13 +4395,12 @@ my.Fields = Backbone.View.extend({
initialize: function(model) {
var self = this;
- this.el = $(this.el);
_.bindAll(this, 'render');
// 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);
@@ -4392,7 +4409,7 @@ my.Fields = Backbone.View.extend({
self.model.getFieldsSummary();
self.render();
});
- this.el.find('.collapse').collapse();
+ this.$el.find('.collapse').collapse();
this.render();
},
render: function() {
@@ -4406,7 +4423,7 @@ my.Fields = Backbone.View.extend({
tmplData.fields.push(out);
});
var templated = Mustache.render(this.template, tmplData);
- this.el.html(templated);
+ this.$el.html(templated);
}
});
@@ -4417,6 +4434,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
my.FilterEditor = Backbone.View.extend({
className: 'recline-filter-editor well',
@@ -4501,11 +4519,9 @@ my.FilterEditor = Backbone.View.extend({
'submit form.js-add': 'onAddFilter'
},
initialize: function() {
- this.el = $(this.el);
_.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() {
@@ -4521,13 +4537,13 @@ my.FilterEditor = Backbone.View.extend({
return Mustache.render(self.filterTemplates[this.type], this);
};
var out = Mustache.render(this.template, tmplData);
- this.el.html(out);
+ this.$el.html(out);
},
onAddFilterShow: function(e) {
e.preventDefault();
var $target = $(e.target);
$target.hide();
- this.el.find('form.js-add').show();
+ this.$el.find('form.js-add').show();
},
onAddFilter: function(e) {
e.preventDefault();
@@ -4587,6 +4603,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
my.Pager = Backbone.View.extend({
className: 'recline-pager',
@@ -4607,14 +4624,13 @@ my.Pager = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
- this.el = $(this.el);
- this.model.bind('change', this.render);
+ this.listenTo(this.model, 'change', this.render);
this.render();
},
onFormSubmit: function(e) {
e.preventDefault();
- var newFrom = parseInt(this.el.find('input[name="from"]').val());
- var newSize = parseInt(this.el.find('input[name="to"]').val()) - newFrom;
+ var newFrom = parseInt(this.$el.find('input[name="from"]').val());
+ var newSize = parseInt(this.$el.find('input[name="to"]').val()) - newFrom;
newFrom = Math.max(newFrom, 0);
newSize = Math.max(newSize, 1);
this.model.set({size: newSize, from: newFrom});
@@ -4635,7 +4651,7 @@ my.Pager = Backbone.View.extend({
var tmplData = this.model.toJSON();
tmplData.to = this.model.get('from') + this.model.get('size');
var templated = Mustache.render(this.template, tmplData);
- this.el.html(templated);
+ this.$el.html(templated);
}
});
@@ -4647,6 +4663,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
my.QueryEditor = Backbone.View.extend({
className: 'recline-query-editor',
@@ -4666,19 +4683,18 @@ my.QueryEditor = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
- this.el = $(this.el);
- this.model.bind('change', this.render);
+ this.listenTo(this.model, 'change', this.render);
this.render();
},
onFormSubmit: function(e) {
e.preventDefault();
- var query = this.el.find('.text-query input').val();
+ var query = this.$el.find('.text-query input').val();
this.model.set({q: query});
},
render: function() {
var tmplData = this.model.toJSON();
var templated = Mustache.render(this.template, tmplData);
- this.el.html(templated);
+ this.$el.html(templated);
}
});
@@ -4690,6 +4706,7 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
+ "use strict";
my.ValueFilter = Backbone.View.extend({
className: 'recline-filter-editor well',
@@ -4736,11 +4753,9 @@ my.ValueFilter = Backbone.View.extend({
'submit form.js-add': 'onAddFilter'
},
initialize: function() {
- this.el = $(this.el);
_.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() {
@@ -4756,7 +4771,7 @@ my.ValueFilter = Backbone.View.extend({
return Mustache.render(self.filterTemplates.term, this);
};
var out = Mustache.render(this.template, tmplData);
- this.el.html(out);
+ this.$el.html(out);
},
updateFilter: function(input) {
var self = this;
@@ -4770,7 +4785,7 @@ my.ValueFilter = Backbone.View.extend({
e.preventDefault();
var $target = $(e.target);
$target.hide();
- this.el.find('form.js-add').show();
+ this.$el.find('form.js-add').show();
},
onAddFilter: function(e) {
e.preventDefault();