[#88,refactor/state,api-change][m]: FlotGraph now uses state plus DataExplorer takes care of parsing state from Hash.

* First test for FlotGraph view (#45)
* Move convenience functions for testing present of elements to test/base.js from view-grid.test.js
This commit is contained in:
Rufus Pollock
2012-04-15 15:03:02 +01:00
parent 8f33235933
commit 4281801120
7 changed files with 82 additions and 57 deletions

View File

@@ -7,10 +7,10 @@ this.recline.View = this.recline.View || {};
// ## Graph view for a Dataset using Flot graphing library. // ## Graph view for a Dataset using Flot graphing library.
// //
// Initialization arguments: // Initialization arguments (in a hash in first parameter):
// //
// * model: recline.Model.Dataset // * model: recline.Model.Dataset
// * config: (optional) graph configuration hash of form: // * state: (optional) configuration hash of form:
// //
// { // {
// group: {column name for x-axis}, // group: {column name for x-axis},
@@ -86,7 +86,7 @@ my.FlotGraph = Backbone.View.extend({
'click .action-toggle-help': 'toggleHelp' 'click .action-toggle-help': 'toggleHelp'
}, },
initialize: function(options, config) { initialize: function(options) {
var self = this; var self = this;
this.el = $(this.el); this.el = $(this.el);
_.bindAll(this, 'render', 'redraw'); _.bindAll(this, 'render', 'redraw');
@@ -96,18 +96,14 @@ my.FlotGraph = Backbone.View.extend({
this.model.fields.bind('add', this.render); this.model.fields.bind('add', this.render);
this.model.currentDocuments.bind('add', this.redraw); this.model.currentDocuments.bind('add', this.redraw);
this.model.currentDocuments.bind('reset', this.redraw); this.model.currentDocuments.bind('reset', this.redraw);
var configFromHash = my.parseHashQueryString().graph; var stateData = _.extend({
if (configFromHash) {
configFromHash = JSON.parse(configFromHash);
}
this.chartConfig = _.extend({
group: null, group: null,
series: [], series: [],
graphType: 'lines-and-points' graphType: 'lines-and-points'
}, },
configFromHash, options.state
config );
); this.state = new recline.Model.ObjectState(stateData);
this.render(); this.render();
}, },
@@ -129,13 +125,12 @@ my.FlotGraph = Backbone.View.extend({
var series = this.$series.map(function () { var series = this.$series.map(function () {
return $(this).val(); return $(this).val();
}); });
this.chartConfig.series = $.makeArray(series); var updatedState = {
this.chartConfig.group = this.el.find('.editor-group select').val(); series: $.makeArray(series),
this.chartConfig.graphType = this.el.find('.editor-type select').val(); group: this.el.find('.editor-group select').val(),
// update navigation graphType: this.el.find('.editor-type select').val()
var qs = my.parseHashQueryString(); };
qs.graph = JSON.stringify(this.chartConfig); this.state.set(updatedState);
my.setHashQueryString(qs);
this.redraw(); this.redraw();
}, },
@@ -151,7 +146,7 @@ my.FlotGraph = Backbone.View.extend({
return; return;
} }
var series = this.createSeries(); 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.plot = $.plot(this.$graph, series, options);
this.setupTooltips(); this.setupTooltips();
// create this.plot and cache it // create this.plot and cache it
@@ -172,7 +167,7 @@ my.FlotGraph = Backbone.View.extend({
// special tickformatter to show labels rather than numbers // special tickformatter to show labels rather than numbers
var tickFormatter = function (val) { var tickFormatter = function (val) {
if (self.model.currentDocuments.models[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 the value was in fact a number we want that not the
if (typeof(out) == 'number') { if (typeof(out) == 'number') {
return val; return val;
@@ -255,14 +250,14 @@ my.FlotGraph = Backbone.View.extend({
var y = item.datapoint[1]; var y = item.datapoint[1];
// convert back from 'index' value on x-axis (e.g. in cases where non-number values) // convert back from 'index' value on x-axis (e.g. in cases where non-number values)
if (self.model.currentDocuments.models[x]) { 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 { } else {
x = x.toFixed(2); x = x.toFixed(2);
} }
y = y.toFixed(2); y = y.toFixed(2);
var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', { var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', {
group: self.chartConfig.group, group: self.state.attributes.group,
x: x, x: x,
series: item.series.label, series: item.series.label,
y: y y: y
@@ -280,25 +275,23 @@ my.FlotGraph = Backbone.View.extend({
createSeries: function () { createSeries: function () {
var self = this; var self = this;
var series = []; var series = [];
if (this.chartConfig) { $.each(this.state.attributes.series, function (seriesIndex, field) {
$.each(this.chartConfig.series, function (seriesIndex, field) { var points = [];
var points = []; $.each(self.model.currentDocuments.models, function (index, doc) {
$.each(self.model.currentDocuments.models, function (index, doc) { var x = doc.get(self.state.attributes.group);
var x = doc.get(self.chartConfig.group); var y = doc.get(field);
var y = doc.get(field); if (typeof x === 'string') {
if (typeof x === 'string') { x = index;
x = index; }
} // horizontal bar chart
// horizontal bar chart if (self.state.attributes.graphType == 'bars') {
if (self.chartConfig.graphType == 'bars') { points.push([y, x]);
points.push([y, x]); } else {
} else { points.push([x, y]);
points.push([x, y]); }
}
});
series.push({data: points, label: field});
}); });
} series.push({data: points, label: field});
});
return series; return series;
}, },

View File

@@ -155,11 +155,7 @@ my.DataExplorer = Backbone.View.extend({
// note this.model and dataset returned are the same // note this.model and dataset returned are the same
this.model.fetch() this.model.fetch()
.done(function(dataset) { .done(function(dataset) {
var queryState = my.parseHashQueryString().reclineQuery; self.model.query(self.state.get('query'));
if (queryState) {
queryState = JSON.parse(queryState);
}
self.model.query(queryState);
}) })
.fail(function(error) { .fail(function(error) {
my.notify(error.message, {category: 'error', persist: true}); my.notify(error.message, {category: 'error', persist: true});
@@ -238,16 +234,33 @@ my.DataExplorer = Backbone.View.extend({
_setupState: function(initialState) { _setupState: function(initialState) {
var self = this; 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({ var stateData = _.extend({
readOnly: false, readOnly: false,
query: self.model.queryState.toJSON(), query: query,
'view-graph': graphState,
currentView: null currentView: null
}, },
initialState); initialState);
this.state.set(stateData); this.state.set(stateData);
// now do updates based on state
if (this.state.get('readOnly')) { if (this.state.get('readOnly')) {
this.setReadOnly(); 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() { this.model.queryState.bind('change', function() {
self.state.set({queryState: self.model.queryState.toJSON()}); self.state.set({queryState: self.model.queryState.toJSON()});
}); });

View File

@@ -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);
}

View File

@@ -32,7 +32,9 @@
<script type="text/javascript" src="../src/view.js"></script> <script type="text/javascript" src="../src/view.js"></script>
<script type="text/javascript" src="../src/view-grid.js"></script> <script type="text/javascript" src="../src/view-grid.js"></script>
<script type="text/javascript" src="../src/view-transform-dialog.js"></script> <script type="text/javascript" src="../src/view-transform-dialog.js"></script>
<script type="text/javascript" src="../src/view-flot-graph.js"></script>
<script type="text/javascript" src="view-grid.test.js"></script> <script type="text/javascript" src="view-grid.test.js"></script>
<script type="text/javascript" src="view-graph.test.js"></script>
<script type="text/javascript" src="view.test.js"></script> <script type="text/javascript" src="view.test.js"></script>
<script type="text/javascript" src="util.test.js"></script> <script type="text/javascript" src="util.test.js"></script>
</head> </head>

13
test/view-graph.test.js Normal file
View File

@@ -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();
});

View File

@@ -2,16 +2,6 @@
module("View - DataGrid"); 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 () { test('menu - hideColumn', function () {
var dataset = Fixture.getDataset(); var dataset = Fixture.getDataset();
var view = new recline.View.DataGrid({ var view = new recline.View.DataGrid({

View File

@@ -36,7 +36,10 @@ test('initialize state', function () {
var explorer = new recline.View.DataExplorer({ var explorer = new recline.View.DataExplorer({
model: dataset, model: dataset,
state: { state: {
readOnly: true readOnly: true,
'view-grid': {
hiddenFields: ['x']
}
} }
}); });
var state = explorer.getState(); var state = explorer.getState();