diff --git a/css/flotr2.css b/css/flotr2.css
deleted file mode 100644
index 7b1c085b..00000000
--- a/css/flotr2.css
+++ /dev/null
@@ -1,36 +0,0 @@
-.recline-graph .graph {
- height: 500px;
-}
-
-.recline-graph .legend table {
- width: auto;
- margin-bottom: 0;
-}
-
-.recline-graph .legend td {
- padding: 5px;
- line-height: 13px;
-}
-
-.recline-graph .graph .alert {
- width: 450px;
-}
-
-.flotr-mouse-value {
- background-color: #FEE !important;
- color: #000000 !important;
- opacity: 0.8 !important;
- border: 1px solid #fdd !important;
-}
-
-.flotr-legend {
- border: none !important;
-}
-
-.flotr-legend-bg {
- display: none;
-}
-
-.flotr-legend-color-box {
- padding: 5px;
-}
diff --git a/src/view.flotr2.js b/src/view.flotr2.js
deleted file mode 100644
index 9259e046..00000000
--- a/src/view.flotr2.js
+++ /dev/null
@@ -1,462 +0,0 @@
-/*jshint multistr:true */
-
-this.recline = this.recline || {};
-this.recline.View = this.recline.View || {};
-
-(function($, my) {
-
-// ## Graph view for a Dataset using Flotr2 graphing library.
-//
-// Initialization arguments (in a hash in first parameter):
-//
-// * model: recline.Model.Dataset
-// * state: (optional) configuration hash of form:
-//
-// {
-// group: {column name for x-axis},
-// series: [{column name for series A}, {column name series B}, ... ],
-// graphType: 'line',
-// graphOptions: {custom [Flotr2 options](http://www.humblesoftware.com/flotr2/documentation#configuration)}
-// }
-//
-// NB: should *not* provide an el argument to the view but must let the view
-// generate the element itself (you can then append view.el to the DOM.
-my.Flotr2 = Backbone.View.extend({
- template: ' \
-
\
-
\
-
\
-
Hey there!
\
-
There\'s no graph here yet because we don\'t know what fields you\'d like to see plotted.
\
-
Please tell us by using the menu on the right and a graph will automatically appear.
\
-
\
-
\
-
\
-',
-
- initialize: function(options) {
- var self = this;
- this.graphColors = ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"];
-
- this.el = $(this.el);
- _.bindAll(this, 'render', 'redraw');
- 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);
- var stateData = _.extend({
- group: null,
- // so that at least one series chooser box shows up
- series: [],
- graphType: 'lines-and-points'
- },
- options.state
- );
- this.state = new recline.Model.ObjectState(stateData);
- this.editor = new my.Flotr2Controls({
- model: this.model,
- state: this.state.toJSON()
- });
- this.editor.state.bind('change', function() {
- self.state.set(self.editor.state.toJSON());
- self.redraw();
- });
- 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');
- return this;
- },
-
- redraw: function() {
- // There appear to be issues generating a Flotr2 graph if either:
-
- // * The relevant div that graph attaches to his hidden at the moment of creating the plot -- Flotr2 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]);
- if ((!areWeVisible || this.model.records.length === 0)) {
- this.needToRedraw = true;
- return;
- }
-
- // check we have something to plot
- if (this.state.get('group') && this.state.get('series')) {
- // faff around with width because flot draws axes *outside* of the element width which means graph can get push down as it hits element next to it
- this.$graph.width(this.el.width() - 20);
- var series = this.createSeries();
- var options = this.getGraphOptions(this.state.attributes.graphType);
- this.plot = Flotr.draw(this.$graph.get(0), series, options);
- }
- },
-
- show: function() {
- // because we cannot redraw when hidden we may need to when becoming visible
- if (this.needToRedraw) {
- this.redraw();
- }
- },
-
- // ### getGraphOptions
- //
- // Get options for Flotr2 Graph
- //
- // needs to be function as can depend on state
- //
- // @param typeId graphType id (lines, lines-and-points etc)
- getGraphOptions: function(typeId) {
- var self = this;
-
- var tickFormatter = function (x) {
- return getFormattedX(x);
- };
-
- // infoboxes on mouse hover on points/bars etc
- var trackFormatter = function (obj) {
- var x = obj.x;
- var y = obj.y;
- // it's horizontal so we have to flip
- if (self.state.attributes.graphType === 'bars') {
- var _tmp = x;
- x = y;
- y = _tmp;
- }
-
- x = getFormattedX(x);
-
- var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', {
- group: self.state.attributes.group,
- x: x,
- series: obj.series.label,
- y: y
- });
-
- return content;
- };
-
- var getFormattedX = function (x) {
- var xfield = self.model.fields.get(self.state.attributes.group);
-
- // time series
- var xtype = xfield.get('type');
- var isDateTime = (xtype === 'date' || xtype === 'date-time' || xtype === 'time');
-
- if (self.model.records.models[parseInt(x)]) {
- x = self.model.records.models[parseInt(x)].get(self.state.attributes.group);
- if (isDateTime) {
- x = new Date(x).toLocaleDateString();
- }
- } else if (isDateTime) {
- x = new Date(parseInt(x)).toLocaleDateString();
- }
- return x;
- }
-
- var xaxis = {};
- xaxis.tickFormatter = tickFormatter;
-
- var yaxis = {};
- yaxis.autoscale = true;
- yaxis.autoscaleMargin = 0.02;
-
- var mouse = {};
- mouse.track = true;
- mouse.relative = true;
- mouse.trackFormatter = trackFormatter;
-
- var legend = {};
- legend.position = 'ne';
-
- // mouse.lineColor is set in createSeries
- var optionsPerGraphType = {
- lines: {
- legend: legend,
- colors: this.graphColors,
- lines: { show: true },
- xaxis: xaxis,
- yaxis: yaxis,
- mouse: mouse
- },
- points: {
- legend: legend,
- colors: this.graphColors,
- points: { show: true, hitRadius: 5 },
- xaxis: xaxis,
- yaxis: yaxis,
- mouse: mouse,
- grid: { hoverable: true, clickable: true }
- },
- 'lines-and-points': {
- legend: legend,
- colors: this.graphColors,
- points: { show: true, hitRadius: 5 },
- lines: { show: true },
- xaxis: xaxis,
- yaxis: yaxis,
- mouse: mouse,
- grid: { hoverable: true, clickable: true }
- },
- bars: {
- legend: legend,
- colors: this.graphColors,
- lines: { show: false },
- xaxis: yaxis,
- yaxis: xaxis,
- mouse: {
- track: true,
- relative: true,
- trackFormatter: trackFormatter,
- fillColor: '#FFFFFF',
- fillOpacity: 0.3,
- position: 'e'
- },
- bars: {
- show: true,
- horizontal: true,
- shadowSize: 0,
- barWidth: 0.8
- }
- },
- columns: {
- legend: legend,
- colors: this.graphColors,
- lines: { show: false },
- xaxis: xaxis,
- yaxis: yaxis,
- mouse: {
- track: true,
- relative: true,
- trackFormatter: trackFormatter,
- fillColor: '#FFFFFF',
- fillOpacity: 0.3,
- position: 'n'
- },
- bars: {
- show: true,
- horizontal: false,
- shadowSize: 0,
- barWidth: 0.8
- }
- },
- grid: { hoverable: true, clickable: true }
- };
-
- if (self.state.get('graphOptions')){
- return _.extend(optionsPerGraphType[typeId],
- self.state.get('graphOptions')
- )
- }else{
- return optionsPerGraphType[typeId];
- }
- },
-
- createSeries: function() {
- var self = this;
- var series = [];
- _.each(this.state.attributes.series, function(field) {
- var points = [];
- _.each(self.model.records.models, function(doc, index) {
- var xfield = self.model.fields.get(self.state.attributes.group);
- var x = doc.getFieldValue(xfield);
-
- // time series
- var xtype = xfield.get('type');
- var isDateTime = (xtype === 'date' || xtype === 'date-time' || xtype === 'time');
-
- if (isDateTime) {
- // datetime
- if (self.state.attributes.graphType != 'bars' && self.state.attributes.graphType != 'columns') {
- // not bar or column
- x = new Date(x).getTime();
- } else {
- // bar or column
- x = index;
- }
- } else if (typeof x === 'string') {
- // string
- x = parseFloat(x);
- if (isNaN(x)) {
- x = index;
- }
- }
-
- var yfield = self.model.fields.get(field);
- var y = doc.getFieldValue(yfield);
-
- // horizontal bar chart
- if (self.state.attributes.graphType == 'bars') {
- points.push([y, x]);
- } else {
- points.push([x, y]);
- }
- });
- series.push({data: points, label: field, mouse:{lineColor: self.graphColors[series.length]}});
- });
- return series;
- }
-});
-
-my.Flotr2Controls = Backbone.View.extend({
- className: "editor",
- template: ' \
- \
-',
- templateSeriesEditor: ' \
- \
-
\
-
\
- \
-
\
-
\
- ',
- events: {
- 'change form select': 'onEditorSubmit',
- 'click .editor-add': '_onAddSeries',
- 'click .action-remove-series': 'removeSeries'
- },
-
- 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.state = new recline.Model.ObjectState(options.state);
- this.render();
- },
-
- render: function() {
- var self = this;
- var tmplData = this.model.toTemplateJSON();
- var htmls = Mustache.render(this.template, tmplData);
- this.el.html(htmls);
-
- // 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'));
- }
- // ensure at least one series box shows up
- var tmpSeries = [""];
- if (this.state.get('series').length > 0) {
- tmpSeries = this.state.get('series');
- }
- _.each(tmpSeries, 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');
- var $editor = this;
- 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()
- };
- this.state.set(updatedState);
- },
-
- // Public: Adds a new empty series select box to the editor.
- //
- // @param [int] idx index of this series in the list of series
- //
- // Returns itself.
- addSeries: function (idx) {
- var data = _.extend({
- seriesIndex: idx,
- seriesName: String.fromCharCode(idx + 64 + 1)
- }, this.model.toTemplateJSON());
-
- var htmls = Mustache.render(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.
- removeSeries: function (e) {
- e.preventDefault();
- var $el = $(e.target);
- $el.parent().parent().remove();
- this.onEditorSubmit();
- }
-});
-
-})(jQuery, recline.View);
-
diff --git a/test/view.flotr2.test.js b/test/view.flotr2.test.js
deleted file mode 100644
index 89edfada..00000000
--- a/test/view.flotr2.test.js
+++ /dev/null
@@ -1,86 +0,0 @@
-module("View - Flotr2");
-
-test('basics', function () {
- var dataset = Fixture.getDataset();
- var view = new recline.View.Flotr2({
- model: dataset
- });
- $('.fixtures').append(view.el);
- equal(view.state.get('graphType'), 'lines-and-points');
- // view will auto render ...
- assertPresent('.editor', view.elSidebar);
- view.remove();
-});
-
-test('initialize', function () {
- var dataset = Fixture.getDataset();
- var view = new recline.View.Flotr2({
- 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.elSidebar.find('.editor-type select').val(), 'lines');
- equal(view.elSidebar.find('.editor-group select').val(), 'x');
- var out = _.map(view.elSidebar.find('.editor-series select'), function($el) {
- return $($el).val();
- });
- deepEqual(out, ['y', 'z']);
-
- view.remove();
-});
-
-test('dates in graph view', function () {
- expect(0);
- var dataset = Fixture.getDataset();
- var view = new recline.View.Flotr2({
- model: dataset,
- state: {
- 'graphType': 'lines',
- 'group': 'date',
- 'series': ['y', 'z']
- }
- });
- $('.fixtures').append(view.el);
-
- view.remove();
-});
-
-test('Flotr2Controls basics', function () {
- var dataset = Fixture.getDataset();
- var view = new recline.View.Flotr2Controls({
- model: dataset,
- state: {
- graphType: 'bars',
- series: []
- }
- });
- $('.fixtures').append(view.el);
- equal(view.state.get('graphType'), 'bars');
- // view will auto render ...
- assertPresent('.editor', view.el);
- view.remove();
-});
-
-test('Overriding graph options', function () {
- var dataset = Fixture.getDataset();
- var randomWidth = Math.random();
- var view = new recline.View.Flotr2({
- model: dataset,
- state: {
- 'graphType': 'bars',
- 'group': 'date',
- 'series': ['y', 'z'],
- 'graphOptions': { bars: {barWidth: randomWidth}}
- }
- });
- equal(view.getGraphOptions('bars').bars.barWidth, randomWidth)
- view.remove();
-});