[#85,view-graph][m]: graph controls are now correctly configure themselves from loaded state.

* Also heavily refactor to have a cleaner and better code e.g. using templating to add new series.
This commit is contained in:
Rufus Pollock 2012-04-25 22:12:42 +01:00
parent dd3b17e3bb
commit 82ca51a0b6
3 changed files with 94 additions and 46 deletions

View File

@ -30,7 +30,11 @@ var ExplorerApp = Backbone.View.extend({
}
}
var dataset = null;
if (state.dataset || state.url) {
if (
(state.dataset || state.url) &&
// special cases for demo / memory dataset
!(state.url === 'demo' || state.backend === 'memory'))
{
dataset = recline.Model.Dataset.restore(state);
} else {
dataset = localDataset();

View File

@ -48,22 +48,13 @@ my.Graph = Backbone.View.extend({
<label>Group Column (x-axis)</label> \
<div class="input editor-group"> \
<select> \
<option value="">Please choose ...</option> \
{{#fields}} \
<option value="{{id}}">{{label}}</option> \
{{/fields}} \
</select> \
</div> \
<div class="editor-series-group"> \
<div class="editor-series"> \
<label>Series <span>A (y-axis)</span></label> \
<div class="input"> \
<select> \
{{#fields}} \
<option value="{{id}}">{{label}}</option> \
{{/fields}} \
</select> \
</div> \
</div> \
</div> \
</div> \
<div class="editor-buttons"> \
@ -78,10 +69,25 @@ my.Graph = Backbone.View.extend({
<div class="panel graph"></div> \
</div> \
',
templateSeriesEditor: ' \
<div class="editor-series js-series-{{seriesIndex}}"> \
<label>Series <span>{{seriesName}} (y-axis)</span> \
[<a href="#remove" class="action-remove-series">Remove</a>] \
</label> \
<div class="input"> \
<select> \
<option value="">Please choose ...</option> \
{{#fields}} \
<option value="{{id}}">{{label}}</option> \
{{/fields}} \
</select> \
</div> \
</div> \
',
events: {
'change form select': 'onEditorSubmit',
'click .editor-add': 'addSeries',
'click .editor-add': '_onAddSeries',
'click .action-remove-series': 'removeSeries',
'click .action-toggle-help': 'toggleHelp'
},
@ -98,7 +104,8 @@ my.Graph = Backbone.View.extend({
this.model.currentDocuments.bind('reset', this.redraw);
var stateData = _.extend({
group: null,
series: [],
// so that at least one series chooser box shows up
series: [""],
graphType: 'lines-and-points'
},
options.state
@ -108,21 +115,45 @@ my.Graph = Backbone.View.extend({
},
render: function() {
htmls = $.mustache(this.template, this.model.toTemplateJSON());
var self = this;
var tmplData = this.model.toTemplateJSON();
var htmls = $.mustache(this.template, tmplData);
$(this.el).html(htmls);
// now set a load of stuff up
this.$graph = this.el.find('.panel.graph');
// for use later when adding additional series
// could be simpler just to have a common template!
this.$seriesClone = this.el.find('.editor-series').clone();
this._updateSeries();
// set up editor from state
if (this.state.get('graphType')) {
this._selectOption('.editor-type', this.state.get('graphType'));
}
if (this.state.get('group')) {
this._selectOption('.editor-group', this.state.get('group'));
}
_.each(this.state.get('series'), function(series, idx) {
self.addSeries(idx);
self._selectOption('.editor-series.js-series-' + idx, series);
});
return this;
},
// Private: Helper function to select an option from a select list
//
_selectOption: function(id,value){
var options = this.el.find(id + ' select > option');
if (options) {
options.each(function(opt){
if (this.value == value) {
$(this).attr('selected','selected');
return false;
}
});
}
},
onEditorSubmit: function(e) {
var select = this.el.find('.editor-group select');
$editor = this;
var series = this.$series.map(function () {
var $editor = this;
var $series = this.el.find('.editor-series select');
var series = $series.map(function () {
return $(this).val();
});
var updatedState = {
@ -297,23 +328,25 @@ my.Graph = Backbone.View.extend({
// Public: Adds a new empty series select box to the editor.
//
// All but the first select box will have a remove button that allows them
// to be removed.
// @param [int] idx index of this series in the list of series
//
// Returns itself.
addSeries: function (e) {
e.preventDefault();
var element = this.$seriesClone.clone(),
label = element.find('label'),
index = this.$series.length;
addSeries: function (idx) {
var data = _.extend({
seriesIndex: idx,
seriesName: String.fromCharCode(idx + 64 + 1),
}, this.model.toTemplateJSON());
this.el.find('.editor-series-group').append(element);
this._updateSeries();
label.append(' [<a href="#remove" class="action-remove-series">Remove</a>]');
label.find('span').text(String.fromCharCode(this.$series.length + 64));
var htmls = $.mustache(this.templateSeriesEditor, data);
this.el.find('.editor-series-group').append(htmls);
return this;
},
_onAddSeries: function(e) {
e.preventDefault();
this.addSeries(this.state.get('series').length);
},
// Public: Removes a series list item from the editor.
//
// Also updates the labels of the remaining series elements.
@ -321,26 +354,12 @@ my.Graph = Backbone.View.extend({
e.preventDefault();
var $el = $(e.target);
$el.parent().parent().remove();
this._updateSeries();
this.$series.each(function (index) {
if (index > 0) {
var labelSpan = $(this).prev().find('span');
labelSpan.text(String.fromCharCode(index + 65));
}
});
this.onEditorSubmit();
},
toggleHelp: function() {
this.el.find('.editor-info').toggleClass('editor-hide-info');
},
// Private: Resets the series property to reference the select elements.
//
// Returns itself.
_updateSeries: function () {
this.$series = this.el.find('.editor-series select');
}
});
})(jQuery, recline.View);

View File

@ -11,3 +11,28 @@ test('basics', function () {
assertPresent('.editor', view.el);
view.remove();
});
test('initialize', function () {
var dataset = Fixture.getDataset();
var view = new recline.View.Graph({
model: dataset,
state: {
'graphType': 'lines',
'group': 'x',
'series': ['y', 'z']
}
});
$('.fixtures').append(view.el);
equal(view.state.get('graphType'), 'lines');
deepEqual(view.state.get('series'), ['y', 'z']);
// check we have updated editor with state info
equal(view.el.find('.editor-type select').val(), 'lines');
equal(view.el.find('.editor-group select').val(), 'x');
var out = _.map(view.el.find('.editor-series select'), function($el) {
return $($el).val();
});
deepEqual(out, ['y', 'z']);
// view.remove();
});