diff --git a/demo/js/app.js b/demo/js/app.js index 1cbab287..9afd6acf 100755 --- a/demo/js/app.js +++ b/demo/js/app.js @@ -29,8 +29,10 @@ $(function() { // again and again function createExplorer(dataset) { // remove existing data explorer view + var reload = false; if (window.dataExplorer) { window.dataExplorer.remove(); + reload = true; } window.dataExplorer = null; var $el = $('
'); @@ -43,8 +45,10 @@ function createExplorer(dataset) { }); // HACK (a bit). Issue is that Backbone will not trigger the route // if you are already at that location so we have to make sure we genuinely switch - window.dataExplorer.router.navigate('graph'); - window.dataExplorer.router.navigate('', true); + if (reload) { + window.dataExplorer.router.navigate('graph'); + window.dataExplorer.router.navigate('', true); + } } // convenience function @@ -77,14 +81,14 @@ function localDataset() { , name: '1-my-test-dataset' , id: datasetId }, - fields: [{id: 'x'}, {id: 'y'}, {id: 'z'}], + fields: [{id: 'x'}, {id: 'y'}, {id: 'z'}, {id: 'label'}], documents: [ - {id: 0, x: 1, y: 2, z: 3} - , {id: 1, x: 2, y: 4, z: 6} - , {id: 2, x: 3, y: 6, z: 9} - , {id: 3, x: 4, y: 8, z: 12} - , {id: 4, x: 5, y: 10, z: 15} - , {id: 5, x: 6, y: 12, z: 18} + {id: 0, x: 1, y: 2, z: 3, label: 'first'} + , {id: 1, x: 2, y: 4, z: 6, label: 'second'} + , {id: 2, x: 3, y: 6, z: 9, label: 'third'} + , {id: 3, x: 4, y: 8, z: 12, label: 'fourth'} + , {id: 4, x: 5, y: 10, z: 15, label: 'fifth'} + , {id: 5, x: 6, y: 12, z: 18, label: 'sixth'} ] }; var backend = new recline.Backend.Memory(); diff --git a/docs/model.html b/docs/model.html index ae7bcb5c..3c926946 100644 --- a/docs/model.html +++ b/docs/model.html @@ -3,15 +3,14 @@ (function($, my) {

A Dataset model

-

A model must have the following (Backbone) attributes:

+

A model has the following (non-Backbone) attributes:

my.Dataset = Backbone.Model.extend({
   __type__: 'Dataset',
   initialize: function(model, backend) {
diff --git a/src/model.js b/src/model.js
index 4f5f5ed7..207a9872 100644
--- a/src/model.js
+++ b/src/model.js
@@ -6,14 +6,13 @@ this.recline.Model = this.recline.Model || {};
 
 // ## A Dataset model
 //
-// A model must have the following (Backbone) attributes:
+// A model has the following (non-Backbone) attributes:
 //
 // * fields: (aka columns) is a FieldList listing all the fields on this
-//   Dataset (this can be set explicitly, or, on fetch() of Dataset
-//   information from the backend, or as is perhaps most common on the first
-//   query)
-// * currentDocuments: a DocumentList containing the Documents we have currently loaded for viewing (you update currentDocuments by calling getRows)
-// * docCount: total number of documents in this dataset (obtained on a fetch for this Dataset)
+//   Dataset (this can be set explicitly, or, will be set by Dataset.fetch() or Dataset.query()
+// * currentDocuments: a DocumentList containing the Documents we have
+//   currently loaded for viewing (you update currentDocuments by calling query)
+// * docCount: total number of documents in this dataset
 my.Dataset = Backbone.Model.extend({
   __type__: 'Dataset',
   initialize: function(model, backend) {
diff --git a/src/view-flot-graph.js b/src/view-flot-graph.js
index 5429eed4..5b6aee18 100644
--- a/src/view-flot-graph.js
+++ b/src/view-flot-graph.js
@@ -149,11 +149,9 @@ my.FlotGraph = Backbone.View.extend({
       return
     }
     var series = this.createSeries();
-    var options = this.graphOptions[this.chartConfig.graphType];
+    var options = this.getGraphOptions(this.chartConfig.graphType);
     this.plot = $.plot(this.$graph, series, options);
-    if (this.chartConfig.graphType in { 'points': '', 'lines-and-points': '' }) {
-      this.setupTooltips();
-    }
+    this.setupTooltips();
     // create this.plot and cache it
 //    if (!this.plot) {
 //      this.plot = $.plot(this.$graph, series, options);
@@ -166,40 +164,63 @@ my.FlotGraph = Backbone.View.extend({
 //    }
   },
 
-  graphOptions: { 
-    lines: {
-       series: { 
-         lines: { show: true }
-       }
-    }
-    , points: {
-      series: {
-        points: { show: true }
-      },
-      grid: { hoverable: true, clickable: true }
-    }
-    , 'lines-and-points': {
-      series: {
-        points: { show: true },
-        lines: { show: true }
-      },
-      grid: { hoverable: true, clickable: true }
-    }
-    , bars: {
-      series: {
-        lines: {show: false},
-        bars: {
-          show: true,
-          barWidth: 1,
-          align: "left",
-          fill: true
+  // needs to be function as can depend on state
+  getGraphOptions: function(typeId) { 
+    var self = this;
+    var tickFormatter = function (val) {
+      if (self.model.currentDocuments.models[val]) {
+        var out = self.model.currentDocuments.models[val].get(self.chartConfig.group);
+        // if the x-axis value was in fact a number we want that not the 
+        if (typeof(out) == 'number') {
+          return val;
+        } else {
+          return out;
+        }
+      }
+      return val;
+    }
+    // TODO: we should really use tickFormatter and 1 interval ticks if (and
+    // only if) x-axis values are non-numeric
+    // However, that is non-trivial to work out from a dataset (datasets may
+    // have no field type info). Thus at present we only do this for bars.
+    var options = { 
+      lines: {
+         series: { 
+           lines: { show: true }
+         }
+      }
+      , points: {
+        series: {
+          points: { show: true }
+        },
+        grid: { hoverable: true, clickable: true }
+      }
+      , 'lines-and-points': {
+        series: {
+          points: { show: true },
+          lines: { show: true }
+        },
+        grid: { hoverable: true, clickable: true },
+      }
+      , bars: {
+        series: {
+          lines: {show: false},
+          bars: {
+            show: true,
+            barWidth: 1,
+            align: "center",
+            fill: true
+          }
+        },
+        grid: { hoverable: true, clickable: true },
+        xaxis: {
+          tickSize: 1,
+          tickLength: 1,
+          tickFormatter: tickFormatter
         }
-      },
-      xaxis: {
-        tickSize: 1,
-        tickLength: 1,
       }
     }
+    return options[typeId];
   },
 
   setupTooltips: function() {
@@ -220,12 +241,19 @@ my.FlotGraph = Backbone.View.extend({
     var previousPoint = null;
     this.$graph.bind("plothover", function (event, pos, item) {
       if (item) {
-        if (previousPoint != item.dataIndex) {
-          previousPoint = item.dataIndex;
+        if (previousPoint != item.datapoint) {
+          previousPoint = item.datapoint;
           
           $("#flot-tooltip").remove();
-          var x = item.datapoint[0].toFixed(2),
-              y = item.datapoint[1].toFixed(2);
+          var x = item.datapoint[0];
+          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);
+          } else {
+            x = x.toFixed(2);
+          }
+          y = y.toFixed(2);
           
           var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', {
             group: self.chartConfig.group,