diff --git a/src/view-flot-graph.js b/src/view-flot-graph.js index afb8f061..ed3142f9 100644 --- a/src/view-flot-graph.js +++ b/src/view-flot-graph.js @@ -7,10 +7,10 @@ this.recline.View = this.recline.View || {}; // ## Graph view for a Dataset using Flot graphing library. // -// Initialization arguments: +// Initialization arguments (in a hash in first parameter): // // * model: recline.Model.Dataset -// * config: (optional) graph configuration hash of form: +// * state: (optional) configuration hash of form: // // { // group: {column name for x-axis}, @@ -86,7 +86,7 @@ my.FlotGraph = Backbone.View.extend({ 'click .action-toggle-help': 'toggleHelp' }, - initialize: function(options, config) { + initialize: function(options) { var self = this; this.el = $(this.el); _.bindAll(this, 'render', 'redraw'); @@ -96,18 +96,14 @@ my.FlotGraph = Backbone.View.extend({ this.model.fields.bind('add', this.render); this.model.currentDocuments.bind('add', this.redraw); this.model.currentDocuments.bind('reset', this.redraw); - var configFromHash = my.parseHashQueryString().graph; - if (configFromHash) { - configFromHash = JSON.parse(configFromHash); - } - this.chartConfig = _.extend({ + var stateData = _.extend({ group: null, series: [], graphType: 'lines-and-points' }, - configFromHash, - config - ); + options.state + ); + this.state = new recline.Model.ObjectState(stateData); this.render(); }, @@ -129,13 +125,12 @@ my.FlotGraph = Backbone.View.extend({ var series = this.$series.map(function () { return $(this).val(); }); - this.chartConfig.series = $.makeArray(series); - this.chartConfig.group = this.el.find('.editor-group select').val(); - this.chartConfig.graphType = this.el.find('.editor-type select').val(); - // update navigation - var qs = my.parseHashQueryString(); - qs.graph = JSON.stringify(this.chartConfig); - my.setHashQueryString(qs); + var updatedState = { + series: $.makeArray(series), + group: this.el.find('.editor-group select').val(), + graphType: this.el.find('.editor-type select').val() + }; + this.state.set(updatedState); this.redraw(); }, @@ -151,7 +146,7 @@ my.FlotGraph = Backbone.View.extend({ return; } var series = this.createSeries(); - var options = this.getGraphOptions(this.chartConfig.graphType); + var options = this.getGraphOptions(this.state.attributes.graphType); this.plot = $.plot(this.$graph, series, options); this.setupTooltips(); // create this.plot and cache it @@ -172,7 +167,7 @@ my.FlotGraph = Backbone.View.extend({ // special tickformatter to show labels rather than numbers var tickFormatter = function (val) { if (self.model.currentDocuments.models[val]) { - var out = self.model.currentDocuments.models[val].get(self.chartConfig.group); + var out = self.model.currentDocuments.models[val].get(self.state.attributes.group); // if the value was in fact a number we want that not the if (typeof(out) == 'number') { return val; @@ -255,14 +250,14 @@ my.FlotGraph = Backbone.View.extend({ var y = item.datapoint[1]; // convert back from 'index' value on x-axis (e.g. in cases where non-number values) if (self.model.currentDocuments.models[x]) { - x = self.model.currentDocuments.models[x].get(self.chartConfig.group); + x = self.model.currentDocuments.models[x].get(self.state.attributes.group); } else { x = x.toFixed(2); } y = y.toFixed(2); var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', { - group: self.chartConfig.group, + group: self.state.attributes.group, x: x, series: item.series.label, y: y @@ -280,25 +275,23 @@ my.FlotGraph = Backbone.View.extend({ createSeries: function () { var self = this; var series = []; - if (this.chartConfig) { - $.each(this.chartConfig.series, function (seriesIndex, field) { - var points = []; - $.each(self.model.currentDocuments.models, function (index, doc) { - var x = doc.get(self.chartConfig.group); - var y = doc.get(field); - if (typeof x === 'string') { - x = index; - } - // horizontal bar chart - if (self.chartConfig.graphType == 'bars') { - points.push([y, x]); - } else { - points.push([x, y]); - } - }); - series.push({data: points, label: field}); + $.each(this.state.attributes.series, function (seriesIndex, field) { + var points = []; + $.each(self.model.currentDocuments.models, function (index, doc) { + var x = doc.get(self.state.attributes.group); + var y = doc.get(field); + if (typeof x === 'string') { + x = index; + } + // horizontal bar chart + if (self.state.attributes.graphType == 'bars') { + points.push([y, x]); + } else { + points.push([x, y]); + } }); - } + series.push({data: points, label: field}); + }); return series; }, diff --git a/src/view.js b/src/view.js index 5648af28..53b7a859 100644 --- a/src/view.js +++ b/src/view.js @@ -155,11 +155,7 @@ my.DataExplorer = Backbone.View.extend({ // note this.model and dataset returned are the same this.model.fetch() .done(function(dataset) { - var queryState = my.parseHashQueryString().reclineQuery; - if (queryState) { - queryState = JSON.parse(queryState); - } - self.model.query(queryState); + self.model.query(self.state.get('query')); }) .fail(function(error) { my.notify(error.message, {category: 'error', persist: true}); @@ -238,16 +234,33 @@ my.DataExplorer = Backbone.View.extend({ _setupState: function(initialState) { var self = this; + var qs = my.parseHashQueryString(); + var query = qs.reclineQuery; + query = query ? JSON.parse(query) : self.model.queryState.toJSON(); + // backwards compatability (now named view-graph but was named graph) + var graphState = qs['view-graph'] || qs.graph; + graphState = graphState ? JSON.parse(graphState) : {}; var stateData = _.extend({ readOnly: false, - query: self.model.queryState.toJSON(), + query: query, + 'view-graph': graphState, currentView: null }, initialState); this.state.set(stateData); + + // now do updates based on state if (this.state.get('readOnly')) { this.setReadOnly(); } + _.each(this.pageViews, function(pageView) { + var viewId = 'view-' + pageView.id; + if (viewId in self.state.attributes) { + pageView.view.state.set(self.state.get(viewId)); + } + }); + + // bind for changes state in associated objects this.model.queryState.bind('change', function() { self.state.set({queryState: self.model.queryState.toJSON()}); }); diff --git a/test/base.js b/test/base.js index 2d8df709..30b2960b 100644 --- a/test/base.js +++ b/test/base.js @@ -14,3 +14,14 @@ var Fixture = { } }; +function assertPresent(selector, el) { + var found = el ? $(el).find(selector) : $(selector); + ok(found.length > 0); +} + +function assertNotPresent(selector, el) { + var found = el ? $(el).find(selector) : $(selector); + ok(found.length > 0); + equal(found.length, 0); +} + diff --git a/test/index.html b/test/index.html index 8131c65c..82751d57 100644 --- a/test/index.html +++ b/test/index.html @@ -32,7 +32,9 @@ + + diff --git a/test/view-graph.test.js b/test/view-graph.test.js new file mode 100644 index 00000000..122937f9 --- /dev/null +++ b/test/view-graph.test.js @@ -0,0 +1,13 @@ +module("View - FlotGraph"); + +test('basics', function () { + var dataset = Fixture.getDataset(); + var view = new recline.View.FlotGraph({ + model: dataset + }); + $('.fixtures').append(view.el); + equal(view.state.get('graphType'), 'lines-and-points'); + // view will auto render ... + assertPresent('.editor', view.el); + view.remove(); +}); diff --git a/test/view-grid.test.js b/test/view-grid.test.js index 19031458..8a723c89 100644 --- a/test/view-grid.test.js +++ b/test/view-grid.test.js @@ -2,16 +2,6 @@ module("View - DataGrid"); -function assertPresent(selector) { - var found = $(selector); - ok(found.length > 0); -} - -function assertNotPresent(selector) { - var found = $(selector); - equal(found.length, 0); -} - test('menu - hideColumn', function () { var dataset = Fixture.getDataset(); var view = new recline.View.DataGrid({ diff --git a/test/view.test.js b/test/view.test.js index afa2f943..6a898989 100644 --- a/test/view.test.js +++ b/test/view.test.js @@ -36,7 +36,10 @@ test('initialize state', function () { var explorer = new recline.View.DataExplorer({ model: dataset, state: { - readOnly: true + readOnly: true, + 'view-grid': { + hiddenFields: ['x'] + } } }); var state = explorer.getState();